From 635ed24e1dad8c641877241f870c0698102722d4 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Wed, 5 Oct 2011 07:56:41 +0000 Subject: [PATCH] Added a flag to identify resolved overloaded function references. llvm-svn: 141171 --- clang/include/clang/AST/Expr.h | 37 +++++++- clang/include/clang/AST/ExprCXX.h | 31 ++++-- clang/include/clang/AST/Stmt.h | 1 + clang/include/clang/Sema/Initialization.h | 4 +- clang/include/clang/Sema/Overload.h | 7 +- clang/include/clang/Sema/Sema.h | 14 +-- clang/lib/AST/ASTImporter.cpp | 19 ++-- clang/lib/AST/ExprCXX.cpp | 16 +++- clang/lib/Sema/SemaDeclCXX.cpp | 17 ++-- clang/lib/Sema/SemaExprCXX.cpp | 21 ++++- clang/lib/Sema/SemaInit.cpp | 12 ++- clang/lib/Sema/SemaOverload.cpp | 109 +++++++++++++++------- clang/lib/Sema/TreeTransform.h | 15 +-- clang/lib/Serialization/ASTReaderStmt.cpp | 13 ++- clang/lib/Serialization/ASTWriterDecl.cpp | 1 + clang/lib/Serialization/ASTWriterStmt.cpp | 7 +- 16 files changed, 237 insertions(+), 87 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 694dd5c6fff0..34755623374d 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -770,6 +770,7 @@ public: DeclRefExprBits.HasQualifier = 0; DeclRefExprBits.HasExplicitTemplateArgs = 0; DeclRefExprBits.HasFoundDecl = 0; + DeclRefExprBits.HadMultipleCandidates = 0; computeDependence(); } @@ -923,6 +924,18 @@ public: return getExplicitTemplateArgs().RAngleLoc; } + /// \brief Returns true if this expression refers to a function that + /// was resolved from an overloaded set having size greater than 1. + bool hadMultipleCandidates() const { + return DeclRefExprBits.HadMultipleCandidates; + } + /// \brief Sets the flag telling whether this expression refers to + /// a function that was resolved from an overloaded set having size + /// greater than 1. + void setHadMultipleCandidates(bool V = true) { + DeclRefExprBits.HadMultipleCandidates = V; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -2021,6 +2034,10 @@ class MemberExpr : public Expr { /// the MemberNameQualifier structure. bool HasExplicitTemplateArgumentList : 1; + /// \brief True if this member expression refers to a method that + /// was resolved from an overloaded set having size greater than 1. + bool HadMultipleCandidates : 1; + /// \brief Retrieve the qualifier that preceded the member name, if any. MemberNameQualifier *getMemberQualifier() { assert(HasQualifierOrFoundDecl); @@ -2043,7 +2060,8 @@ public: base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) { + HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false), + HadMultipleCandidates(false) { assert(memberdecl->getDeclName() == NameInfo.getName()); } @@ -2060,7 +2078,8 @@ public: base->containsUnexpandedParameterPack()), Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} + HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false), + HadMultipleCandidates(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifierLoc QualifierLoc, @@ -2210,7 +2229,19 @@ public: bool isImplicitAccess() const { return getBase() && getBase()->isImplicitCXXThis(); } - + + /// \brief Returns true if this member expression refers to a method that + /// was resolved from an overloaded set having size greater than 1. + bool hadMultipleCandidates() const { + return HadMultipleCandidates; + } + /// \brief Sets the flag telling whether this expression refers to + /// a method that was resolved from an overloaded set having size + /// greater than 1. + void setHadMultipleCandidates(bool V = true) { + HadMultipleCandidates = V; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index d42d12e4b576..3cc09cdf5e45 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -809,6 +809,7 @@ private: SourceRange ParenRange; unsigned NumArgs : 16; bool Elidable : 1; + bool HadMultipleCandidates : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; @@ -818,26 +819,29 @@ protected: SourceLocation Loc, CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, + bool HadMultipleCandidates, bool ZeroInitialization = false, ConstructionKind ConstructKind = CK_Complete, SourceRange ParenRange = SourceRange()); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(0), - ZeroInitialization(0), ConstructKind(0), Args(0) { } + : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(0), + HadMultipleCandidates(false), ZeroInitialization(0), + ConstructKind(0), Args(0) { } public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) : Expr(CXXConstructExprClass, Empty), Constructor(0), - NumArgs(0), Elidable(0), ZeroInitialization(0), - ConstructKind(0), Args(0) { } + NumArgs(0), Elidable(0), HadMultipleCandidates(false), + ZeroInitialization(0), ConstructKind(0), Args(0) { } static CXXConstructExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, + bool HadMultipleCandidates, bool ZeroInitialization = false, ConstructionKind ConstructKind = CK_Complete, SourceRange ParenRange = SourceRange()); @@ -852,7 +856,12 @@ public: /// \brief Whether this construction is elidable. bool isElidable() const { return Elidable; } void setElidable(bool E) { Elidable = E; } - + + /// \brief Whether the referred constructor was resolved from + /// an overloaded set having size greater than 1. + bool hadMultipleCandidates() const { return HadMultipleCandidates; } + void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } + /// \brief Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } @@ -980,6 +989,7 @@ public: TypeSourceInfo *Type, Expr **Args,unsigned NumArgs, SourceRange parenRange, + bool HadMultipleCandidates, bool ZeroInitialization = false); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } @@ -1049,8 +1059,11 @@ class CXXNewExpr : public Expr { // If this is an array allocation, does the usual deallocation // function for the allocated type want to know the allocated size? bool UsualArrayDeleteWantsSize : 1; + // Whether the referred constructor (if any) was resolved from an + // overload set having size greater than 1. + bool HadMultipleCandidates : 1; // The number of placement new arguments. - unsigned NumPlacementArgs : 14; + unsigned NumPlacementArgs : 13; // The number of constructor arguments. This may be 1 even for non-class // types; use the pseudo copy constructor. unsigned NumConstructorArgs : 14; @@ -1086,6 +1099,7 @@ public: SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, + bool HadMultipleCandidates, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, QualType ty, TypeSourceInfo *AllocatedTypeInfo, SourceLocation startLoc, SourceLocation endLoc, @@ -1174,6 +1188,11 @@ public: return cast(SubExprs[Array + NumPlacementArgs + i]); } + /// \brief Whether the new expression refers a constructor that was + /// resolved from an overloaded set having size greater than 1. + bool hadMultipleCandidates() const { return HadMultipleCandidates; } + void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 3b0edccf02c6..8a3a74c2bdc2 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -165,6 +165,7 @@ protected: unsigned HasQualifier : 1; unsigned HasExplicitTemplateArgs : 1; unsigned HasFoundDecl : 1; + unsigned HadMultipleCandidates : 1; }; class CastExprBitfields { diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index ef592d2ab968..e69bebd56cff 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -568,10 +568,12 @@ public: /// When Kind == SK_ConstructorInitialization or SK_ListConstruction, /// the constructor to be called. /// - /// Always a FunctionDecl. + /// Always a FunctionDecl, plus a Boolean flag telling if it was + /// selected from an overloaded set having size greater than 1. /// For conversion decls, the naming class is the source type. /// For construct decls, the naming class is the target type. struct { + bool HadMultipleCandidates; FunctionDecl *Function; DeclAccessPair FoundDecl; } Function; diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 2dd85d5b2af3..dbc0926f03af 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -244,7 +244,12 @@ namespace clang { // a gcc code gen. bug which causes a crash in a test. Putting it here seems // to work around the crash. bool EllipsisConversion : 1; - + + /// HadMultipleCandidates - When this is true, it means that the + /// conversion function was resolved from an overloaded set having + /// size greater than 1. + bool HadMultipleCandidates : 1; + /// After - Represents the standard conversion that occurs after /// the actual user-defined conversion. StandardConversionSequence After; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b1b4da37af0c..bf8f9c81e485 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2685,7 +2685,8 @@ public: /// and sets it as the initializer for the the passed in VarDecl. bool InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, - MultiExprArg Exprs); + MultiExprArg Exprs, + bool HadMultipleCandidates); /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. @@ -2694,16 +2695,16 @@ public: ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool RequiresZeroInit, unsigned ConstructKind, - SourceRange ParenRange); + bool HadMultipleCandidates, bool RequiresZeroInit, + unsigned ConstructKind, SourceRange ParenRange); // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, - MultiExprArg Exprs, bool RequiresZeroInit, - unsigned ConstructKind, + MultiExprArg Exprs, bool HadMultipleCandidates, + bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating @@ -3360,7 +3361,8 @@ public: TypeSourceInfo *EncodedTypeInfo, SourceLocation RParenLoc); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, - CXXMethodDecl *Method); + CXXMethodDecl *Method, + bool HadMultipleCandidates); ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, SourceLocation EncodeLoc, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 37299d963344..e50dcbe4b004 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3837,14 +3837,17 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) return 0; - - return DeclRefExpr::Create(Importer.getToContext(), - Importer.Import(E->getQualifierLoc()), - ToD, - Importer.Import(E->getLocation()), - T, E->getValueKind(), - FoundD, - /*FIXME:TemplateArgs=*/0); + + DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), + Importer.Import(E->getQualifierLoc()), + ToD, + Importer.Import(E->getLocation()), + T, E->getValueKind(), + FoundD, + /*FIXME:TemplateArgs=*/0); + if (E->hadMultipleCandidates()) + DRE->setHadMultipleCandidates(true); + return DRE; } Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 95b03ee1832e..ad5ec8b8331a 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -49,6 +49,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, + bool HadMultipleCandidates, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, QualType ty, TypeSourceInfo *AllocatedTypeInfo, @@ -61,6 +62,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, ty->containsUnexpandedParameterPack()), GlobalNew(globalNew), Initializer(initializer), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), + HadMultipleCandidates(HadMultipleCandidates), SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), Constructor(constructor), AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), @@ -628,11 +630,13 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, Expr **Args, unsigned NumArgs, SourceRange parenRange, + bool HadMultipleCandidates, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), - Cons, false, Args, NumArgs, ZeroInitialization, + Cons, false, Args, NumArgs, + HadMultipleCandidates, ZeroInitialization, CXXConstructExpr::CK_Complete, parenRange), Type(Type) { } @@ -646,11 +650,13 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, + bool HadMultipleCandidates, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, - Elidable, Args, NumArgs, ZeroInitialization, + Elidable, Args, NumArgs, + HadMultipleCandidates, ZeroInitialization, ConstructKind, ParenRange); } @@ -658,7 +664,8 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool elidable, Expr **args, unsigned numargs, - bool ZeroInitialization, + bool HadMultipleCandidates, + bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) : Expr(SC, T, VK_RValue, OK_Ordinary, @@ -666,7 +673,8 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs), - Elidable(elidable), ZeroInitialization(ZeroInitialization), + Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), + ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(0) { if (NumArgs) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index bc0383165daf..4df525c6f3c3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8874,6 +8874,7 @@ ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, + bool HadMultipleCandidates, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { @@ -8896,8 +8897,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, } return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, - Elidable, move(ExprArgs), RequiresZeroInit, - ConstructKind, ParenRange); + Elidable, move(ExprArgs), HadMultipleCandidates, + RequiresZeroInit, ConstructKind, ParenRange); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -8906,6 +8907,7 @@ ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, + bool HadMultipleCandidates, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { @@ -8921,20 +8923,21 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, MarkDeclarationReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, - Constructor, Elidable, Exprs, NumExprs, - RequiresZeroInit, + Constructor, Elidable, Exprs, NumExprs, + HadMultipleCandidates, RequiresZeroInit, static_cast(ConstructKind), ParenRange)); } bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, - MultiExprArg Exprs) { + MultiExprArg Exprs, + bool HadMultipleCandidates) { // FIXME: Provide the correct paren SourceRange when available. ExprResult TempResult = BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - move(Exprs), false, CXXConstructExpr::CK_Complete, - SourceRange()); + move(Exprs), HadMultipleCandidates, false, + CXXConstructExpr::CK_Complete, SourceRange()); if (TempResult.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7571f7610c9d..16d9ae94f263 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1062,6 +1062,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, bool Init = ConstructorLParen.isValid(); // --- Choosing a constructor --- CXXConstructorDecl *Constructor = 0; + bool HadMultipleCandidates = false; Expr **ConsArgs = (Expr**)ConstructorArgs.get(); unsigned NumConsArgs = ConstructorArgs.size(); ASTOwningVector ConvertedConstructorArgs(*this); @@ -1108,6 +1109,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, if (CXXConstructExpr *Construct = dyn_cast(FullInitExpr)) { Constructor = Construct->getConstructor(); + HadMultipleCandidates = Construct->hadMultipleCandidates(); for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(), AEnd = Construct->arg_end(); A != AEnd; ++A) @@ -1149,7 +1151,9 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, PlaceArgs, NumPlaceArgs, TypeIdParens, ArraySize, Constructor, Init, - ConsArgs, NumConsArgs, OperatorDelete, + ConsArgs, NumConsArgs, + HadMultipleCandidates, + OperatorDelete, UsualArrayDeleteWantsSize, ResultType, AllocTypeInfo, StartLoc, @@ -2048,6 +2052,7 @@ static ExprResult BuildCXXCastArgument(Sema &S, CastKind Kind, CXXMethodDecl *Method, DeclAccessPair FoundDecl, + bool HadMultipleCandidates, Expr *From) { switch (Kind) { default: llvm_unreachable("Unhandled cast kind!"); @@ -2061,7 +2066,7 @@ static ExprResult BuildCXXCastArgument(Sema &S, ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast(Method), - move_arg(ConstructorArgs), + move_arg(ConstructorArgs), HadMultipleCandidates, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (Result.isInvalid()) @@ -2074,7 +2079,8 @@ static ExprResult BuildCXXCastArgument(Sema &S, assert(!From->getType()->isPointerType() && "Arg can't have pointer type!"); // Create an implicit call expr that calls it. - ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Method); + ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Method, + HadMultipleCandidates); if (Result.isInvalid()) return ExprError(); @@ -2145,6 +2151,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType.getNonReferenceType(), CastKind, cast(FD), ICS.UserDefined.FoundConversionFunction, + ICS.UserDefined.HadMultipleCandidates, From); if (CastArg.isInvalid()) @@ -2204,6 +2211,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, move_arg(ConstructorArgs), + /*HadMultipleCandidates*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -2211,6 +2219,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, MultiExprArg(*this, &From, 1), + /*HadMultipleCandidates*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -4520,7 +4529,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, - CXXMethodDecl *Method) { + CXXMethodDecl *Method, + bool HadMultipleCandidates) { ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0, FoundDecl, Method); if (Exp.isInvalid()) @@ -4530,6 +4540,9 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method, SourceLocation(), Method->getType(), VK_RValue, OK_Ordinary); + if (HadMultipleCandidates) + ME->setHadMultipleCandidates(true); + QualType ResultType = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 145a7ecaba4c..30abef5d834f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4140,6 +4140,8 @@ static ExprResult CopyObject(Sema &S, &CurInitExpr, 1, CandidateSet, true); } + bool HadMultipleCandidates = (CandidateSet.size() > 1); + OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(S, Loc, Best)) { case OR_Success: @@ -4217,6 +4219,7 @@ static ExprResult CopyObject(Sema &S, // Actually perform the constructor call. CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, move_arg(ConstructorArgs), + HadMultipleCandidates, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -4478,6 +4481,7 @@ InitializationSequence::Perform(Sema &S, bool IsCopy = false; FunctionDecl *Fn = Step->Function.Function; DeclAccessPair FoundFn = Step->Function.FoundDecl; + bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; bool CreatedObject = false; if (CXXConstructorDecl *Constructor = dyn_cast(Fn)) { // Build a call to the selected constructor. @@ -4496,6 +4500,7 @@ InitializationSequence::Perform(Sema &S, // Build the an expression that constructs a temporary. CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, move_arg(ConstructorArgs), + HadMultipleCandidates, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -4531,7 +4536,8 @@ InitializationSequence::Perform(Sema &S, CurInit = move(CurInitExprRes); // Build the actual call to the conversion function. - CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion); + CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, + HadMultipleCandidates); if (CurInit.isInvalid() || !CurInit.get()) return ExprError(); @@ -4616,6 +4622,7 @@ InitializationSequence::Perform(Sema &S, unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast(Step->Function.Function); + bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; // Build a call to the selected constructor. ASTOwningVector ConstructorArgs(S); @@ -4662,6 +4669,7 @@ InitializationSequence::Perform(Sema &S, Exprs, NumExprs, Kind.getParenRange(), + HadMultipleCandidates, ConstructorInitRequiresZeroInit)); } else { CXXConstructExpr::ConstructionKind ConstructKind = @@ -4686,6 +4694,7 @@ InitializationSequence::Perform(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), Constructor, /*Elidable=*/true, move_arg(ConstructorArgs), + HadMultipleCandidates, ConstructorInitRequiresZeroInit, ConstructKind, parenRange); @@ -4693,6 +4702,7 @@ InitializationSequence::Perform(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), Constructor, move_arg(ConstructorArgs), + HadMultipleCandidates, ConstructorInitRequiresZeroInit, ConstructKind, parenRange); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 6174bbac73c5..c968498d00b7 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -37,11 +37,14 @@ using namespace sema; /// A convenience routine for creating a decayed reference to a /// function. static ExprResult -CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, +CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates, SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ - ExprResult E = S.Owned(new (S.Context) DeclRefExpr(Fn, Fn->getType(), - VK_LValue, Loc, LocInfo)); + DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, Fn->getType(), + VK_LValue, Loc, LocInfo); + if (HadMultipleCandidates) + DRE->setHadMultipleCandidates(true); + ExprResult E = S.Owned(DRE); E = S.DefaultFunctionArrayConversion(E.take()); if (E.isInvalid()) return ExprError(); @@ -2496,6 +2499,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } } + bool HadMultipleCandidates = (CandidateSet.size() > 1); + OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { case OR_Success: @@ -2517,6 +2522,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.Before = Best->Conversions[0].Standard; User.EllipsisConversion = false; } + User.HadMultipleCandidates = HadMultipleCandidates; User.ConversionFunction = Constructor; User.FoundConversionFunction = Best->FoundDecl; User.After.setAsIdentityConversion(); @@ -2534,6 +2540,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // conversion sequence converts the source type to the // implicit object parameter of the conversion function. User.Before = Best->Conversions[0].Standard; + User.HadMultipleCandidates = HadMultipleCandidates; User.ConversionFunction = Conversion; User.FoundConversionFunction = Best->FoundDecl; User.EllipsisConversion = false; @@ -3364,6 +3371,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, DeclType, CandidateSet); } + bool HadMultipleCandidates = (CandidateSet.size() > 1); + OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) { case OR_Success: @@ -3385,6 +3394,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, ICS.setUserDefined(); ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; + ICS.UserDefined.HadMultipleCandidates = HadMultipleCandidates; ICS.UserDefined.ConversionFunction = Best->Function; ICS.UserDefined.FoundConversionFunction = Best->FoundDecl; ICS.UserDefined.EllipsisConversion = false; @@ -4050,6 +4060,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, const UnresolvedSetImpl *Conversions = cast(RecordTy->getDecl())->getVisibleConversionFunctions(); + bool HadMultipleCandidates = (Conversions->size() > 1); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), E = Conversions->end(); I != E; @@ -4094,7 +4106,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, return ExprError(); CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); - ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion); + ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, + HadMultipleCandidates); if (Result.isInvalid()) return ExprError(); @@ -4121,8 +4134,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); } - ExprResult Result = BuildCXXMemberCallExpr(From, Found, - cast(Found->getUnderlyingDecl())); + ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, + HadMultipleCandidates); if (Result.isInvalid()) return ExprError(); @@ -4794,6 +4807,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.Conversions[0].setUserDefined(); Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard; Candidate.Conversions[0].UserDefined.EllipsisConversion = false; + Candidate.Conversions[0].UserDefined.HadMultipleCandidates = false; Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion; Candidate.Conversions[0].UserDefined.FoundConversionFunction = FoundDecl; Candidate.Conversions[0].UserDefined.After @@ -8621,6 +8635,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); + bool HadMultipleCandidates = (CandidateSet.size() > 1); + // Perform overload resolution. OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { @@ -8665,7 +8681,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + HadMultipleCandidates); if (FnExpr.isInvalid()) return ExprError(); @@ -8869,6 +8886,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); + bool HadMultipleCandidates = (CandidateSet.size() > 1); + // Perform overload resolution. OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { @@ -8930,7 +8949,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -9080,6 +9100,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Add builtin operator candidates. AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + bool HadMultipleCandidates = (CandidateSet.size() > 1); + // Perform overload resolution. OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) { @@ -9126,7 +9148,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, DeclarationNameLoc LocInfo; LocInfo.CXXOperatorName.BeginOpNameLoc = LLoc.getRawEncoding(); LocInfo.CXXOperatorName.EndOpNameLoc = RLoc.getRawEncoding(); - ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc, LocInfo); + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + HadMultipleCandidates, + LLoc, LocInfo); if (FnExpr.isInvalid()) return ExprError(); @@ -9520,6 +9544,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, } } + bool HadMultipleCandidates = (CandidateSet.size() > 1); + // Perform overload resolution. OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(), @@ -9578,7 +9604,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // Create an implicit member expr to refer to the conversion operator. // and then call it. - ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, Conv); + ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, + Conv, HadMultipleCandidates); if (Call.isInvalid()) return ExprError(); @@ -9614,7 +9641,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) MethodArgs[ArgIdx + 1] = Args[ArgIdx]; - ExprResult NewFn = CreateFunctionRefExpr(*this, Method); + ExprResult NewFn = CreateFunctionRefExpr(*this, Method, + HadMultipleCandidates); if (NewFn.isInvalid()) return true; @@ -9744,6 +9772,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { 0, 0, CandidateSet, /*SuppressUserConversions=*/false); } + bool HadMultipleCandidates = (CandidateSet.size() > 1); + // Perform overload resolution. OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { @@ -9791,7 +9821,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { Base = BaseResult.take(); // Build the operator call. - ExprResult FnExpr = CreateFunctionRefExpr(*this, Method); + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, + HadMultipleCandidates); if (FnExpr.isInvalid()) return ExprError(); @@ -9894,14 +9925,16 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, TemplateArgs = &TemplateArgsBuffer; } - return DeclRefExpr::Create(Context, - ULE->getQualifierLoc(), - Fn, - ULE->getNameLoc(), - Fn->getType(), - VK_LValue, - Found.getDecl(), - TemplateArgs); + DeclRefExpr *DRE = DeclRefExpr::Create(Context, + ULE->getQualifierLoc(), + Fn, + ULE->getNameLoc(), + Fn->getType(), + VK_LValue, + Found.getDecl(), + TemplateArgs); + DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1); + return DRE; } if (UnresolvedMemberExpr *MemExpr = dyn_cast(E)) { @@ -9918,14 +9951,16 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, // implicit member access, rewrite to a simple decl ref. if (MemExpr->isImplicitAccess()) { if (cast(Fn)->isStatic()) { - return DeclRefExpr::Create(Context, - MemExpr->getQualifierLoc(), - Fn, - MemExpr->getMemberLoc(), - Fn->getType(), - VK_LValue, - Found.getDecl(), - TemplateArgs); + DeclRefExpr *DRE = DeclRefExpr::Create(Context, + MemExpr->getQualifierLoc(), + Fn, + MemExpr->getMemberLoc(), + Fn->getType(), + VK_LValue, + Found.getDecl(), + TemplateArgs); + DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1); + return DRE; } else { SourceLocation Loc = MemExpr->getMemberLoc(); if (MemExpr->getQualifier()) @@ -9947,14 +9982,16 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, type = Context.BoundMemberTy; } - return MemberExpr::Create(Context, Base, - MemExpr->isArrow(), - MemExpr->getQualifierLoc(), - Fn, - Found, - MemExpr->getMemberNameInfo(), - TemplateArgs, - type, valueKind, OK_Ordinary); + MemberExpr *ME = MemberExpr::Create(Context, Base, + MemExpr->isArrow(), + MemExpr->getQualifierLoc(), + Fn, + Found, + MemExpr->getMemberNameInfo(), + TemplateArgs, + type, valueKind, OK_Ordinary); + ME->setHadMultipleCandidates(true); + return ME; } llvm_unreachable("Invalid reference to overloaded function"); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 99ddd239129f..62c6d18b59f9 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2031,13 +2031,14 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXConstructExpr(QualType T, - SourceLocation Loc, - CXXConstructorDecl *Constructor, - bool IsElidable, - MultiExprArg Args, - bool RequiresZeroInit, + SourceLocation Loc, + CXXConstructorDecl *Constructor, + bool IsElidable, + MultiExprArg Args, + bool HadMultipleCandidates, + bool RequiresZeroInit, CXXConstructExpr::ConstructionKind ConstructKind, - SourceRange ParenRange) { + SourceRange ParenRange) { ASTOwningVector ConvertedArgs(SemaRef); if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc, ConvertedArgs)) @@ -2045,6 +2046,7 @@ public: return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, move_arg(ConvertedArgs), + HadMultipleCandidates, RequiresZeroInit, ConstructKind, ParenRange); } @@ -7345,6 +7347,7 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(), Constructor, E->isElidable(), move_arg(Args), + E->hadMultipleCandidates(), E->requiresZeroInitialization(), E->getConstructionKind(), E->getParenRange()); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index e2a78e9d1eaf..7653d5f2906c 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -327,6 +327,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.HasQualifier = Record[Idx++]; E->DeclRefExprBits.HasFoundDecl = Record[Idx++]; E->DeclRefExprBits.HasExplicitTemplateArgs = Record[Idx++]; + E->DeclRefExprBits.HadMultipleCandidates = Record[Idx++]; unsigned NumTemplateArgs = 0; if (E->hasExplicitTemplateArgs()) NumTemplateArgs = Record[Idx++]; @@ -986,7 +987,8 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->setArg(I, Reader.ReadSubExpr()); E->setConstructor(ReadDeclAs(Record, Idx)); E->setLocation(ReadSourceLocation(Record, Idx)); - E->setElidable(Record[Idx++]); + E->setElidable(Record[Idx++]); + E->setHadMultipleCandidates(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); E->ParenRange = ReadSourceRange(Record, Idx); @@ -1090,6 +1092,7 @@ void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { E->Initializer = Record[Idx++]; E->UsualArrayDeleteWantsSize = Record[Idx++]; bool isArray = Record[Idx++]; + E->setHadMultipleCandidates(Record[Idx++]); unsigned NumPlacementArgs = Record[Idx++]; unsigned NumCtorArgs = Record[Idx++]; E->setOperatorNew(ReadDeclAs(Record, Idx)); @@ -1549,7 +1552,7 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1], /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2], /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ? - Record[ASTStmtReader::NumExprFields + 3] : 0); + Record[ASTStmtReader::NumExprFields + 4] : 0); break; case EXPR_INTEGER_LITERAL: @@ -1623,7 +1626,9 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { for (unsigned i = 0; i != NumTemplateArgs; ++i) ArgInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Idx)); } - + + bool HadMultipleCandidates = Record[Idx++]; + NamedDecl *FoundD = ReadDeclAs(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); @@ -1642,6 +1647,8 @@ Stmt *ASTReader::ReadStmtFromStream(Module &F) { HasExplicitTemplateArgs ? &ArgInfo : 0, T, VK, OK); ReadDeclarationNameLoc(F, cast(S)->MemberDNLoc, MemberD->getDeclName(), Record, Idx); + if (HadMultipleCandidates) + cast(S)->setHadMultipleCandidates(true); break; } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 81394c25d066..c5e06d7bf492 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1538,6 +1538,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(Abv); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index b7d7afdfa842..fb5617551e95 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -265,6 +265,7 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { Record.push_back(E->hasQualifier()); Record.push_back(E->getDecl() != E->getFoundDecl()); Record.push_back(E->hasExplicitTemplateArgs()); + Record.push_back(E->hadMultipleCandidates()); if (E->hasExplicitTemplateArgs()) { unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -457,7 +458,9 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { for (unsigned i=0; i != NumTemplateArgs; ++i) Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); } - + + Record.push_back(E->hadMultipleCandidates()); + DeclAccessPair FoundDecl = E->getFoundDecl(); Writer.AddDeclRef(FoundDecl.getDecl(), Record); Record.push_back(FoundDecl.getAccess()); @@ -958,6 +961,7 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Writer.AddDeclRef(E->getConstructor(), Record); Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->isElidable()); + Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding Writer.AddSourceRange(E->getParenRange(), Record); @@ -1077,6 +1081,7 @@ void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { Record.push_back(E->hasInitializer()); Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->isArray()); + Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->getNumPlacementArgs()); Record.push_back(E->getNumConstructorArgs()); Writer.AddDeclRef(E->getOperatorNew(), Record);