]> granicus.if.org Git - clang/commitdiff
Resolve placeholder expressions before trying to deduce
authorJohn McCall <rjmccall@apple.com>
Tue, 15 Nov 2011 01:35:18 +0000 (01:35 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 15 Nov 2011 01:35:18 +0000 (01:35 +0000)
'auto'.  Introduce a convenience method to make this a bit
easier, and use it elsewhere.

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

include/clang/AST/BuiltinTypes.def
include/clang/AST/Type.h
include/clang/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaPseudoObject.cpp
lib/Sema/SemaTemplateDeduction.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
test/SemaObjCXX/properties.mm

index bfcd55bedba252607add74bdb2ea7ad81f04ac63..34e6fc5cd826daf3273e1e1b59c6da88569abecf 100644 (file)
@@ -170,6 +170,9 @@ BUILTIN_TYPE(Dependent, DependentTy)
 //   &x->foo      # only if might be a static member function
 //   &Class::foo  # when a pointer-to-member; sub-expr also has this type
 // OverloadExpr::find can be used to analyze the expression.
+//
+// Overload should be the first placeholder type, or else change
+// BuiltinType::isNonOverloadPlaceholderType()
 PLACEHOLDER_TYPE(Overload, OverloadTy)
 
 // The type of a bound C++ non-static member function.
index dfa594db1e589c29e9802a39d4d9244463e76b26..c9bee817a8bac3fbfe40968f8959cf8a6f2db62a 100644 (file)
@@ -1367,6 +1367,10 @@ public:
   /// isSpecificPlaceholderType - Test for a specific placeholder type.
   bool isSpecificPlaceholderType(unsigned K) const;
 
+  /// isNonOverloadPlaceholderType - Test for a placeholder type
+  /// other than Overload;  see BuiltinType::isNonOverloadPlaceholderType.
+  bool isNonOverloadPlaceholderType() const;
+
   /// isIntegerType() does *not* include complex integers (a GCC extension).
   /// isComplexIntegerType() can be used to test for complex integers.
   bool isIntegerType() const;     // C99 6.2.5p17 (int, char, bool, enum)
@@ -1725,6 +1729,19 @@ public:
     return isPlaceholderTypeKind(getKind());
   }
 
+  /// Determines whether this type is a placeholder type other than
+  /// Overload.  Most placeholder types require only syntactic
+  /// information about their context in order to be resolved (e.g.
+  /// whether it is a call expression), which means they can (and
+  /// should) be resolved in an earlier "phase" of analysis.
+  /// Overload expressions sometimes pick up further information
+  /// from their context, like whether the context expects a
+  /// specific function-pointer type, and so frequently need
+  /// special treatment.
+  bool isNonOverloadPlaceholderType() const {
+    return getKind() > Overload;
+  }
+
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
   static bool classof(const BuiltinType *) { return true; }
 };
@@ -4710,6 +4727,12 @@ inline bool Type::isSpecificPlaceholderType(unsigned K) const {
   return false;
 }
 
+inline bool Type::isNonOverloadPlaceholderType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+    return BT->isNonOverloadPlaceholderType();
+  return false;
+}
+
 /// \brief Determines whether this is a type for which one can define
 /// an overloaded operator.
 inline bool Type::isOverloadableType() const {
index 27730f08f7b506f7091140a57503d623ded4cb80..f1d5c2d239e5220137919227a6fbb8f3de537b03 100644 (file)
@@ -4624,7 +4624,7 @@ public:
                           FunctionDecl *&Specialization,
                           sema::TemplateDeductionInfo &Info);
 
-  bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *Initializer,
+  bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
                       TypeSourceInfo *&Result);
 
   FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
index 4f2f8c4eafd55c647e92173b5afc63bbcec5cdd0..cfa5feabb39a77ee562767a62641cebf0bdbae40 100644 (file)
@@ -3976,10 +3976,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
   // Immediately handle non-overload placeholders.  Overloads can be
   // resolved contextually, but everything else here can't.
   for (unsigned I = 0; I != NumInit; ++I) {
-    if (const BuiltinType *pty
-          = InitList[I]->getType()->getAsPlaceholderType()) {
-      if (pty->getKind() == BuiltinType::Overload) continue;
-
+    if (InitList[I]->getType()->isNonOverloadPlaceholderType()) {
       ExprResult result = CheckPlaceholderExpr(InitList[I]);
 
       // Ignore failures; dropping the entire initializer list because
index c24f8aa5e21345cb78cf624c3b3b966d85806ba8..3f91bb53e880f5dcd228f522ea615796fbac515e 100644 (file)
@@ -3795,17 +3795,14 @@ InitializationSequence::InitializationSequence(Sema &S,
   setSequenceKind(NormalSequence);
 
   for (unsigned I = 0; I != NumArgs; ++I)
-    if (const BuiltinType *PlaceholderTy
-          = Args[I]->getType()->getAsPlaceholderType()) {
+    if (Args[I]->getType()->isNonOverloadPlaceholderType()) {
       // FIXME: should we be doing this here?
-      if (PlaceholderTy->getKind() != BuiltinType::Overload) {
-        ExprResult result = S.CheckPlaceholderExpr(Args[I]);
-        if (result.isInvalid()) {
-          SetFailed(FK_PlaceholderType);
-          return;
-        }
-        Args[I] = result.take();
+      ExprResult result = S.CheckPlaceholderExpr(Args[I]);
+      if (result.isInvalid()) {
+        SetFailed(FK_PlaceholderType);
+        return;
       }
+      Args[I] = result.take();
     }
 
 
index b70c4ca811cd1eb0ee5ce25477f7b870d5575896..3bd671d10cd0745507d14c03eda3eaa42b39d7e9 100644 (file)
@@ -775,12 +775,10 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
                                         VK_RValue, OK_Ordinary, opcLoc);
 
   // Filter out non-overload placeholder types in the RHS.
-  if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
-    if (PTy->getKind() != BuiltinType::Overload) {
-      ExprResult result = CheckPlaceholderExpr(RHS);
-      if (result.isInvalid()) return ExprError();
-      RHS = result.take();
-    }
+  if (RHS->getType()->isNonOverloadPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(RHS);
+    if (result.isInvalid()) return ExprError();
+    RHS = result.take();
   }
 
   Expr *opaqueRef = LHS->IgnoreParens();
index 93ea89d6285d15074077c8bc22e86b69af19e9ad..17987da16ad98769640a4d378f6220d61d219d1f 100644 (file)
@@ -3342,8 +3342,14 @@ namespace {
 ///
 /// \returns true if deduction succeeded, false if it failed.
 bool
-Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init,
+Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
                      TypeSourceInfo *&Result) {
+  if (Init->getType()->isNonOverloadPlaceholderType()) {
+    ExprResult result = CheckPlaceholderExpr(Init);
+    if (result.isInvalid()) return false;
+    Init = result.take();
+  }
+
   if (Init->isTypeDependent()) {
     Result = Type;
     return true;
index ceb246eb22cf5eb657ed08c59256ed57614305fe..aa22b8f56bb94884fe16e0245b79ac4d1544c4fb 100644 (file)
@@ -92,7 +92,8 @@ namespace PR10939 {
   template<typename T> T g(T);
 
   void f(X *x) {
-    auto value = x->method; // expected-error{{variable 'value' with type 'auto' has incompatible initializer of type '<bound member function type>'}}
+    // FIXME: we should really only get the first diagnostic here.
+    auto value = x->method; // expected-error {{reference to non-static member function must be called}} expected-error{{variable 'value' with type 'auto' has incompatible initializer of type '<bound member function type>'}}
     if (value) { }
 
     auto funcptr = &g<int>;
index f148b3395d9364ce582ee5d68776bc1ee3d242e3..0b9c63e30dcf3f0c05fdec2f013be6acc3aa7c00 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
 
 struct X { 
   void f() const;
@@ -19,6 +19,15 @@ struct X {
 - (void)setx:(const X&)other { x_ = other; }
 - (void)method {
   self.x.f();
-} 
+}
 @end
 
+// rdar://problem/10444030
+@interface Test2
+- (void) setY: (int) y;
+- (int) z;
+@end
+void test2(Test2 *a) {
+  auto y = a.y; // expected-error {{expected getter method not found on object of type 'Test2 *'}} expected-error {{variable 'y' with type 'auto' has incompatible initializer of type}}
+  auto z = a.z;
+}