diff options
author | John McCall <rjmccall@apple.com> | 2011-04-26 20:42:42 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-04-26 20:42:42 +0000 |
commit | 864c041e118155c2b1ce0ba36942a3da5a4a055e (patch) | |
tree | 19f877df6230e8eb683deb156e16b51f25dabcf2 /lib/AST | |
parent | eab80782f645489db299db24aa7a5886b37185b0 (diff) |
Make yet another placeholder type, this one marking that an expression is a bound
member function, i.e. something of the form 'x.f' where 'f' is a non-static
member function. Diagnose this in the general case. Some of the new diagnostics
are probably worse than the old ones, but we now get this right much more
universally, and there's certainly room for improvement in the diagnostics.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130239 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 3 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 1 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 32 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 27 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 1 | ||||
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 1 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 1 | ||||
-rw-r--r-- | lib/AST/TypeLoc.cpp | 1 |
8 files changed, 63 insertions, 4 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3d74d3a938..a31969dc90 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -402,6 +402,9 @@ void ASTContext::InitBuiltinTypes() { // Placeholder type for functions. InitBuiltinType(OverloadTy, BuiltinType::Overload); + // Placeholder type for bound members. + InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember); + // "any" type; useful for debugger-like clients. InitBuiltinType(UnknownAnyTy, BuiltinType::UnknownAny); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 2b15904fdb..7c45543f66 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1363,6 +1363,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Overload: return Importer.getToContext().OverloadTy; case BuiltinType::Dependent: return Importer.getToContext().DependentTy; case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy; + case BuiltinType::BoundMember: return Importer.getToContext().BoundMemberTy; case BuiltinType::ObjCId: // FIXME: Make sure that the "to" context supports Objective-C! diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index dd1a317f4a..2a5917c459 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -820,11 +820,11 @@ QualType CallExpr::getCallReturnType() const { CalleeType = FnTypePtr->getPointeeType(); else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) CalleeType = BPT->getPointeeType(); - else if (const MemberPointerType *MPT - = CalleeType->getAs<MemberPointerType>()) - CalleeType = MPT->getPointeeType(); + else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) + // This should never be overloaded and so should never return null. + CalleeType = Expr::findBoundMemberType(getCallee()); - const FunctionType *FnType = CalleeType->getAs<FunctionType>(); + const FunctionType *FnType = CalleeType->castAs<FunctionType>(); return FnType->getResultType(); } @@ -1623,6 +1623,30 @@ bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { return ClassifyLValue(Ctx) == Expr::LV_MemberFunction; } +QualType Expr::findBoundMemberType(const Expr *expr) { + assert(expr->getType()->isSpecificPlaceholderType(BuiltinType::BoundMember)); + + // Bound member expressions are always one of these possibilities: + // x->m x.m x->*y x.*y + // (possibly parenthesized) + + expr = expr->IgnoreParens(); + if (const MemberExpr *mem = dyn_cast<MemberExpr>(expr)) { + assert(isa<CXXMethodDecl>(mem->getMemberDecl())); + return mem->getMemberDecl()->getType(); + } + + if (const BinaryOperator *op = dyn_cast<BinaryOperator>(expr)) { + QualType type = op->getRHS()->getType()->castAs<MemberPointerType>() + ->getPointeeType(); + assert(type->isFunctionType()); + return type; + } + + assert(isa<UnresolvedMemberExpr>(expr)); + return QualType(); +} + static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1, Expr::CanThrowResult CT2) { // CanThrowResult constants are ordered so that the maximum is the correct diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 127431ba7d..1a1a0a36a6 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -837,6 +837,28 @@ bool CXXDependentScopeMemberExpr::isImplicitAccess() const { return cast<Expr>(Base)->isImplicitCXXThis(); } +static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, + UnresolvedSetIterator end) { + do { + NamedDecl *decl = *begin; + if (isa<UnresolvedUsingValueDecl>(decl)) + return false; + if (isa<UsingShadowDecl>(decl)) + decl = cast<UsingShadowDecl>(decl)->getUnderlyingDecl(); + + // Unresolved member expressions should only contain methods and + // method templates. + assert(isa<CXXMethodDecl>(decl) || isa<FunctionTemplateDecl>(decl)); + + if (isa<FunctionTemplateDecl>(decl)) + decl = cast<FunctionTemplateDecl>(decl)->getTemplatedDecl(); + if (cast<CXXMethodDecl>(decl)->isStatic()) + return false; + } while (++begin != end); + + return true; +} + UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, @@ -857,6 +879,11 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, BaseType->containsUnexpandedParameterPack())), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { + + // Check whether all of the members are non-static member functions, + // and if so, mark give this bound-member type instead of overload type. + if (hasOnlyNonStaticMemberFunctions(Begin, End)) + setType(C.BoundMemberTy); } bool UnresolvedMemberExpr::isImplicitAccess() const { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index b62442d6d2..14ee74be12 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1471,6 +1471,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Overload: case BuiltinType::Dependent: + case BuiltinType::BoundMember: case BuiltinType::UnknownAny: assert(false && "Overloaded and dependent types shouldn't get to name mangling"); diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 046c33ddda..2ba4cf2f67 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -718,6 +718,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Overload: case BuiltinType::Dependent: case BuiltinType::UnknownAny: + case BuiltinType::BoundMember: assert(false && "Overloaded and dependent types shouldn't get to name mangling"); break; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 124bf13305..d43a121881 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1169,6 +1169,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const { case Char32: return "char32_t"; case NullPtr: return "nullptr_t"; case Overload: return "<overloaded function type>"; + case BoundMember: return "<bound member function type>"; case Dependent: return "<dependent type>"; case UnknownAny: return "<unknown type>"; case ObjCId: return "id"; diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index cc64830428..34e7693e30 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -234,6 +234,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::NullPtr: case BuiltinType::Overload: case BuiltinType::Dependent: + case BuiltinType::BoundMember: case BuiltinType::UnknownAny: case BuiltinType::ObjCId: case BuiltinType::ObjCClass: |