]> granicus.if.org Git - clang/commitdiff
Allow Objective-C pointer conversions following an explicit user conversion.
authorDouglas Gregor <dgregor@apple.com>
Wed, 18 Dec 2013 21:46:16 +0000 (21:46 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 18 Dec 2013 21:46:16 +0000 (21:46 +0000)
Finishes the work started in r194224, and fixes <rdar://problem/15494681>.

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

include/clang/Sema/Sema.h
lib/Sema/SemaInit.cpp
test/SemaObjCXX/contextual-convert-to-id.mm

index 0e4ab07af01d1b747c05d39c6231d972d7ac892e..75e1a341ed4381868d5c751275c8f882ee4f8441 100644 (file)
@@ -2162,13 +2162,13 @@ public:
                               CXXRecordDecl *ActingContext,
                               Expr *From, QualType ToType,
                               OverloadCandidateSet& CandidateSet,
-                              bool AllowObjCConversionOnExplicit = false);
+                              bool AllowObjCConversionOnExplicit);
   void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
                                       DeclAccessPair FoundDecl,
                                       CXXRecordDecl *ActingContext,
                                       Expr *From, QualType ToType,
                                       OverloadCandidateSet &CandidateSet,
-                                    bool AllowObjCConversionOnExplicit = false);
+                                      bool AllowObjCConversionOnExplicit);
   void AddSurrogateCandidate(CXXConversionDecl *Conversion,
                              DeclAccessPair FoundDecl,
                              CXXRecordDecl *ActingContext,
index 9ba873a0780b7b4ebe05ad3beb2fa56930817ef2..ae0f662562e56d48b0b933d16fc64581f3475686 100644 (file)
@@ -3522,10 +3522,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
         if (ConvTemplate)
           S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
                                            ActingDC, Initializer,
-                                           DestType, CandidateSet);
+                                           DestType, CandidateSet,
+                                           /*AllowObjCConversionOnExplicit=*/
+                                             false);
         else
           S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
-                                   Initializer, DestType, CandidateSet);
+                                   Initializer, DestType, CandidateSet,
+                                   /*AllowObjCConversionOnExplicit=*/false);
       }
     }
   }
@@ -4145,10 +4148,11 @@ static void TryUserDefinedConversion(Sema &S,
           if (ConvTemplate)
             S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
                                              ActingDC, Initializer, DestType,
-                                             CandidateSet);
+                                             CandidateSet, AllowExplicit);
           else
             S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
-                                     Initializer, DestType, CandidateSet);
+                                     Initializer, DestType, CandidateSet,
+                                     AllowExplicit);
         }
       }
     }
index 602d6c24a8d6345d0ddeadb53e2939adfc66257a..47a9d07d41c2953b93973edba58e903b19b0e635 100644 (file)
@@ -8,6 +8,10 @@
 - unknownMethod;
 @end
 
+@interface C : A
+- knownMethod;
+@end
+
 template<typename T> struct RetainPtr {
   explicit operator T*() const;
 };
@@ -17,6 +21,16 @@ void methodCallToSpecific(RetainPtr<A> a) {
   [a unknownMethod]; // expected-warning{{'A' may not respond to 'unknownMethod'}}
 }
 
+void explicitCast(RetainPtr<A> a, RetainPtr<B> b, RetainPtr<C> c) {
+  (void)(A*)a;
+  (void)(A*)b; // expected-error{{cannot convert 'RetainPtr<B>' to 'A *' without a conversion operator}}
+  (void)(A*)c;
+  (void)(C*)a;
+  (void)static_cast<A*>(a);
+  (void)static_cast<A*>(b);  // expected-error{{cannot convert 'RetainPtr<B>' to 'A *' without a conversion operator}}
+  (void)static_cast<A*>(c);
+}
+
 struct Incomplete; // expected-note{{forward declaration}}
 
 void methodCallToIncomplete(Incomplete &incomplete) {
@@ -31,3 +45,8 @@ void methodCallToId(IdPtr a) {
   [a knownMethod];
   [a unknownMethod];
 }
+
+void explicitCast(IdPtr a) {
+  (void)(A*)a;
+  (void)static_cast<A*>(a);
+}