"incompatible pointer types %2 %1, expected %0">;
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
"%2 %1 discards qualifiers, expected %0">;
+def err_multi_pointer_qualifier_mismatch : Error<
+ "%2, %0 and %1 have different qualifiers in a multi-level pointer chain">;
def warn_incompatible_vectors : Warning<
"incompatible vector types %2 %1, expected %0">,
InGroup<VectorConversions>, DefaultIgnore;
/// 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.
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;
}
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;