aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-11-15 01:35:18 +0000
committerJohn McCall <rjmccall@apple.com>2011-11-15 01:35:18 +0000
commit32509f1e60451d86e9fbc473b6e853ba10b5fd1e (patch)
treefb5508ad78d02b807ee47b267d03ec278ad4cead
parent02ae32ae110eeb1ef785bf5ad9cdce1c001a5fa1 (diff)
Resolve placeholder expressions before trying to deduce
'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
-rw-r--r--include/clang/AST/BuiltinTypes.def3
-rw-r--r--include/clang/AST/Type.h23
-rw-r--r--include/clang/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaExpr.cpp5
-rw-r--r--lib/Sema/SemaInit.cpp15
-rw-r--r--lib/Sema/SemaPseudoObject.cpp10
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp8
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp3
-rw-r--r--test/SemaObjCXX/properties.mm13
9 files changed, 58 insertions, 24 deletions
diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def
index bfcd55bedb..34e6fc5cd8 100644
--- a/include/clang/AST/BuiltinTypes.def
+++ b/include/clang/AST/BuiltinTypes.def
@@ -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.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index dfa594db1e..c9bee817a8 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -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 {
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 27730f08f7..f1d5c2d239 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -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,
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 4f2f8c4eaf..cfa5feabb3 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index c24f8aa5e2..3f91bb53e8 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -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();
}
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index b70c4ca811..3bd671d10c 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -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();
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 93ea89d628..17987da16a 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -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;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
index ceb246eb22..aa22b8f56b 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
@@ -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>;
diff --git a/test/SemaObjCXX/properties.mm b/test/SemaObjCXX/properties.mm
index f148b3395d..0b9c63e30d 100644
--- a/test/SemaObjCXX/properties.mm
+++ b/test/SemaObjCXX/properties.mm
@@ -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;
+}