diff options
30 files changed, 364 insertions, 229 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 820c5a288d5..959e158cebc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -426,7 +426,7 @@ public: CanQualType FloatTy, DoubleTy, LongDoubleTy; CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType VoidPtrTy, NullPtrTy; - CanQualType OverloadTy, DependentTy, UnknownAnyTy; + CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 2969b752336..ed207ace0c3 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -486,6 +486,11 @@ public: /// \brief Returns true if this expression is a bound member function. bool isBoundMemberFunction(ASTContext &Ctx) const; + /// \brief Given an expression of bound-member type, find the type + /// of the member. Returns null if this is an *overloaded* bound + /// member expression. + static QualType findBoundMemberType(const Expr *expr); + /// \brief Result type of CanThrow(). enum CanThrowResult { CT_Cannot, diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 9ed30563598..cfdfae1ee36 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1190,6 +1190,9 @@ public: /// BuiltinTypes. bool isPlaceholderType() const; + /// isSpecificPlaceholderType - Test for a specific placeholder type. + bool isSpecificPlaceholderType(unsigned K) 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) @@ -1488,32 +1491,52 @@ public: NullPtr, // This is the type of C++0x 'nullptr'. + /// The primitive Objective C 'id' type. The user-visible 'id' + /// type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The user-visible + /// 'Class' type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCClass, + + /// The primitive Objective C 'SEL' type. The user-visible 'SEL' + /// type is a typedef of a PointerType to this. + ObjCSel, + /// This represents the type of an expression whose type is /// totally unknown, e.g. 'T::foo'. It is permitted for this to /// appear in situations where the structure of the type is /// theoretically deducible. Dependent, - /// The type of an unresolved overload set. + /// The type of an unresolved overload set. A placeholder type. + /// Expressions with this type have one of the following basic + /// forms, with parentheses generally permitted: + /// foo # possibly qualified, not if an implicit access + /// foo # possibly qualified, not if an implicit access + /// &foo # possibly qualified, not if an implicit access + /// x->foo # only if might be a static member function + /// &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, - /// __builtin_any_type. Useful for clients like debuggers - /// that don't know what type to give something. Only a small - /// number of operations are valid on expressions of unknown type; - /// notable among them, calls and explicit casts. - UnknownAny, - - /// The primitive Objective C 'id' type. The type pointed to by the - /// user-visible 'id' type. Only ever shows up in an AST as the base - /// type of an ObjCObjectType. - ObjCId, - - /// The primitive Objective C 'Class' type. The type pointed to by the - /// user-visible 'Class' type. Only ever shows up in an AST as the - /// base type of an ObjCObjectType. - ObjCClass, - - ObjCSel // This represents the ObjC 'SEL' type. + /// The type of a bound C++ non-static member function. + /// A placeholder type. Expressions with this type have one of the + /// following basic forms: + /// foo # if an implicit access + /// x->foo # if only contains non-static members + BoundMember, + + /// __builtin_any_type. A placeholder type. Useful for clients + /// like debuggers that don't know what type to give something. + /// Only a small number of operations are valid on expressions of + /// unknown type, most notably explicit casts. + UnknownAny }; public: @@ -1546,11 +1569,11 @@ public: return getKind() >= Float && getKind() <= LongDouble; } - /// Determines whether this type is a "forbidden" placeholder type, - /// i.e. a type which cannot appear in arbitrary positions in a - /// fully-formed expression. + /// Determines whether this type is a placeholder type, i.e. a type + /// which cannot appear in arbitrary positions in a fully-formed + /// expression. bool isPlaceholderType() const { - return getKind() == Overload || getKind() == UnknownAny; + return getKind() >= Overload; } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } @@ -4300,6 +4323,12 @@ inline bool Type::isPlaceholderType() const { return false; } +inline bool Type::isSpecificPlaceholderType(unsigned K) const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + return (BT->getKind() == (BuiltinType::Kind) K); + 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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0e813a6e123..b3d4890fdaf 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -112,6 +112,7 @@ namespace clang { class ObjCPropertyDecl; class ObjCProtocolDecl; class OverloadCandidateSet; + class OverloadExpr; class ParenListExpr; class ParmVarDecl; class Preprocessor; @@ -1413,7 +1414,7 @@ public: bool Complain, DeclAccessPair &Found); - FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From, + FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain = false, DeclAccessPair* Found = 0); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 72252d4da80..06be2179156 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -491,8 +491,10 @@ namespace clang { PREDEF_TYPE_OBJC_CLASS = 27, /// \brief The ObjC 'SEL' type. PREDEF_TYPE_OBJC_SEL = 28, - /// \brief The 'unknown any' type. - PREDEF_TYPE_UNKNOWN_ANY = 29 + /// \brief The 'unknown any' placeholder type. + PREDEF_TYPE_UNKNOWN_ANY = 29, + /// \brief The placeholder type for bound member functions. + PREDEF_TYPE_BOUND_MEMBER = 30 }; /// \brief The number of predefined type IDs that are reserved for diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 3d74d3a9380..a31969dc907 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 2b15904fdba..7c45543f66a 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/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/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index dd1a317f4a1..2a5917c4594 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/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/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 127431ba7d6..1a1a0a36a65 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index b62442d6d2a..14ee74be124 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/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/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 046c33ddda6..2ba4cf2f67c 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/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/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 124bf133052..d43a121881e 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/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/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index cc648304285..34e7693e307 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/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: diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 228d9c6c5e6..94f95053425 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -289,10 +289,10 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, const Expr *MemFnExpr = BO->getRHS(); const MemberPointerType *MPT = - MemFnExpr->getType()->getAs<MemberPointerType>(); + MemFnExpr->getType()->castAs<MemberPointerType>(); const FunctionProtoType *FPT = - MPT->getPointeeType()->getAs<FunctionProtoType>(); + MPT->getPointeeType()->castAs<FunctionProtoType>(); const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); @@ -321,8 +321,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, // And the rest of the call args EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); - const FunctionType *BO_FPT = BO->getType()->getAs<FunctionProtoType>(); - return EmitCall(CGM.getTypes().getFunctionInfo(Args, BO_FPT), Callee, + return EmitCall(CGM.getTypes().getFunctionInfo(Args, FPT), Callee, ReturnValue, Args); } diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index b8d234f8a62..c73b199e31f 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/lib/CodeGen/CGRTTI.cpp @@ -196,8 +196,9 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { case BuiltinType::Overload: case BuiltinType::Dependent: + case BuiltinType::BoundMember: case BuiltinType::UnknownAny: - assert(false && "Should not see this type here!"); + llvm_unreachable("asking for RRTI for a placeholder type!"); case BuiltinType::ObjCId: case BuiltinType::ObjCClass: diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 255d12f2cc3..8db6fe51868 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -229,7 +229,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { #define DEPENDENT_TYPE(Class, Base) case Type::Class: #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" - assert(false && "Non-canonical or dependent types aren't possible."); + llvm_unreachable("Non-canonical or dependent types aren't possible."); break; case Type::Builtin: { @@ -283,8 +283,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case BuiltinType::Overload: case BuiltinType::Dependent: + case BuiltinType::BoundMember: case BuiltinType::UnknownAny: - llvm_unreachable("Unexpected builtin type!"); + llvm_unreachable("Unexpected placeholder builtin type!"); break; } llvm_unreachable("Unknown builtin type!"); diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 648011b1f05..ed54f0f5442 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -160,10 +160,6 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, // FIXME: should we check this in a more fine-grained manner? bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent(); - if (Ex.get()->isBoundMemberFunction(Context)) - Diag(Ex.get()->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << Ex.get()->getSourceRange(); - ExprValueKind VK = VK_RValue; if (TypeDependent) VK = Expr::getValueKindForType(DestType); @@ -305,6 +301,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, /// Diagnose a failed cast. static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, SourceRange opRange, Expr *src, QualType destType) { + if (src->getType() == S.Context.BoundMemberTy) { + (void) S.CheckPlaceholderExpr(src); // will always fail + return; + } + if (msg == diag::err_bad_cxx_cast_generic && tryDiagnoseOverloadedCast(S, castType, opRange, src, destType)) return; @@ -1540,12 +1541,6 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, Expr *CastExpr, CastKind &Kind, CXXCastPath &BasePath, bool FunctionalStyle) { - if (CastExpr->isBoundMemberFunction(Context)) { - Diag(CastExpr->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << CastExpr->getSourceRange(); - return ExprError(); - } - // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". @@ -1557,6 +1552,9 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, return ExprError(); CastExpr = CastExprRes.take(); + if (CastExpr->getType() == Context.BoundMemberTy) + return CheckPlaceholderExpr(CastExpr); // will always fail + if (CastExpr->getType() == Context.OverloadTy) { ExprResult SingleFunctionExpr = ResolveAndFixSingleFunctionTemplateSpecialization( diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c90c5132506..212f584f5fe 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3934,12 +3934,20 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { + ExprValueKind valueKind; + QualType type; + if (MemberFn->isInstance()) { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } else { + valueKind = VK_LValue; + type = MemberFn->getType(); + } + MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, MemberFn, FoundDecl, MemberNameInfo, - MemberFn->getType(), - MemberFn->isInstance() ? VK_RValue : VK_LValue, - OK_Ordinary)); + type, valueKind, OK_Ordinary)); } assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); @@ -4051,6 +4059,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; + } else if (BaseType == Context.BoundMemberTy) { + goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr.get()->getSourceRange(); @@ -4424,6 +4434,16 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, } } else if ((Fun = BaseType->getAs<FunctionType>())) { TryCall = true; + } else if (BaseType == Context.BoundMemberTy) { + // Look for the bound-member type. If it's still overloaded, + // give up, although we probably should have fallen into the + // OverloadExpr case above if we actually have an overloaded + // bound member. + QualType fnType = Expr::findBoundMemberType(BaseExpr.get()); + if (!fnType.isNull()) { + TryCall = true; + Fun = fnType->castAs<FunctionType>(); + } } if (TryCall) { @@ -4858,91 +4878,33 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, Fn = result.take(); } - Expr *NakedFn = Fn->IgnoreParens(); - - // Determine whether this is a call to an unresolved member function. - if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { - // If lookup was unresolved but not dependent (i.e. didn't find - // an unresolved using declaration), it has to be an overloaded - // function set, which means it must contain either multiple - // declarations (all methods or method templates) or a single - // method template. - assert((MemE->getNumDecls() > 1) || - isa<FunctionTemplateDecl>( - (*MemE->decls_begin())->getUnderlyingDecl())); - (void)MemE; - + if (Fn->getType() == Context.BoundMemberTy) { return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, RParenLoc); } + } + + // Check for overloaded calls. This can happen even in C due to extensions. + if (Fn->getType() == Context.OverloadTy) { + OverloadExpr::FindResult find = OverloadExpr::find(Fn); - // Determine whether this is a call to a member function. - if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) { - NamedDecl *MemDecl = MemExpr->getMemberDecl(); - if (isa<CXXMethodDecl>(MemDecl)) + // We aren't supposed to apply this logic if there's an '&' involved. + if (!find.IsAddressOfOperand) { + OverloadExpr *ovl = find.Expression; + if (isa<UnresolvedLookupExpr>(ovl)) { + UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } else { return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, RParenLoc); - } - - // Determine whether this is a call to a pointer-to-member function. - if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) { - if (BO->getOpcode() == BO_PtrMemD || - BO->getOpcode() == BO_PtrMemI) { - if (const FunctionProtoType *FPT - = BO->getType()->getAs<FunctionProtoType>()) { - QualType ResultTy = FPT->getCallResultType(Context); - ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType()); - - // Check that the object type isn't more qualified than the - // member function we're calling. - Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals()); - Qualifiers ObjectQuals - = BO->getOpcode() == BO_PtrMemD - ? BO->getLHS()->getType().getQualifiers() - : BO->getLHS()->getType()->getAs<PointerType>() - ->getPointeeType().getQualifiers(); - - Qualifiers Difference = ObjectQuals - FuncQuals; - Difference.removeObjCGCAttr(); - Difference.removeAddressSpace(); - if (Difference) { - std::string QualsString = Difference.getAsString(); - Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals) - << BO->getType().getUnqualifiedType() - << QualsString - << (QualsString.find(' ') == std::string::npos? 1 : 2); - } - - CXXMemberCallExpr *TheCall - = new (Context) CXXMemberCallExpr(Context, Fn, Args, - NumArgs, ResultTy, VK, - RParenLoc); - - if (CheckCallReturnType(FPT->getResultType(), - BO->getRHS()->getSourceRange().getBegin(), - TheCall, 0)) - return ExprError(); - - if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs, - RParenLoc)) - return ExprError(); - - return MaybeBindToTemporary(TheCall); - } } } } // If we're directly calling a function, get the appropriate declaration. - // Also, in C++, keep track of whether we should perform argument-dependent - // lookup and whether there were any explicitly-specified template arguments. Expr *NakedFn = Fn->IgnoreParens(); - if (isa<UnresolvedLookupExpr>(NakedFn)) { - UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn); - return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); - } NamedDecl *NDecl = 0; if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) @@ -4951,6 +4913,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, if (isa<DeclRefExpr>(NakedFn)) NDecl = cast<DeclRefExpr>(NakedFn)->getDecl(); + else if (isa<MemberExpr>(NakedFn)) + NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, ExecConfig); @@ -8282,6 +8246,11 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, return S.Context.OverloadTy; if (OrigOp->getType() == S.Context.UnknownAnyTy) return S.Context.UnknownAnyTy; + if (OrigOp->getType() == S.Context.BoundMemberTy) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp->getSourceRange(); + return QualType(); + } assert(!OrigOp->getType()->isPlaceholderType()); @@ -10301,13 +10270,11 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { if (ParenExpr *parenE = dyn_cast<ParenExpr>(E)) DiagnoseEqualityWithExtraParens(parenE); - if (!E->isTypeDependent()) { - if (E->isBoundMemberFunction(Context)) { - Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); - return ExprError(); - } + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + if (!E->isTypeDependent()) { if (getLangOptions().CPlusPlus) return CheckCXXBooleanCondition(E); // C++ 6.4p4 @@ -10728,6 +10695,13 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { QualType(), diag::err_ovl_unresolvable); + // Bound member functions. + if (type == Context.BoundMemberTy) { + Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) + << E->getSourceRange(); + return ExprError(); + } + // Expressions of unknown type. if (type == Context.UnknownAnyTy) return diagnoseUnknownAnyExpr(*this, E); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index edfa4a532df..f8ad763e4bd 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2857,13 +2857,6 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex, // second operand. // The cv qualifiers are the union of those in the pointer and the left side, // in accordance with 5.5p5 and 5.2.5. - // FIXME: This returns a dereferenced member function pointer as a normal - // function type. However, the only operation valid on such functions is - // calling them. There's also a GCC extension to get a function pointer to the - // thing, which is another complication, because this type - unlike the type - // that is the result of this expression - takes the class as the first - // argument. - // We probably need a "MemberFunctionClosureType" or something like that. QualType Result = MemPtr->getPointeeType(); Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers()); @@ -2900,12 +2893,14 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex, // operand is a pointer to a member function is a prvalue. The // result of an ->* expression is an lvalue if its second operand // is a pointer to data member and a prvalue otherwise. - if (Result->isFunctionType()) + if (Result->isFunctionType()) { VK = VK_RValue; - else if (isIndirect) + return Context.BoundMemberTy; + } else if (isIndirect) { VK = VK_LValue; - else + } else { VK = lex.get()->getValueKind(); + } return Result; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 06c097c620c..6e6bf22be0b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3623,8 +3623,8 @@ ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) - return Diag(From->getSourceRange().getBegin(), - diag::err_typecheck_bool_condition) + return Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_bool_condition) << From->getType() << From->getSourceRange(); return ExprError(); } @@ -7202,7 +7202,7 @@ public: if (!TargetFunctionType->isFunctionType()) { if (OvlExpr->hasExplicitTemplateArgs()) { DeclAccessPair dap; - if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( + if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( OvlExpr, false, &dap) ) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { @@ -7502,32 +7502,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp /// template, where that template-id refers to a single template whose template /// arguments are either provided by the template-id or have defaults, /// as described in C++0x [temp.arg.explicit]p3. -FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, - bool Complain, - DeclAccessPair* FoundResult) { +FunctionDecl * +Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, + bool Complain, + DeclAccessPair *FoundResult) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] // C++ [over.over]p1: // [...] The overloaded function name can be preceded by the & // operator. - if (From->getType() != Context.OverloadTy) - return 0; - - OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression; // If we didn't actually find any template-ids, we're done. - if (!OvlExpr->hasExplicitTemplateArgs()) + if (!ovl->hasExplicitTemplateArgs()) return 0; TemplateArgumentListInfo ExplicitTemplateArgs; - OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); // Look through all of the overloaded functions, searching for one // whose type matches exactly. FunctionDecl *Matched = 0; - for (UnresolvedSetIterator I = OvlExpr->decls_begin(), - E = OvlExpr->decls_end(); I != E; ++I) { + for (UnresolvedSetIterator I = ovl->decls_begin(), + E = ovl->decls_end(); I != E; ++I) { // C++0x [temp.arg.explicit]p3: // [...] In contexts where deduction is done and fails, or in contexts // where deduction is not done, if a template argument list is @@ -7544,7 +7541,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + TemplateDeductionInfo Info(Context, ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info)) { @@ -7553,21 +7550,20 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, continue; } + assert(Specialization && "no specialization and no error?"); + // Multiple matches; we can't resolve to a single declaration. if (Matched) { - if (FoundResult) - *FoundResult = DeclAccessPair(); - if (Complain) { - Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) - << OvlExpr->getName(); - NoteAllOverloadCandidates(OvlExpr); + Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous) + << ovl->getName(); + NoteAllOverloadCandidates(ovl); } return 0; - } + } - if ((Matched = Specialization) && FoundResult) - *FoundResult = I.getPair(); + Matched = Specialization; + if (FoundResult) *FoundResult = I.getPair(); } return Matched; @@ -7581,39 +7577,65 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, // template specialization // Last three arguments should only be supplied if Complain = true ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( - Expr *SrcExpr, bool DoFunctionPointerConverion, bool Complain, + Expr *SrcExpr, bool doFunctionPointerConverion, bool complain, const SourceRange& OpRangeForComplaining, QualType DestTypeForComplaining, - unsigned DiagIDForComplaining ) { + unsigned DiagIDForComplaining) { + assert(SrcExpr->getType() == Context.OverloadTy); - assert(SrcExpr->getType() == Context.OverloadTy); + OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr); - DeclAccessPair Found; - ExprResult SingleFunctionExpression; - if (FunctionDecl* Fn = ResolveSingleFunctionTemplateSpecialization( - SrcExpr, false, // false -> Complain - &Found)) { - if (!DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) { - // mark the expression as resolved to Fn - SingleFunctionExpression = Owned(FixOverloadedFunctionReference(SrcExpr, - Found, Fn)); - if (DoFunctionPointerConverion) - SingleFunctionExpression = - DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); - } - } - if (!SingleFunctionExpression.isUsable()) { - if (Complain) { - OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression; - Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) - << oe->getName() << DestTypeForComplaining << OpRangeForComplaining - << oe->getQualifierLoc().getSourceRange(); - NoteAllOverloadCandidates(SrcExpr); - } + DeclAccessPair found; + ExprResult SingleFunctionExpression; + if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( + ovl.Expression, /*complain*/ false, &found)) { + if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin())) + return ExprError(); + + // It is only correct to resolve to an instance method if we're + // resolving a form that's permitted to be a pointer to member. + // Otherwise we'll end up making a bound member expression, which + // is illegal in all the contexts we resolve like this. + if (!ovl.HasFormOfMemberPointer && + isa<CXXMethodDecl>(fn) && + cast<CXXMethodDecl>(fn)->isInstance()) { + if (complain) { + Diag(ovl.Expression->getExprLoc(), + diag::err_invalid_use_of_bound_member_func) + << ovl.Expression->getSourceRange(); + // TODO: I believe we only end up here if there's a mix of + // static and non-static candidates (otherwise the expression + // would have 'bound member' type, not 'overload' type). + // Ideally we would note which candidate was chosen and why + // the static candidates were rejected. + } + return ExprError(); } - return SingleFunctionExpression; + // Fix the expresion to refer to 'fn'. + SingleFunctionExpression = + Owned(FixOverloadedFunctionReference(SrcExpr, found, fn)); + + // If desired, do function-to-pointer decay. + if (doFunctionPointerConverion) + SingleFunctionExpression = + DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); + } + + if (!SingleFunctionExpression.isUsable()) { + if (complain) { + Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) + << ovl.Expression->getName() + << DestTypeForComplaining + << OpRangeForComplaining + << ovl.Expression->getQualifierLoc().getSourceRange(); + NoteAllOverloadCandidates(SrcExpr); + } + return ExprError(); + } + + return SingleFunctionExpression; } /// \brief Add a single candidate to the overload set. @@ -8499,16 +8521,66 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, /// function (and includes the object parameter), Args/NumArgs are the /// arguments to the function call (not including the object /// parameter). The caller needs to validate that the member -/// expression refers to a member function or an overloaded member -/// function. +/// expression refers to a non-static member function or an overloaded +/// member function. ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { + assert(MemExprE->getType() == Context.BoundMemberTy || + MemExprE->getType() == Context.OverloadTy); + // Dig out the member expression. This holds both the object // argument and the member function we're referring to. Expr *NakedMemExpr = MemExprE->IgnoreParens(); + // Determine whether this is a call to a pointer-to-member function. + if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) { + assert(op->getType() == Context.BoundMemberTy); + assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI); + + QualType fnType = + op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType(); + + const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>(); + QualType resultType = proto->getCallResultType(Context); + ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType()); + + // Check that the object type isn't more qualified than the + // member function we're calling. + Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals()); + + QualType objectType = op->getLHS()->getType(); + if (op->getOpcode() == BO_PtrMemI) + objectType = objectType->castAs<PointerType>()->getPointeeType(); + Qualifiers objectQuals = objectType.getQualifiers(); + + Qualifiers difference = objectQuals - funcQuals; + difference.removeObjCGCAttr(); + difference.removeAddressSpace(); + if (difference) { + std::string qualsString = difference.getAsString(); + Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals) + << fnType.getUnqualifiedType() + << qualsString + << (qualsString.find(' ') == std::string::npos ? 1 : 2); + } + + CXXMemberCallExpr *call + = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + resultType, valueKind, RParenLoc); + + if (CheckCallReturnType(proto->getResultType(), + op->getRHS()->getSourceRange().getBegin(), + call, 0)) + return ExprError(); + + if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc)) + return ExprError(); + + return MaybeBindToTemporary(call); + } + MemberExpr *MemExpr; CXXMethodDecl *Method = 0; DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index e6609c08e21..5e21a367588 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -77,12 +77,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (!E) return; - if (E->isBoundMemberFunction(Context)) { - Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); - return; - } - SourceLocation Loc; SourceRange R1, R2; if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index b5bbe74ce3d..782e5c6aa79 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -50,6 +50,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break; case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break; case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break; + case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break; case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break; case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break; case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 03d9a05f3e3..65ff731d3a8 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3638,6 +3638,7 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break; case PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break; case PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break; + case PREDEF_TYPE_BOUND_MEMBER: T = Context->BoundMemberTy; break; case PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break; case PREDEF_TYPE_UNKNOWN_ANY: T = Context->UnknownAnyTy; break; case PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break; diff --git a/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp index b1cc1e3cfab..544a66d9e39 100644 --- a/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp +++ b/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -137,10 +137,10 @@ namespace member_pointers { if (S::f<int>) return; // expected-error {{call to non-static member function without an object argument}} if (&S::f<char>) return; if (&S::f<int>) return; - if (s.f<char>) return; // expected-error {{contextually convertible}} - if (s.f<int>) return; // expected-error {{contextually convertible}} - if (&s.f<char>) return; // expected-error {{contextually convertible}} - if (&s.f<int>) return; // expected-error {{contextually convertible}} + if (s.f<char>) return; // expected-error {{a bound member function may only be called}} + if (s.f<int>) return; // expected-error {{a bound member function may only be called}} + if (&s.f<char>) return; // expected-error {{cannot create a non-constant pointer to member function}} + if (&s.f<int>) return; // expected-error {{cannot create a non-constant pointer to member function}} if (S::g<char>) return; if (S::g<int>) return; @@ -152,22 +152,23 @@ namespace member_pointers { if (&s.g<int>) return; if (S::h<42>) return; - if (S::h<int>) return; // expected-error {{contextually convertible}} + if (S::h<int>) return; // expected-error {{a bound member function may only be called}} if (&S::h<42>) return; if (&S::h<int>) return; if (s.h<42>) return; - if (s.h<int>) return; // expected-error {{contextually convertible}} + if (s.h<int>) return; // expected-error {{a bound member function may only be called}} if (&s.h<42>) return; - if (&s.h<int>) return; // expected-error {{contextually convertible}} + if (&s.h<int>) return; // expected-error {{a bound member function may only be called}} { bool b = S::f<char>; } // expected-error {{call to non-static member function without an object argument}} { bool b = S::f<int>; } // expected-error {{call to non-static member function without an object argument}} { bool b = &S::f<char>; } { bool b = &S::f<int>; } - { bool b = s.f<char>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} - { bool b = s.f<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} - { bool b = &s.f<char>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} - { bool b = &s.f<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} + // These next two errors are terrible. + { bool b = s.f<char>; } // expected-error {{cannot initialize}} + { bool b = s.f<int>; } // expected-error {{cannot initialize}} + { bool b = &s.f<char>; } // expected-error {{cannot create a non-constant pointer to member function}} + { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}} { bool b = S::g<char>; } { bool b = S::g<int>; } diff --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp index a1079ff5bac..a36fd582db2 100644 --- a/clang/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp @@ -57,11 +57,12 @@ struct B struct C { C &getC() { - return makeAC; // expected-error{{address of overloaded function 'makeAC'}} + // FIXME: this error message is terrible + return makeAC; // expected-error{{cannot bind to a value of unrelated type}} } - C &makeAC(); //expected-note{{candidate function}} - const C &makeAC() const; //expected-note{{candidate function}} + C &makeAC(); + const C &makeAC() const; static void f(); // expected-note{{candidate function}} static void f(int); // expected-note{{candidate function}} diff --git a/clang/test/SemaCXX/expression-traits.cpp b/clang/test/SemaCXX/expression-traits.cpp index 6b644ea84da..4555192280f 100644 --- a/clang/test/SemaCXX/expression-traits.cpp +++ b/clang/test/SemaCXX/expression-traits.cpp @@ -189,12 +189,12 @@ struct Class : BaseClass static int& NestedFuncTemplate() { return variable; } // expected-note{{candidate function}} template <class T> - int& NestedMemfunTemplate() { return variable; } // expected-note{{candidate function}} + int& NestedMemfunTemplate() { return variable; } int operator*() const; template <class T> - int operator+(T) const; // expected-note{{candidate function}} + int operator+(T) const; int NonstaticMemberFunction(); static int StaticMemberFunction(); @@ -237,12 +237,12 @@ struct Class : BaseClass // expected-error{{cannot resolve overloaded function 'NestedFuncTemplate' from context}} __is_lvalue_expr(::Class::NestedMemfunTemplate); // qualified-id: template \ - // expected-error{{cannot resolve overloaded function 'NestedMemfunTemplate' from context}} + // expected-error{{a bound member function may only be called}} __is_lvalue_expr(::Class::operator+); // operator-function-id: template \ - // expected-error{{cannot resolve overloaded function 'operator+' from context}} + // expected-error{{a bound member function may only be called}} - ASSERT_RVALUE(::Class::operator*); // operator-function-id: member function + //ASSERT_RVALUE(::Class::operator*); // operator-function-id: member function } void expr_prim_7() @@ -256,7 +256,7 @@ struct Class : BaseClass ASSERT_LVALUE(StaticMemberFunction); // identifier: function ASSERT_LVALUE(variable); // identifier: variable ASSERT_LVALUE(dataMember); // identifier: data member - ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function + //ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function // (cont'd)...A nested-name-specifier that names a class, // optionally followed by the keyword template (14.2), and then @@ -267,11 +267,11 @@ struct Class : BaseClass // member function or a data member. ASSERT_LVALUE(Class::dataMember); ASSERT_LVALUE(Class::StaticMemberFunction); - ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function + //ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function ASSERT_LVALUE(Class::baseDataMember); ASSERT_LVALUE(Class::BaseStaticMemberFunction); - ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function + //ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function } }; @@ -371,7 +371,7 @@ void expr_ref_4() // — Otherwise, if E1.E2 refers to a non-static member function, // then E1.E2 is not an lvalue. - ASSERT_RVALUE(Class().NonstaticMemberFunction); + //ASSERT_RVALUE(Class().NonstaticMemberFunction); // — If E2 is a member enumerator, and the type of E2 is T, the // expression E1.E2 is not an lvalue. The type of E1.E2 is T. @@ -502,17 +502,17 @@ void expr_mptr_oper() // is a pointer to data member... (cont'd) typedef Class MakeRValue; ASSERT_RVALUE(MakeRValue().*(&Class::dataMember)); - ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction)); + //ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction)); Class lvalue; ASSERT_LVALUE(lvalue.*(&Class::dataMember)); - ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction)); + //ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction)); // (cont'd)...The result of an ->* expression is an lvalue only // if its second operand is a pointer to data member. If the // second operand is the null pointer to member value (4.11), the // behavior is undefined. ASSERT_LVALUE((&lvalue)->*(&Class::dataMember)); - ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction)); + //ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction)); } void expr_cond(bool cond) diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp index 8d39af10af0..44d013fe796 100644 --- a/clang/test/SemaCXX/overloaded-operator.cpp +++ b/clang/test/SemaCXX/overloaded-operator.cpp @@ -387,15 +387,15 @@ void test_lookup_through_using() { namespace rdar9136502 { struct X { - int i(); // expected-note {{candidate function}} - int i(int); // expected-note {{candidate function}} + int i(); + int i(int); }; struct Y { - Y &operator<<(int); // expected-note{{candidate function not viable: no overload of 'i' matching 'int' for 1st argument}} + Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}} }; void f(X x, Y y) { - y << x.i; // expected-error{{cannot resolve overloaded function 'i' from context}} + y << x.i; // expected-error{{a bound member function may only be called}} } } diff --git a/clang/test/SemaCXX/ptrtomember.cpp b/clang/test/SemaCXX/ptrtomember.cpp index 8afcb112a36..c3917333a54 100644 --- a/clang/test/SemaCXX/ptrtomember.cpp +++ b/clang/test/SemaCXX/ptrtomember.cpp @@ -27,8 +27,7 @@ void f3(S3* p, void (S3::*m)()) { (void)(void*)(p->*m); // expected-error {{a bound member function may only be called}} (void)reinterpret_cast<void*>(p->*m); // expected-error {{a bound member function may only be called}} if (p->*m) {} // expected-error {{a bound member function may only be called}} - if (!p->*m) {} // FIXME: xpected-error {{a bound member function may only be called}} \ - // expected-error{{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'bool'}} + if (!(p->*m)) {} // expected-error {{a bound member function may only be called}} if (p->m) {}; // expected-error {{a bound member function may only be called}} - if (!p->m) {}; // FIXME: xpected-error {{a bound member function may only be called}} + if (!p->m) {}; // expected-error {{a bound member function may only be called}} } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index a50c987b3c2..a0e204d61fe 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1412,6 +1412,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { case BuiltinType::LongDouble: case BuiltinType::NullPtr: case BuiltinType::Overload: + case BuiltinType::BoundMember: case BuiltinType::Dependent: case BuiltinType::UnknownAny: break; diff --git a/clang/tools/libclang/CIndexUSRs.cpp b/clang/tools/libclang/CIndexUSRs.cpp index 30173d3e7ed..68871e94951 100644 --- a/clang/tools/libclang/CIndexUSRs.cpp +++ b/clang/tools/libclang/CIndexUSRs.cpp @@ -570,6 +570,7 @@ void USRGenerator::VisitType(QualType T) { case BuiltinType::NullPtr: c = 'n'; break; case BuiltinType::Overload: + case BuiltinType::BoundMember: case BuiltinType::Dependent: case BuiltinType::UnknownAny: IgnoreResults = true; |

