From 9821058530c8aa4d14cfadb324194245032a1c91 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 11 May 2016 20:37:46 +0000 Subject: [PATCH] Preserve the FoundDecl when performing overload resolution for constructors. This is in preparation for C++ P0136R1, which switches the model for inheriting constructors over from synthesizing a constructor to finding base class constructors (via using shadow decls) when looking for derived class constructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269231 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 38 ++++--- include/clang/Sema/Overload.h | 30 ++++- include/clang/Sema/Sema.h | 5 +- include/clang/Sema/TemplateDeduction.h | 7 +- lib/AST/ASTImporter.cpp | 9 +- lib/AST/ExprCXX.cpp | 44 +++++--- lib/CodeGen/CGObjC.cpp | 1 + lib/Sema/SemaDeclCXX.cpp | 14 ++- lib/Sema/SemaExprCXX.cpp | 8 +- lib/Sema/SemaInit.cpp | 126 +++++++++------------ lib/Sema/SemaLookup.cpp | 2 +- lib/Sema/SemaOverload.cpp | 146 +++++++++++-------------- lib/Sema/SemaTemplate.cpp | 16 +-- lib/Sema/SemaTemplateInstantiate.cpp | 5 +- lib/Sema/TreeTransform.h | 14 ++- 15 files changed, 251 insertions(+), 214 deletions(-) diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index adb5b18616..f4f653f4bb 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/LambdaCapture.h" #include "clang/AST/TemplateBase.h" @@ -26,9 +27,6 @@ namespace clang { -class CXXConstructorDecl; -class CXXDestructorDecl; -class CXXMethodDecl; class CXXTemporary; class MSPropertyDecl; class TemplateArgumentListInfo; @@ -1168,18 +1166,21 @@ private: SourceLocation Loc; SourceRange ParenOrBraceRange; unsigned NumArgs : 16; - bool Elidable : 1; - bool HadMultipleCandidates : 1; - bool ListInitialization : 1; - bool StdInitListInitialization : 1; - bool ZeroInitialization : 1; + unsigned Elidable : 1; + unsigned HadMultipleCandidates : 1; + unsigned ListInitialization : 1; + unsigned StdInitListInitialization : 1; + unsigned ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; + void setConstructor(CXXConstructorDecl *C) { Constructor = C; } + protected: CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, - CXXConstructorDecl *d, bool elidable, + NamedDecl *Found, CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, @@ -1198,15 +1199,13 @@ protected: public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) - : Expr(CXXConstructExprClass, Empty), Constructor(nullptr), - NumArgs(0), Elidable(false), HadMultipleCandidates(false), - ListInitialization(false), ZeroInitialization(false), - ConstructKind(0), Args(nullptr) - { } + : CXXConstructExpr(CXXConstructExprClass, Empty) {} static CXXConstructExpr *Create(const ASTContext &C, QualType T, SourceLocation Loc, - CXXConstructorDecl *D, bool Elidable, + NamedDecl *Found, + CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, @@ -1215,8 +1214,11 @@ public: ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); + /// \brief Get the declaration that was found by name lookup. + NamedDecl *getFoundDecl() const; + + /// \brief Get the constructor that this expression will (ultimately) call. CXXConstructorDecl *getConstructor() const { return Constructor; } - void setConstructor(CXXConstructorDecl *C) { Constructor = C; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation Loc) { this->Loc = Loc; } @@ -1382,7 +1384,9 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr { TypeSourceInfo *Type; public: - CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, + CXXTemporaryObjectExpr(const ASTContext &C, + NamedDecl *Found, + CXXConstructorDecl *Cons, TypeSourceInfo *Type, ArrayRef Args, SourceRange ParenOrBraceRange, diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 62437953b3..abc1a07840 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -199,6 +199,7 @@ namespace clang { /// conversions are either identity conversions or derived-to-base /// conversions. CXXConstructorDecl *CopyConstructor; + DeclAccessPair FoundCopyConstructor; void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } void setToType(unsigned Idx, QualType T) { @@ -282,7 +283,7 @@ namespace clang { /// Represents an ambiguous user-defined conversion sequence. struct AmbiguousConversionSequence { - typedef SmallVector ConversionSet; + typedef SmallVector, 4> ConversionSet; void *FromTypePtr; void *ToTypePtr; @@ -305,8 +306,8 @@ namespace clang { return *reinterpret_cast(Buffer); } - void addConversion(FunctionDecl *D) { - conversions().push_back(D); + void addConversion(NamedDecl *Found, FunctionDecl *D) { + conversions().push_back(std::make_pair(Found, D)); } typedef ConversionSet::iterator iterator; @@ -797,6 +798,29 @@ namespace clang { const OverloadCandidate& Cand2, SourceLocation Loc, bool UserDefinedConversion = false); + + struct ConstructorInfo { + DeclAccessPair FoundDecl; + CXXConstructorDecl *Constructor; + FunctionTemplateDecl *ConstructorTmpl; + }; + // FIXME: Add an AddOverloadCandidate / AddTemplateOverloadCandidate overload + // that takes one of these. + inline ConstructorInfo getConstructorInfo(NamedDecl *ND) { + if (isa(ND)) + return ConstructorInfo{}; + + // For constructors, the access check is performed against the underlying + // declaration, not the found declaration. + auto *D = ND->getUnderlyingDecl(); + ConstructorInfo Info = {DeclAccessPair::make(ND, D->getAccess()), nullptr, + nullptr}; + Info.ConstructorTmpl = dyn_cast(D); + if (Info.ConstructorTmpl) + D = Info.ConstructorTmpl->getTemplatedDecl(); + Info.Constructor = cast(D); + return Info; + } } // end namespace clang #endif // LLVM_CLANG_SEMA_OVERLOAD_H diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index dff303124d..0d1a0af780 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2526,7 +2526,8 @@ public: bool PartialOverloading = false); // Emit as a 'note' the specific overload candidate - void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType(), + void NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, + QualType DestType = QualType(), bool TakingAddress = false); // Emit as a series of 'note's all template and non-templates identified by @@ -4273,6 +4274,7 @@ public: /// \param ConstructKind - a CXXConstructExpr::ConstructionKind ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, MultiExprArg Exprs, bool HadMultipleCandidates, bool IsListInitialization, bool IsStdInitListInitialization, @@ -4283,6 +4285,7 @@ public: // the constructor can be elidable? ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool HadMultipleCandidates, bool IsListInitialization, diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index c22c703ef7..ed1e768832 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -244,6 +244,10 @@ struct DeductionFailureInfo { /// TODO: In the future, we may need to unify/generalize this with /// OverloadCandidate. struct TemplateSpecCandidate { + /// \brief The declaration that was looked up, together with its access. + /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl. + DeclAccessPair FoundDecl; + /// Specialization - The actual specialization that this candidate /// represents. When NULL, this may be a built-in candidate. Decl *Specialization; @@ -251,7 +255,8 @@ struct TemplateSpecCandidate { /// Template argument deduction info DeductionFailureInfo DeductionFailure; - void set(Decl *Spec, DeductionFailureInfo Info) { + void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) { + FoundDecl = Found; Specialization = Spec; DeductionFailure = Info; } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 747f9fc9bd..8665d809ae 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -5767,9 +5767,14 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { if (T.isNull()) return nullptr; + NamedDecl *ToFound = + dyn_cast(Importer.Import(E->getFoundDecl())); + if (!ToFound) + return nullptr; + CXXConstructorDecl *ToCCD = dyn_cast(Importer.Import(E->getConstructor())); - if (!ToCCD && E->getConstructor()) + if (!ToCCD) return nullptr; SmallVector ToArgs(E->getNumArgs()); @@ -5779,7 +5784,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { return CXXConstructExpr::Create(Importer.getToContext(), T, Importer.Import(E->getLocation()), - ToCCD, E->isElidable(), + ToFound, ToCCD, E->isElidable(), ToArgs, E->hadMultipleCandidates(), E->isListInitialization(), E->isStdInitListInitialization(), diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 6bd03b5f9a..dbfe58c8b3 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -432,6 +432,12 @@ SourceLocation CXXConstructExpr::getLocEnd() const { return End; } +NamedDecl *CXXConstructExpr::getFoundDecl() const { + if (auto *Template = Constructor->getPrimaryTemplate()) + return Template; + return Constructor; +} + SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const { OverloadedOperatorKind Kind = getOperator(); if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) { @@ -717,6 +723,7 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C, } CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, + NamedDecl *Found, CXXConstructorDecl *Cons, TypeSourceInfo *Type, ArrayRef Args, @@ -728,7 +735,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), - Cons, false, Args, + Found, Cons, false, Args, HadMultipleCandidates, ListInitialization, StdInitListInitialization, @@ -750,7 +757,9 @@ SourceLocation CXXTemporaryObjectExpr::getLocEnd() const { CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, SourceLocation Loc, - CXXConstructorDecl *D, bool Elidable, + NamedDecl *Found, + CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, @@ -758,8 +767,8 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) { - return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, - Elidable, Args, + return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, + Found, Ctor, Elidable, Args, HadMultipleCandidates, ListInitialization, StdInitListInitialization, ZeroInitialization, ConstructKind, @@ -768,8 +777,9 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, - CXXConstructorDecl *D, bool elidable, - ArrayRef args, + NamedDecl *Found, CXXConstructorDecl *Ctor, + bool Elidable, + ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, @@ -780,28 +790,30 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, T->isDependentType(), T->isDependentType(), T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), - Constructor(D), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), - NumArgs(args.size()), - Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), + Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), + NumArgs(Args.size()), + Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates), ListInitialization(ListInitialization), StdInitListInitialization(StdInitListInitialization), ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(nullptr) { + assert(declaresSameEntity(Found, Ctor) || + declaresSameEntity(Found, Ctor->getPrimaryTemplate())); if (NumArgs) { - Args = new (C) Stmt*[args.size()]; + this->Args = new (C) Stmt*[Args.size()]; - for (unsigned i = 0; i != args.size(); ++i) { - assert(args[i] && "NULL argument in CXXConstructExpr"); + for (unsigned i = 0; i != Args.size(); ++i) { + assert(Args[i] && "NULL argument in CXXConstructExpr"); - if (args[i]->isValueDependent()) + if (Args[i]->isValueDependent()) ExprBits.ValueDependent = true; - if (args[i]->isInstantiationDependent()) + if (Args[i]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (args[i]->containsUnexpandedParameterPack()) + if (Args[i]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - Args[i] = args[i]; + this->Args[i] = Args[i]; } } } diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index df571de1b8..7fb6a36590 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -3305,6 +3305,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( CXXConstructExpr *TheCXXConstructExpr = CXXConstructExpr::Create(C, Ty, SourceLocation(), + CXXConstExpr->getFoundDecl(), CXXConstExpr->getConstructor(), CXXConstExpr->isElidable(), ConstructorArgs, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 95f10f8ccc..5967c20ea6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -11369,6 +11369,7 @@ static bool hasOneRealArgument(MultiExprArg Args) { ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool HadMultipleCandidates, @@ -11395,7 +11396,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); } - return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, + return BuildCXXConstructExpr(ConstructLoc, DeclInitType, + FoundDecl, Constructor, Elidable, ExprArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, RequiresZeroInit, @@ -11406,7 +11408,9 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, /// including handling of its default argument expressions. ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, - CXXConstructorDecl *Constructor, bool Elidable, + NamedDecl *FoundDecl, + CXXConstructorDecl *Constructor, + bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, @@ -11416,9 +11420,9 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, SourceRange ParenRange) { MarkFunctionReferenced(ConstructLoc, Constructor); return CXXConstructExpr::Create( - Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, - HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, - RequiresZeroInit, + Context, DeclInitType, ConstructLoc, FoundDecl, Constructor, Elidable, + ExprArgs, HadMultipleCandidates, IsListInitialization, + IsStdInitListInitialization, RequiresZeroInit, static_cast(ConstructKind), ParenRange); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3e95076486..67d2cdbb07 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3077,7 +3077,7 @@ static ExprResult BuildCXXCastArgument(Sema &S, return ExprError(); ExprResult Result = S.BuildCXXConstructExpr( - CastLoc, Ty, cast(Method), + CastLoc, Ty, FoundDecl, cast(Method), ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -3228,13 +3228,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ConstructorArgs)) return ExprError(); return BuildCXXConstructExpr( - /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor, + /*FIXME:ConstructLoc*/ SourceLocation(), ToType, + SCS.FoundCopyConstructor, SCS.CopyConstructor, ConstructorArgs, /*HadMultipleCandidates*/ false, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } return BuildCXXConstructExpr( - /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor, + /*FIXME:ConstructLoc*/ SourceLocation(), ToType, + SCS.FoundCopyConstructor, SCS.CopyConstructor, From, /*HadMultipleCandidates*/ false, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 81b5312d87..5b82cb97b5 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3449,18 +3449,13 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, CandidateSet.clear(); for (NamedDecl *D : Ctors) { - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - bool SuppressUserConversions = false; + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl = dyn_cast(D); - if (ConstructorTmpl) - Constructor = cast( - ConstructorTmpl->getTemplatedDecl()); - else { - Constructor = cast(D); + bool SuppressUserConversions = false; + if (!Info.ConstructorTmpl) { // C++11 [over.best.ics]p4: // ... and the constructor or user-defined conversion function is a // candidate by @@ -3477,15 +3472,15 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, // parameter of a constructor of X. if ((CopyInitializing || (IsListInit && Args.size() == 1 && isa(Args[0]))) && - Constructor->isCopyOrMoveConstructor()) + Info.Constructor->isCopyOrMoveConstructor()) SuppressUserConversions = true; } - if (!Constructor->isInvalidDecl() && - (AllowExplicit || !Constructor->isExplicit()) && - (!OnlyListConstructors || S.isInitListConstructor(Constructor))) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + if (!Info.Constructor->isInvalidDecl() && + (AllowExplicit || !Info.Constructor->isExplicit()) && + (!OnlyListConstructors || S.isInitListConstructor(Info.Constructor))) { + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions); else { @@ -3497,9 +3492,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, // are also considered. bool AllowExplicitConv = AllowExplicit && !CopyInitializing && Args.size() == 1 && - Constructor->isCopyOrMoveConstructor(); - S.AddOverloadCandidate(Constructor, FoundDecl, Args, CandidateSet, - SuppressUserConversions, + Info.Constructor->isCopyOrMoveConstructor(); + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, + CandidateSet, SuppressUserConversions, /*PartialOverloading=*/false, /*AllowExplicit=*/AllowExplicitConv); } @@ -3991,26 +3986,19 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, CXXRecordDecl *T1RecordDecl = cast(T1RecordType->getDecl()); for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) { - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl = dyn_cast(D); - if (ConstructorTmpl) - Constructor = cast( - ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast(D); + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + if (!Info.Constructor->isInvalidDecl() && + Info.Constructor->isConvertingConstructor(AllowExplicit)) { + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } @@ -4614,27 +4602,19 @@ static void TryUserDefinedConversion(Sema &S, Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl - = dyn_cast(D); - if (ConstructorTmpl) - Constructor = cast( - ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast(D); + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + if (!Info.Constructor->isInvalidDecl() && + Info.Constructor->isConvertingConstructor(AllowExplicit)) { + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } @@ -5378,38 +5358,33 @@ static void LookupCopyAndMoveConstructors(Sema &S, for (SmallVectorImpl::iterator CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { NamedDecl *D = *CI; - CXXConstructorDecl *Constructor = nullptr; + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - if ((Constructor = dyn_cast(D))) { - // Handle copy/moveconstructors, only. - if (!Constructor || Constructor->isInvalidDecl() || - !Constructor->isCopyOrMoveConstructor() || - !Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + if (!Info.ConstructorTmpl) { + // Handle copy/move constructors, only. + if (Info.Constructor->isInvalidDecl() || + !Info.Constructor->isCopyOrMoveConstructor() || + !Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) continue; - DeclAccessPair FoundDecl - = DeclAccessPair::make(Constructor, Constructor->getAccess()); - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, CurInitExpr, CandidateSet); continue; } // Handle constructor templates. - FunctionTemplateDecl *ConstructorTmpl = cast(D); - if (ConstructorTmpl->isInvalidDecl()) + if (Info.ConstructorTmpl->isInvalidDecl()) continue; - Constructor = cast( - ConstructorTmpl->getTemplatedDecl()); - if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + if (!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) continue; // FIXME: Do we need to limit this to copy-constructor-like // candidates? - DeclAccessPair FoundDecl - = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess()); - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, nullptr, - CurInitExpr, CandidateSet, true); + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, + nullptr, CurInitExpr, CandidateSet, true); } } @@ -5584,7 +5559,8 @@ static ExprResult CopyObject(Sema &S, return ExprError(); // Actually perform the constructor call. - CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, + CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor, + Elidable, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, @@ -5770,9 +5746,10 @@ PerformConstructorInitialization(Sema &S, : Kind.getParenRange(); CurInit = new (S.Context) CXXTemporaryObjectExpr( - S.Context, Constructor, TSInfo, ConstructorArgs, ParenOrBraceRange, - HadMultipleCandidates, IsListInitialization, - IsStdInitListInitialization, ConstructorInitRequiresZeroInit); + S.Context, Step.Function.FoundDecl, Constructor, TSInfo, + ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, + IsListInitialization, IsStdInitListInitialization, + ConstructorInitRequiresZeroInit); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; @@ -5797,6 +5774,7 @@ PerformConstructorInitialization(Sema &S, // unconditionally. if (Entity.allowsNRVO()) CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Step.Function.FoundDecl, Constructor, /*Elidable=*/true, ConstructorArgs, HadMultipleCandidates, @@ -5807,6 +5785,7 @@ PerformConstructorInitialization(Sema &S, ParenOrBraceRange); else CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Step.Function.FoundDecl, Constructor, ConstructorArgs, HadMultipleCandidates, @@ -6511,7 +6490,8 @@ InitializationSequence::Perform(Sema &S, return ExprError(); // Build an expression that constructs a temporary. - CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, + CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, + FoundFn, Constructor, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index f1eed0e156..5490d7568c 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3196,7 +3196,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FoundRaw && FoundTemplate) { Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction()); + NoteOverloadCandidate(*I, (*I)->getUnderlyingDecl()->getAsFunction()); return LOLR_Error; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 415eda02ec..1c41487f5a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1218,11 +1218,13 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) { // Turn this into a "standard" conversion sequence, so that it // gets ranked with standard conversion sequences. + DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction; ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); ICS.Standard.setFromType(From->getType()); ICS.Standard.setAllToTypes(ToType); ICS.Standard.CopyConstructor = Constructor; + ICS.Standard.FoundCopyConstructor = Found; if (ToCanon != FromCanon) ICS.Standard.Second = ICK_Derived_To_Base; } @@ -1236,7 +1238,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, for (OverloadCandidateSet::iterator Cand = Conversions.begin(); Cand != Conversions.end(); ++Cand) if (Cand->Viable) - ICS.Ambiguous.addConversion(Cand->Function); + ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function); break; // Fall through. @@ -3051,39 +3053,26 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, UserDefinedConversionSequence &User, OverloadCandidateSet &CandidateSet, bool AllowExplicit) { - DeclContext::lookup_result R = S.LookupConstructors(To); - for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end(); - Con != ConEnd; ++Con) { - NamedDecl *D = *Con; - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl - = dyn_cast(D); - if (ConstructorTmpl) - Constructor - = cast(ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast(D); + for (auto *D : S.LookupConstructors(To)) { + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - bool Usable = !Constructor->isInvalidDecl() && - S.isInitListConstructor(Constructor) && - (AllowExplicit || !Constructor->isExplicit()); + bool Usable = !Info.Constructor->isInvalidDecl() && + S.isInitListConstructor(Info.Constructor) && + (AllowExplicit || !Info.Constructor->isExplicit()); if (Usable) { // If the first argument is (a reference to) the target type, // suppress conversions. - bool SuppressUserConversions = - isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType); - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, - /*ExplicitArgs*/ nullptr, - From, CandidateSet, - SuppressUserConversions); + bool SuppressUserConversions = isFirstArgumentCompatibleWithType( + S.Context, Info.Constructor, ToType); + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, + /*ExplicitArgs*/ nullptr, From, + CandidateSet, SuppressUserConversions); else - S.AddOverloadCandidate(Constructor, FoundDecl, - From, CandidateSet, - SuppressUserConversions); + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From, + CandidateSet, SuppressUserConversions); } } @@ -3183,27 +3172,17 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, ListInitializing = true; } - DeclContext::lookup_result R = S.LookupConstructors(ToRecordDecl); - for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end(); - Con != ConEnd; ++Con) { - NamedDecl *D = *Con; - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl - = dyn_cast(D); - if (ConstructorTmpl) - Constructor - = cast(ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast(D); + for (auto *D : S.LookupConstructors(ToRecordDecl)) { + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - bool Usable = !Constructor->isInvalidDecl(); + bool Usable = !Info.Constructor->isInvalidDecl(); if (ListInitializing) - Usable = Usable && (AllowExplicit || !Constructor->isExplicit()); + Usable = Usable && (AllowExplicit || !Info.Constructor->isExplicit()); else - Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit); + Usable = Usable && + Info.Constructor->isConvertingConstructor(AllowExplicit); if (Usable) { bool SuppressUserConversions = !ConstructorsOnly; if (SuppressUserConversions && ListInitializing) { @@ -3212,18 +3191,18 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // If the first argument is (a reference to) the target type, // suppress conversions. SuppressUserConversions = isFirstArgumentCompatibleWithType( - S.Context, Constructor, ToType); + S.Context, Info.Constructor, ToType); } } - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, - /*ExplicitArgs*/ nullptr, - llvm::makeArrayRef(Args, NumArgs), - CandidateSet, SuppressUserConversions); + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate( + Info.ConstructorTmpl, Info.FoundDecl, + /*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs), + CandidateSet, SuppressUserConversions); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, llvm::makeArrayRef(Args, NumArgs), CandidateSet, SuppressUserConversions); } @@ -4288,7 +4267,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); Cand != CandidateSet.end(); ++Cand) if (Cand->Viable) - ICS.Ambiguous.addConversion(Cand->Function); + ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function); return true; case OR_No_Viable_Function: @@ -8862,6 +8841,7 @@ enum OverloadCandidateKind { }; OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, + NamedDecl *Found, FunctionDecl *Fn, std::string &Description) { bool isTemplate = false; @@ -8990,13 +8970,13 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, } // Notes the location of an overload candidate. -void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType, - bool TakingAddress) { +void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, + QualType DestType, bool TakingAddress) { if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn)) return; std::string FnDesc; - OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); + OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc); PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) << (unsigned) K << FnDesc; @@ -9019,11 +8999,11 @@ void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType, I != IEnd; ++I) { if (FunctionTemplateDecl *FunTmpl = dyn_cast((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType, + NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), DestType, TakingAddress); } else if (FunctionDecl *Fun = dyn_cast((*I)->getUnderlyingDecl()) ) { - NoteOverloadCandidate(Fun, DestType, TakingAddress); + NoteOverloadCandidate(*I, Fun, DestType, TakingAddress); } } } @@ -9047,7 +9027,7 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion( if (CandsShown >= 4 && ShowOverloads == Ovl_Best) break; ++CandsShown; - S.NoteOverloadCandidate(*I); + S.NoteOverloadCandidate(I->first, I->second); } if (I != E) S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I); @@ -9072,7 +9052,8 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, } std::string FnDesc; - OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); + OverloadCandidateKind FnKind = + ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); Expr *FromExpr = Conv.Bad.FromExpr; QualType FromTy = Conv.Bad.getFromType(); @@ -9318,7 +9299,8 @@ static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand, } /// General arity mismatch diagnosis over a candidate in a candidate set. -static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { +static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D, + unsigned NumFormalArgs) { assert(isa(D) && "The templated declaration should at least be a function" " when diagnosing bad template argument deduction due to too many" @@ -9348,7 +9330,8 @@ static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { } std::string Description; - OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description); + OverloadCandidateKind FnKind = + ClassifyOverloadCandidate(S, Found, Fn, Description); if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName()) S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one) @@ -9365,7 +9348,7 @@ static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, unsigned NumFormalArgs) { if (!CheckArityMismatch(S, Cand, NumFormalArgs)) - DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs); + DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs); } static TemplateDecl *getDescribedTemplate(Decl *Templated) { @@ -9376,7 +9359,7 @@ static TemplateDecl *getDescribedTemplate(Decl *Templated) { } /// Diagnose a failed template-argument deduction. -static void DiagnoseBadDeduction(Sema &S, Decl *Templated, +static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, DeductionFailureInfo &DeductionFailure, unsigned NumArgs, bool TakingCandidateAddress) { @@ -9466,7 +9449,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated, case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: - DiagnoseArityMismatch(S, Templated, NumArgs); + DiagnoseArityMismatch(S, Found, Templated, NumArgs); return; case Sema::TDK_InstantiationDepth: @@ -9596,7 +9579,7 @@ static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, if (CheckArityMismatch(S, Cand, NumArgs)) return; } - DiagnoseBadDeduction(S, Cand->Function, // pattern + DiagnoseBadDeduction(S, Cand->FoundDecl, Cand->Function, // pattern Cand->DeductionFailure, NumArgs, TakingCandidateAddress); } @@ -9609,7 +9592,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { CalleeTarget = S.IdentifyCUDATarget(Callee); std::string FnDesc; - OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc); + OverloadCandidateKind FnKind = + ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc); S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target) << (unsigned)FnKind << CalleeTarget << CallerTarget; @@ -9686,7 +9670,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, if (Cand->Viable && (Fn->isDeleted() || S.isFunctionConsideredUnavailable(Fn))) { std::string FnDesc; - OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); + OverloadCandidateKind FnKind = + ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) << FnKind << FnDesc @@ -9697,7 +9682,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, // We don't really have anything else to say about viable candidates. if (Cand->Viable) { - S.NoteOverloadCandidate(Fn); + S.NoteOverloadCandidate(Cand->FoundDecl, Fn); return; } @@ -9707,7 +9692,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, return DiagnoseArityMismatch(S, Cand, NumArgs); case ovl_fail_bad_deduction: - return DiagnoseBadDeduction(S, Cand, NumArgs, TakingCandidateAddress); + return DiagnoseBadDeduction(S, Cand, NumArgs, + TakingCandidateAddress); case ovl_fail_illegal_constructor: { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor) @@ -9719,7 +9705,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_trivial_conversion: case ovl_fail_bad_final_conversion: case ovl_fail_final_conversion_not_exact: - return S.NoteOverloadCandidate(Fn); + return S.NoteOverloadCandidate(Cand->FoundDecl, Fn); case ovl_fail_bad_conversion: { unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); @@ -9730,7 +9716,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, // FIXME: this currently happens when we're called from SemaInit // when user-conversion overload fails. Figure out how to handle // those conditions and diagnose them well. - return S.NoteOverloadCandidate(Fn); + return S.NoteOverloadCandidate(Cand->FoundDecl, Fn); } case ovl_fail_bad_target: @@ -9808,8 +9794,8 @@ static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, if (ICS.isBad()) break; // all meaningless after first invalid if (!ICS.isAmbiguous()) continue; - ICS.DiagnoseAmbiguousConversion(S, OpLoc, - S.PDiag(diag::note_ambiguous_type_conversion)); + ICS.DiagnoseAmbiguousConversion( + S, OpLoc, S.PDiag(diag::note_ambiguous_type_conversion)); } } @@ -10176,7 +10162,7 @@ struct CompareTemplateSpecCandidatesForDisplay { /// deductions. void TemplateSpecCandidate::NoteDeductionFailure(Sema &S, bool ForTakingAddress) { - DiagnoseBadDeduction(S, Specialization, // pattern + DiagnoseBadDeduction(S, FoundDecl, Specialization, // pattern DeductionFailure, /*NumArgs=*/0, ForTakingAddress); } @@ -10429,7 +10415,7 @@ private: Info, /*InOverloadResolution=*/true)) { // Make a note of the failed deduction for diagnostics. FailedCandidates.addCandidate() - .set(FunctionTemplate->getTemplatedDecl(), + .set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(), MakeDeductionFailureInfo(Context, Result, Info)); return false; } @@ -10595,7 +10581,7 @@ public: if (FunctionDecl *Fun = dyn_cast((*I)->getUnderlyingDecl())) if (!functionHasPassObjectSizeParams(Fun)) - S.NoteOverloadCandidate(Fun, TargetFunctionType, + S.NoteOverloadCandidate(*I, Fun, TargetFunctionType, /*TakingAddress=*/true); FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart()); } @@ -10801,7 +10787,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // Make a note of the failed deduction for diagnostics. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate() - .set(FunctionTemplate->getTemplatedDecl(), + .set(I.getPair(), FunctionTemplate->getTemplatedDecl(), MakeDeductionFailureInfo(Context, Result, Info)); continue; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 4960a2d144..fd0dc6fca7 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2791,8 +2791,9 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, DeduceTemplateArguments(Partial, TemplateArgList, Info)) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? - FailedCandidates.addCandidate() - .set(Partial, MakeDeductionFailureInfo(Context, Result, Info)); + FailedCandidates.addCandidate().set( + DeclAccessPair::make(Template, AS_public), Partial, + MakeDeductionFailureInfo(Context, Result, Info)); (void)Result; } else { Matched.push_back(PartialSpecMatchResult()); @@ -6895,12 +6896,13 @@ bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult TDK = DeduceTemplateArguments( cast(FunTmpl->getFirstDecl()), - ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) { + ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, + Info)) { // Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. - FailedCandidates.addCandidate() - .set(FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK, Info)); + FailedCandidates.addCandidate().set( + I.getPair(), FunTmpl->getTemplatedDecl(), + MakeDeductionFailureInfo(Context, TDK, Info)); (void)TDK; continue; } @@ -7925,7 +7927,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, R, Specialization, Info)) { // Keep track of almost-matches. FailedCandidates.addCandidate() - .set(FunTmpl->getTemplatedDecl(), + .set(P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo(Context, TDK, Info)); (void)TDK; continue; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c9eaa243c6..243fedbd65 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2321,8 +2321,9 @@ bool Sema::InstantiateClassTemplateSpecialization( Info)) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? - FailedCandidates.addCandidate() - .set(Partial, MakeDeductionFailureInfo(Context, Result, Info)); + FailedCandidates.addCandidate().set( + DeclAccessPair::make(Template, AS_public), Partial, + MakeDeductionFailureInfo(Context, Result, Info)); (void)Result; } else { Matched.push_back(PartialSpecMatchResult()); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 58cf67ccc8..a2ad14fde0 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2637,6 +2637,7 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXConstructExpr(QualType T, SourceLocation Loc, + NamedDecl *Found, CXXConstructorDecl *Constructor, bool IsElidable, MultiExprArg Args, @@ -2651,7 +2652,8 @@ public: ConvertedArgs)) return ExprError(); - return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, + return getSema().BuildCXXConstructExpr(Loc, T, Found, Constructor, + IsElidable, ConvertedArgs, HadMultipleCandidates, ListInitialization, @@ -9880,6 +9882,11 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { if (T.isNull()) return ExprError(); + NamedDecl *FoundDecl = cast_or_null( + getDerived().TransformDecl(E->getLocStart(), E->getFoundDecl())); + if (!FoundDecl) + return ExprError(); + CXXConstructorDecl *Constructor = cast_or_null( getDerived().TransformDecl(E->getLocStart(), @@ -9895,6 +9902,7 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { if (!getDerived().AlwaysRebuild() && T == E->getType() && + FoundDecl == E->getFoundDecl() && Constructor == E->getConstructor() && !ArgumentChanged) { // Mark the constructor as referenced. @@ -9904,8 +9912,8 @@ TreeTransform::TransformCXXConstructExpr(CXXConstructExpr *E) { } return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(), - Constructor, E->isElidable(), - Args, + FoundDecl, Constructor, + E->isElidable(), Args, E->hadMultipleCandidates(), E->isListInitialization(), E->isStdInitListInitialization(), -- 2.40.0