aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/Sema.h6
-rw-r--r--lib/Sema/SemaExpr.cpp21
2 files changed, 27 insertions, 0 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 45d6b57437..84d4c598b2 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3485,6 +3485,12 @@ public:
/// CompatiblePointerDiscardsQualifiers - The assignment discards
/// c/v/r qualifiers, which we accept as an extension.
CompatiblePointerDiscardsQualifiers,
+
+ /// IncompatibleMultiPointerQualifiers - The assignment is between two
+ /// multi-level pointer types, and the qualifiers other than the first two
+ /// levels differ e.g. char ** -> const char **. We disallow this.
+ /// FIXME: GCC only warns for this - should we do the same?
+ IncompatibleMultiPointerQualifiers,
/// IncompatibleVectors - The assignment is between two vector types that
/// have the same size, which we accept as an extension.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9a549f1ff7..a09f6a9005 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3747,6 +3747,24 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
return ConvTy;
return IncompatiblePointerSign;
}
+
+ // If we are a multi-level pointer, it's possible that our issue is simply
+ // one of qualification - e.g. char ** -> const char ** is not allowed. If
+ // the eventual target type is the same and the pointers have the same
+ // level of indirection, this must be the issue.
+ if (lhptee->isPointerType() && rhptee->isPointerType()) {
+ do {
+ lhptee = lhptee->getAs<PointerType>()->getPointeeType();
+ rhptee = rhptee->getAs<PointerType>()->getPointeeType();
+
+ lhptee = Context.getCanonicalType(lhptee);
+ rhptee = Context.getCanonicalType(rhptee);
+ } while (lhptee->isPointerType() && rhptee->isPointerType());
+
+ if (lhptee.getUnqualifiedType() == rhptee.getUnqualifiedType())
+ return IncompatibleMultiPointerQualifiers;
+ }
+
// General pointer incompatibility takes priority over qualifiers.
return IncompatiblePointer;
}
@@ -6223,6 +6241,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
return false;
DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
break;
+ case IncompatibleMultiPointerQualifiers:
+ DiagKind = diag::err_multi_pointer_qualifier_mismatch;
+ break;
case IntToBlockPointer:
DiagKind = diag::err_int_to_block_pointer;
break;