Index: test/SemaCXX/warn-cast-qual.cpp
===================================================================
--- test/SemaCXX/warn-cast-qual.cpp	(revision 0)
+++ test/SemaCXX/warn-cast-qual.cpp	(revision 0)
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -Wcast-qual -verify %s
+
+void test_c_style_cast()
+{
+  // C-style cast
+  const char* x = "foo";
+  char* y = (char *)x;  // expected-warning {{cast discards qualifiers from pointer target type}}
+  (void)y;
+}
+
+void test_explicit_const_cast()
+{
+  // no warning, explicit cast with const_cast
+  const char* x = "foo";
+  char* y2 = const_cast<char*>(x);
+  (void)y2;  
+}
+
+void test_functionsl_style_cast()
+{
+  // functional style cast
+  const char* x = "foo";
+  typedef char* PChar;
+  char* y3 = PChar(x); // expected-warning {{cast discards qualifiers from pointer target type}}
+  (void)y3;
+}
+
+void test_qual_introduce_unsafe()
+{
+  // const qualifier introduced unsafe way
+  char** x = 0;
+  const char** y = (const char**)x; // expected-warning {{cast discards qualifiers from pointer target type}}
+  (void)y;
+}
+
+void test_cast_no_warning()
+{
+  const char* x = 0;
+  const int* xx = (const int*)x; // no warning
+  (void)xx;
+
+  const char** z = 0;
+  const int** zz = (const int**)z; // no warning
+  (void)zz;
+}
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp	(revision 158800)
+++ lib/Sema/SemaChecking.cpp	(working copy)
@@ -4624,6 +4624,54 @@
     << TRange << Op->getSourceRange();
 }
 
+// CheckCastQual - Implements -Wcast-qual, which warn when a
+// pointer cast
+void Sema::CheckCastQual(Expr *Op, QualType T, SourceRange TRange)
+{
+  // Do nothing if we're ignoring -Wcast_qual (as is the default).
+  if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_qual,
+	                                          TRange.getBegin())
+        == DiagnosticsEngine::Ignored)
+	return;
+
+  // Require that the destination be a pointer type.
+  const PointerType *DestPtr = T->getAs<PointerType>();
+  if (!DestPtr) return;
+  // Require that the source be a pointer type.
+  const PointerType *SrcPtr = Op->getType()->getAs<PointerType>();
+  if (!SrcPtr) return;
+
+  // Get the pointee types
+  QualType SrcPointee = SrcPtr->getPointeeType();
+  QualType DestPointee = DestPtr->getPointeeType();
+
+  // Iterate through nested pointers if any presents, comparing cv-qualifiers
+  bool NestedPointeeMustBeConst = false;
+  while (isa<PointerType>(SrcPointee) && isa<PointerType>(DestPointee)) {
+    // Conditions are similar to C++03 [conv.qual]
+    if (SrcPointee.isMoreQualifiedThan(DestPointee))
+	  break;
+    if (DestPointee.isMoreQualifiedThan(SrcPointee))
+      NestedPointeeMustBeConst = true;
+    if (NestedPointeeMustBeConst && !SrcPointee.isConstQualified())
+      break;
+    // Get the next level pointee
+    SrcPtr = SrcPointee->getAs<PointerType>();
+    DestPtr = DestPointee->getAs<PointerType>();
+    SrcPointee = SrcPtr->getPointeeType();
+    DestPointee = DestPtr->getPointeeType();
+  }
+  // Process the last-level pointee
+  if (DestPointee.isMoreQualifiedThan(SrcPointee))
+    NestedPointeeMustBeConst = true;
+  // and generate warning if conditions triggered
+  if (SrcPointee.isMoreQualifiedThan(DestPointee) ||
+     (NestedPointeeMustBeConst && !SrcPointee.isConstQualified())) {
+    Diag(TRange.getBegin(), diag::warn_cast_qual)
+      << TRange << Op->getSourceRange();
+  }
+}
+
 static const Type* getElementType(const Expr *BaseExpr) {
   const Type* EltType = BaseExpr->getType().getTypePtr();
   if (EltType->isAnyPointerType())
Index: lib/Sema/SemaCast.cpp
===================================================================
--- lib/Sema/SemaCast.cpp	(revision 158800)
+++ lib/Sema/SemaCast.cpp	(working copy)
@@ -117,6 +117,10 @@
       Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
     }
 
+    void checkCastQual() {
+    	Self.CheckCastQual(SrcExpr.get(), DestType, OpRange);
+    }
+
     void checkObjCARCConversion(Sema::CheckedConversionKind CCK) {
       assert(Self.getLangOpts().ObjCAutoRefCount);
 
@@ -1877,8 +1881,11 @@
       diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
                       OpRange, SrcExpr.get(), DestType, ListInitialization);
     }
-  } else if (Kind == CK_BitCast) {
-    checkCastAlign();
+  } else {
+	  if (Kind == CK_BitCast) {
+        checkCastAlign();
+      }
+      checkCastQual();
   }
 
   // Clear out SrcExpr if there was a fatal error.
@@ -2065,6 +2072,8 @@
 
   if (Kind == CK_BitCast)
     checkCastAlign();
+
+  checkCastQual();
 }
 
 ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 158800)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -1248,6 +1248,7 @@
   void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
   void CheckShadow(Scope *S, VarDecl *D);
   void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
+  void CheckCastQual(Expr *Op, QualType T, SourceRange TRange);
   void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                     TypeSourceInfo *TInfo,
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 158800)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -1861,6 +1861,10 @@
   "cast from %0 to %1 increases required alignment from %2 to %3">,
   InGroup<CastAlign>, DefaultIgnore;
 
+def warn_cast_qual : Warning<
+  "cast discards qualifiers from pointer target type">,
+  InGroup<CastQual>, DefaultIgnore;
+
 def warn_attribute_ignored_for_field_of_type : Warning<
   "%0 attribute ignored for field of type %1">;
 def warn_transparent_union_attribute_field_size_align : Warning<
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td	(revision 158800)
+++ include/clang/Basic/DiagnosticGroups.td	(working copy)
@@ -37,7 +37,7 @@
 def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
 def CXXCompat: DiagGroup<"c++-compat">;
 def CastAlign : DiagGroup<"cast-align">;
-def : DiagGroup<"cast-qual">;
+def CastQual : DiagGroup<"cast-qual">;
 def : DiagGroup<"char-align">;
 def Comment : DiagGroup<"comment">;
 def : DiagGroup<"ctor-dtor-privacy">;
