]> granicus.if.org Git - clang/commitdiff
When computing Objective-C pointer conversions in C++, retain
authorDouglas Gregor <dgregor@apple.com>
Tue, 26 Apr 2011 23:16:46 +0000 (23:16 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 26 Apr 2011 23:16:46 +0000 (23:16 +0000)
the qualifiers (e.g., GC qualifiers) on the type we're converting
from, rather than just blindly adopting the qualifiers of the type
we're converting to or dropping qualifiers altogether.

As an added bonus, properly diagnose GC qualifier mismatches to
eliminate a crash in the overload resolution failure diagnostics.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130255 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
test/SemaObjCXX/overload-gc.mm [new file with mode: 0644]

index d690358070477e0002356fedc828447b4fae5166..f35d5c4b9bf18f2ff894acb7f6cc9c1b1edbd790 100644 (file)
@@ -1483,6 +1483,15 @@ def note_ovl_candidate_bad_addrspace : Note<"candidate "
     "constructor (inherited)}0%1 not viable: "
     "%select{%ordinal6|'this'}5 argument (%2) is in "
     "address space %3, but parameter must be in address space %4">;
+def note_ovl_candidate_bad_gc : Note<"candidate "
+    "%select{function|function|constructor|"
+    "function |function |constructor |"
+    "constructor (the implicit default constructor)|"
+    "constructor (the implicit copy constructor)|"
+    "function (the implicit copy assignment operator)|"
+    "constructor (inherited)}0%1 not viable: "
+    "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 "
+    "lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">;
 def note_ovl_candidate_bad_cvr_this : Note<"candidate "
     "%select{|function|||function||||"
     "function (the implicit copy assignment operator)|}0 not viable: "
index 6e6bf22be0b5bf2ab76554469741e525b4c68e1f..7eb89787f99b80276e7a4da1c6abb7800bd9b481 100644 (file)
@@ -1205,6 +1205,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
     // Pointer conversions (C++ 4.10).
     SCS.Second = ICK_Pointer_Conversion;
     SCS.IncompatibleObjC = IncompatibleObjC;
+    FromType = FromType.getUnqualifiedType();
   } else if (S.IsMemberPointerConversion(From, FromType, ToType,
                                          InOverloadResolution, FromType)) {
     // Pointer to member conversions (4.11).
@@ -1671,6 +1672,20 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
   
   return false;
 }
+/// \brief Adopt the given qualifiers for the given type.
+static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
+  Qualifiers TQs = T.getQualifiers();
+  
+  // Check whether qualifiers already match.
+  if (TQs == Qs)
+    return T;
+  
+  if (Qs.compatiblyIncludes(TQs))
+    return Context.getQualifiedType(T, Qs);
+  
+  return Context.getQualifiedType(T.getUnqualifiedType(), Qs);
+}
 
 /// isObjCPointerConversion - Determines whether this is an
 /// Objective-C pointer conversion. Subroutine of IsPointerConversion,
@@ -1681,6 +1696,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
   if (!getLangOptions().ObjC1)
     return false;
 
+  // The set of qualifiers on the type we're converting from.
+  Qualifiers FromQualifiers = FromType.getQualifiers();
+  
   // First, we handle all conversions on ObjC object pointer types.
   const ObjCObjectPointerType* ToObjCPtr =
     ToType->getAs<ObjCObjectPointerType>();
@@ -1694,10 +1712,11 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
                                        FromObjCPtr->getPointeeType()))
       return false;
 
+    // Check for compatible 
     // Objective C++: We're able to convert between "id" or "Class" and a
     // pointer to any interface (in both directions).
     if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
-      ConvertedType = ToType;
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
       return true;
     }
     // Conversions with Objective-C's id<...>.
@@ -1705,7 +1724,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
          ToObjCPtr->isObjCQualifiedIdType()) &&
         Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
                                                   /*compare=*/false)) {
-      ConvertedType = ToType;
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
       return true;
     }
     // Objective C++: We're able to convert from a pointer to an
@@ -1720,6 +1739,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
       ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
                                                    ToObjCPtr->getPointeeType(),
                                                          ToType, Context);
+      ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
       return true;
     }
 
@@ -1731,6 +1751,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
       ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
                                                    ToObjCPtr->getPointeeType(),
                                                          ToType, Context);
+      ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
       return true;
     }
   }
@@ -1743,7 +1764,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
     // Objective C++: We're able to convert from a pointer to any object
     // to a block pointer type.
     if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
-      ConvertedType = ToType;
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
       return true;
     }
     ToPointeeType = ToBlockPtr->getPointeeType();
@@ -1752,7 +1773,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
            ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
     // Objective C++: We're able to convert from a block pointer type to a
     // pointer to any object.
-    ConvertedType = ToType;
+    ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
     return true;
   }
   else
@@ -1775,6 +1796,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
     // We always complain about this conversion.
     IncompatibleObjC = true;
     ConvertedType = Context.getPointerType(ConvertedType);
+    ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
     return true;
   }
   // Allow conversion of pointee being objective-c pointer to another one;
@@ -1784,6 +1806,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
       isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
                               IncompatibleObjC)) {
     ConvertedType = Context.getPointerType(ConvertedType);
+    ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
     return true;
   }
 
@@ -1844,7 +1867,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
     if (HasObjCConversion) {
       // We had an Objective-C conversion. Allow this pointer
       // conversion, but complain about it.
-      ConvertedType = ToType;
+      ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
       IncompatibleObjC = true;
       return true;
     }
@@ -6541,6 +6564,17 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
       return;
     }
 
+    if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
+      << (unsigned) FnKind << FnDesc
+      << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+      << FromTy
+      << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
+      << (unsigned) isObjectArgument << I+1;
+      MaybeEmitInheritedConstructorNote(S, Fn);
+      return;
+    }
+
     unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
     assert(CVR && "unexpected qualifiers mismatch");
 
diff --git a/test/SemaObjCXX/overload-gc.mm b/test/SemaObjCXX/overload-gc.mm
new file mode 100644 (file)
index 0000000..afc6b96
--- /dev/null
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-gc -fobjc-nonfragile-abi -verify %s
+
+void f0(__weak id *); // expected-note{{candidate function not viable: 1st argument ('id *') has no lifetime, but parameter has __weak lifetime}}
+
+void test_f0(id *x) {
+  f0(x); // expected-error{{no matching function for call to 'f0'}}
+}
+
+@interface A
+@end
+
+void f1(__weak id*);
+void test_f1(__weak A** a) {
+  f1(a);
+}
+
+@interface B : A
+@end
+
+void f2(__weak A**);
+void test_f2(__weak B** b) {
+  f2(b);
+}
+