diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -480,6 +480,13 @@ /// error. llvm::Expected Import(const APValue &FromValue); + /// Import the given C++ TemplateArgumentList from the "from" + /// context into the "to" context. + /// + /// \returns The equivalent initializer in the "to" context, or the import + /// error. + llvm::Expected Import(const TemplateArgumentList *); + /// Import the definition of the given declaration, including all of /// the declarations it contains. [[nodiscard]] llvm::Error ImportDefinition(Decl *From); diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1232,6 +1232,8 @@ /// The declaration that we are referencing. ValueDecl *D; + const TemplateArgumentList *ConvertedArgs; + /// Provides source/type location info for the declaration name /// embedded in D. DeclarationNameLoc DNLoc; @@ -1256,7 +1258,8 @@ SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnlosingVariableOrCapture, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, - const TemplateArgumentListInfo *TemplateArgs, QualType T, + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs, QualType T, ExprValueKind VK, NonOdrUseReason NOUR); /// Construct an empty declaration reference expression. @@ -1275,6 +1278,7 @@ bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertedArgs = nullptr, NonOdrUseReason NOUR = NOUR_None); static DeclRefExpr * @@ -1284,6 +1288,7 @@ const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertedArgs = nullptr, NonOdrUseReason NOUR = NOUR_None); /// Construct an empty declaration reference expression. @@ -1391,6 +1396,8 @@ return getTrailingObjects(); } + const TemplateArgumentList *getConvertedArgs() const { return ConvertedArgs; } + /// Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { @@ -3175,6 +3182,8 @@ /// In X.F, this is the decl referenced by F. ValueDecl *MemberDecl; + const TemplateArgumentList *Deduced; + /// MemberDNLoc - Provides source/type location info for the /// declaration name embedded in MemberDecl. DeclarationNameLoc MemberDNLoc; @@ -3200,21 +3209,20 @@ MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, - QualType T, ExprValueKind VK, ExprObjectKind OK, - NonOdrUseReason NOUR); + const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, + ExprObjectKind OK, NonOdrUseReason NOUR); MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} public: - static MemberExpr *Create(const ASTContext &C, Expr *Base, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, - DeclAccessPair FoundDecl, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK, ExprObjectKind OK, - NonOdrUseReason NOUR); + static MemberExpr * + Create(const ASTContext &C, Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, + DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, + ExprObjectKind OK, NonOdrUseReason NOUR); /// Create an implicit MemberExpr, with no location, qualifier, template /// arguments, and so on. Suitable only for non-static member access. @@ -3225,7 +3233,8 @@ return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), MemberDecl, DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()), - DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None); + DeclarationNameInfo(), nullptr, nullptr, T, VK, OK, + NOUR_None); } static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, @@ -3251,6 +3260,8 @@ return getTrailingObjects()->FoundDecl; } + const TemplateArgumentList *getDeduced() const { return Deduced; } + /// Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -939,6 +939,7 @@ bool HadMultipleCandidates; FunctionDecl *Function; DeclAccessPair FoundDecl; + const TemplateArgumentList *ConvertedArgs; }; union { @@ -1237,9 +1238,10 @@ /// /// \param Function the function to which the overloaded function reference /// resolves. - void AddAddressOverloadResolutionStep(FunctionDecl *Function, - DeclAccessPair Found, - bool HadMultipleCandidates); + void + AddAddressOverloadResolutionStep(FunctionDecl *Function, DeclAccessPair Found, + const TemplateArgumentList *ConvertedArgs, + bool HadMultipleCandidates); /// Add a new step in the initialization that performs a derived-to- /// base cast. diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -885,6 +885,9 @@ StandardConversionSequence FinalConversion; }; + /// Deduced Arguments for Function Templates. + const TemplateArgumentList *Deduced; + /// Get RewriteKind value in OverloadCandidateRewriteKind type (This /// function is to workaround the spurious GCC bitfield enum warning) OverloadCandidateRewriteKind getRewriteKind() const { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3885,7 +3885,8 @@ bool AllowExplicitConversion = false, ADLCallKind IsADLCandidate = ADLCallKind::NotADL, ConversionSequenceList EarlyConversions = None, - OverloadCandidateParamOrder PO = {}); + OverloadCandidateParamOrder PO = {}, + const TemplateArgumentList *Deduced = nullptr); void AddFunctionCandidates(const UnresolvedSetImpl &Functions, ArrayRef Args, OverloadCandidateSet &CandidateSet, @@ -3900,16 +3901,16 @@ OverloadCandidateSet& CandidateSet, bool SuppressUserConversion = false, OverloadCandidateParamOrder PO = {}); - void AddMethodCandidate(CXXMethodDecl *Method, - DeclAccessPair FoundDecl, + void AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef Args, - OverloadCandidateSet& CandidateSet, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, ConversionSequenceList EarlyConversions = None, - OverloadCandidateParamOrder PO = {}); + OverloadCandidateParamOrder PO = {}, + const TemplateArgumentList *Deduced = nullptr); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -4033,10 +4034,9 @@ QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType); FunctionDecl * - ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, - QualType TargetType, - bool Complain, - DeclAccessPair &Found, + ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, + bool Complain, DeclAccessPair &Found, + const TemplateArgumentList *&ConvertedArgs, bool *pHadMultipleCandidates = nullptr); FunctionDecl * @@ -4045,10 +4045,10 @@ bool resolveAndFixAddressOfSingleOverloadCandidate( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); - FunctionDecl * - ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, - bool Complain = false, - DeclAccessPair *Found = nullptr); + FunctionDecl *ResolveSingleFunctionTemplateSpecialization( + OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs, + const TemplateArgumentList *&ConvertedArgs, bool Complain = false, + DeclAccessPair *Found = nullptr); bool ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false, @@ -4056,12 +4056,13 @@ QualType DestTypeForComplaining = QualType(), unsigned DiagIDForComplaining = 0); - Expr *FixOverloadedFunctionReference(Expr *E, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); - ExprResult FixOverloadedFunctionReference(ExprResult, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); + Expr *FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced); + ExprResult + FixOverloadedFunctionReference(ExprResult, DeclAccessPair FoundDecl, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced); void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, ArrayRef Args, @@ -5472,14 +5473,15 @@ const CXXScopeSpec *SS = nullptr, NamedDecl *FoundD = nullptr, SourceLocation TemplateKWLoc = SourceLocation(), - const TemplateArgumentListInfo *TemplateArgs = nullptr); + const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertedArgs = nullptr); DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, - NestedNameSpecifierLoc NNS, - NamedDecl *FoundD = nullptr, + NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr, SourceLocation TemplateKWLoc = SourceLocation(), - const TemplateArgumentListInfo *TemplateArgs = nullptr); + const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertedArgs = nullptr); ExprResult BuildAnonymousStructUnionMemberReference( @@ -5523,6 +5525,7 @@ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertedArgs = nullptr, bool AcceptInvalidDecl = false); ExprResult BuildLiteralOperatorCall(LookupResult &R, @@ -5706,22 +5709,20 @@ UnqualifiedId &Member, Decl *ObjCImpDecl); - MemberExpr * - BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, - const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, - ValueDecl *Member, DeclAccessPair FoundDecl, - bool HadMultipleCandidates, - const DeclarationNameInfo &MemberNameInfo, QualType Ty, - ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs = nullptr); - MemberExpr * - BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, - NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - ValueDecl *Member, DeclAccessPair FoundDecl, - bool HadMultipleCandidates, - const DeclarationNameInfo &MemberNameInfo, QualType Ty, - ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs = nullptr); + MemberExpr *BuildMemberExpr( + Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS, + SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, + bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, + QualType Ty, ExprValueKind VK, ExprObjectKind OK, + const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *Deduced = nullptr); + MemberExpr *BuildMemberExpr( + Expr *Base, bool IsArrow, SourceLocation OpLoc, + NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, + ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, + const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *Deduced = nullptr); void ActOnDefaultCtorInitializers(Decl *CDtorDecl); bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, @@ -7992,7 +7993,8 @@ DeclResult CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs); + const TemplateArgumentListInfo &TemplateArgs, + const TemplateArgumentList *&ConvertedArgs); /// Form a reference to the specialization of the given variable template /// corresponding to the specified argument list, or a null-but-valid result @@ -12799,7 +12801,8 @@ /// calling priority. void EraseUnwantedCUDAMatches( const FunctionDecl *Caller, - SmallVectorImpl> &Matches); + SmallVectorImpl> &Matches); /// Given a implicit special member, infer its CUDA target from the /// calls it needs to make to underlying base/field special members. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7041,6 +7041,7 @@ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToDecl = importChecked(Err, E->getDecl()); + auto ToConvertedArgs = importChecked(Err, E->getConvertedArgs()); auto ToLocation = importChecked(Err, E->getLocation()); auto ToType = importChecked(Err, E->getType()); if (Err) @@ -7067,7 +7068,8 @@ auto *ToE = DeclRefExpr::Create( Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, E->refersToEnclosingVariableOrCapture(), ToLocation, ToType, - E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse()); + E->getValueKind(), ToFoundD, ToResInfo, ToConvertedArgs, + E->isNonOdrUse()); if (E->hadMultipleCandidates()) ToE->setHadMultipleCandidates(true); return ToE; @@ -7951,6 +7953,7 @@ auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToMemberDecl = importChecked(Err, E->getMemberDecl()); + auto ToDeduced = importChecked(Err, E->getDeduced()); auto ToType = importChecked(Err, E->getType()); auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl()); auto ToName = importChecked(Err, E->getMemberNameInfo().getName()); @@ -7975,7 +7978,7 @@ return MemberExpr::Create(Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl, ToMemberNameInfo, - ResInfo, ToType, E->getValueKind(), + ResInfo, ToDeduced, ToType, E->getValueKind(), E->getObjectKind(), E->isNonOdrUse()); } @@ -9655,6 +9658,17 @@ return Importer.ImportAPValue(FromValue); } +llvm::Expected +ASTImporter::Import(const TemplateArgumentList *ArgList) { + ASTNodeImporter Importer(*this); + if (!ArgList) + return nullptr; + SmallVector ToArgs(ArgList->size()); + if (auto Res = Importer.ImportTemplateArguments(ArgList->asArray(), ToArgs)) + return std::move(Res); + return TemplateArgumentList::CreateCopy(ToContext, ToArgs); +} + Error ASTImporter::ImportDefinition(Decl *From) { ExpectedDecl ToOrErr = Import(From); if (!ToOrErr) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -401,7 +401,8 @@ ExprValueKind VK, SourceLocation L, const DeclarationNameLoc &LocInfo, NonOdrUseReason NOUR) - : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), DNLoc(LocInfo) { + : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), ConvertedArgs(nullptr), + DNLoc(LocInfo) { DeclRefExprBits.HasQualifier = false; DeclRefExprBits.HasTemplateKWAndArgsInfo = false; DeclRefExprBits.HasFoundDecl = false; @@ -419,9 +420,12 @@ bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK, NonOdrUseReason NOUR) + const TemplateArgumentList *ConvertedArgs, QualType T, + ExprValueKind VK, NonOdrUseReason NOUR) : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), - DNLoc(NameInfo.getInfo()) { + ConvertedArgs(ConvertedArgs), DNLoc(NameInfo.getInfo()) { + assert(!TemplateArgs || ConvertedArgs); + assert(!ConvertedArgs || ConvertedArgs->size() != 0); DeclRefExprBits.Loc = NameInfo.getLoc(); DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; if (QualifierLoc) @@ -457,22 +461,21 @@ SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs, NonOdrUseReason NOUR) { return Create(Context, QualifierLoc, TemplateKWLoc, D, RefersToEnclosingVariableOrCapture, - DeclarationNameInfo(D->getDeclName(), NameLoc), - T, VK, FoundD, TemplateArgs, NOUR); + DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, FoundD, + TemplateArgs, ConvertedArgs, NOUR); } -DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, - bool RefersToEnclosingVariableOrCapture, - const DeclarationNameInfo &NameInfo, - QualType T, ExprValueKind VK, - NamedDecl *FoundD, - const TemplateArgumentListInfo *TemplateArgs, - NonOdrUseReason NOUR) { +DeclRefExpr *DeclRefExpr::Create( + const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, + const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs, NonOdrUseReason NOUR) { // Filter out cases where the found Decl is the same as the value refenenced. if (D == FoundD) FoundD = nullptr; @@ -486,9 +489,10 @@ TemplateArgs ? TemplateArgs->size() : 0); void *Mem = Context.Allocate(Size, alignof(DeclRefExpr)); - return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, - RefersToEnclosingVariableOrCapture, NameInfo, - FoundD, TemplateArgs, T, VK, NOUR); + return new (Mem) + DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, + RefersToEnclosingVariableOrCapture, NameInfo, FoundD, + TemplateArgs, ConvertedArgs, T, VK, NOUR); } DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, @@ -1612,11 +1616,13 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, ValueDecl *MemberDecl, - const DeclarationNameInfo &NameInfo, QualType T, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl), - MemberDNLoc(NameInfo.getInfo()), MemberLoc(NameInfo.getLoc()) { + Deduced(Deduced), MemberDNLoc(NameInfo.getInfo()), + MemberLoc(NameInfo.getLoc()) { assert(!NameInfo.getName() || MemberDecl->getDeclName() == NameInfo.getName()); MemberExprBits.IsArrow = IsArrow; @@ -1633,7 +1639,8 @@ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) { + const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK, + ExprObjectKind OK, NonOdrUseReason NOUR) { bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl || FoundDecl.getAccess() != MemberDecl->getAccess(); bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); @@ -1645,7 +1652,7 @@ void *Mem = C.Allocate(Size, alignof(MemberExpr)); MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, - NameInfo, T, VK, OK, NOUR); + NameInfo, Deduced, T, VK, OK, NOUR); // FIXME: remove remaining dependence computation to computeDependence(). auto Deps = E->getDependence(); diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -230,8 +230,8 @@ C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), MemberDecl, FoundDecl, DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()), - /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind, - OK_Ordinary, NOUR_None); + /* TemplateArgumentListInfo=*/nullptr, /*Deduced=*/nullptr, + MemberDecl->getType(), ValueKind, OK_Ordinary, NOUR_None); } ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1603,7 +1603,8 @@ return DeclRefExpr::Create( CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD, /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(), - ME->getType(), ME->getValueKind(), nullptr, nullptr, ME->isNonOdrUse()); + ME->getType(), ME->getValueKind(), nullptr, nullptr, nullptr, + ME->isNonOdrUse()); } return nullptr; } diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -271,25 +271,28 @@ void Sema::EraseUnwantedCUDAMatches( const FunctionDecl *Caller, - SmallVectorImpl> &Matches) { + SmallVectorImpl> &Matches) { if (Matches.size() <= 1) return; - using Pair = std::pair; + using Tuple = + std::tuple; // Gets the CUDA function preference for a call from Caller to Match. - auto GetCFP = [&](const Pair &Match) { - return IdentifyCUDAPreference(Caller, Match.second); + auto GetCFP = [&](const Tuple &Match) { + return IdentifyCUDAPreference(Caller, std::get<1>(Match)); }; // Find the best call preference among the functions in Matches. CUDAFunctionPreference BestCFP = GetCFP(*std::max_element( - Matches.begin(), Matches.end(), - [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); })); + Matches.begin(), Matches.end(), [&](const Tuple &M1, const Tuple &M2) { + return GetCFP(M1) < GetCFP(M2); + })); // Erase all functions with lower priority. llvm::erase_if(Matches, - [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }); + [&](const Tuple &Match) { return GetCFP(Match) < BestCFP; }); } /// When an implicitly-declared special member has to invoke more than one diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1720,9 +1720,9 @@ bool WasOverloadedFunction = false; DeclAccessPair FoundOverload; if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { - if (FunctionDecl *Fn - = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, - FoundOverload)) { + const TemplateArgumentList *ConvertedArgs; + if (FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction( + SrcExpr.get(), DestType, false, FoundOverload, ConvertedArgs)) { CXXMethodDecl *M = cast(Fn); SrcType = Self.Context.getMemberPointerType(Fn->getType(), Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); @@ -1799,16 +1799,16 @@ if (WasOverloadedFunction) { // Resolve the address of the overloaded function again, this time // allowing complaints if something goes wrong. - FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), - DestType, - true, - FoundOverload); + const TemplateArgumentList *ConvertedArgs; + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction( + SrcExpr.get(), DestType, true, FoundOverload, ConvertedArgs); if (!Fn) { msg = 0; return TC_Failed; } - SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn); + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn, + ConvertedArgs); if (!SrcExpr.isUsable()) { msg = 0; return TC_Failed; @@ -2773,10 +2773,10 @@ if (tcr != TC_Success && msg != 0) { if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { DeclAccessPair Found; - FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), - DestType, - /*Complain*/ true, - Found); + const TemplateArgumentList *ConvertedArgs; + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction( + SrcExpr.get(), DestType, + /*Complain*/ true, Found, ConvertedArgs); if (Fn) { // If DestType is a function type (not to be confused with the function // pointer type), it will be possible to resolve the function address, @@ -2882,10 +2882,12 @@ // Overloads are allowed with C extensions, so we need to support them. if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + const TemplateArgumentList *ConvertedArgs; DeclAccessPair DAP; if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction( - SrcExpr.get(), DestType, /*Complain=*/true, DAP)) - SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD); + SrcExpr.get(), DestType, /*Complain=*/true, DAP, ConvertedArgs)) + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD, + ConvertedArgs); else return; assert(SrcExpr.isUsable()); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -6899,7 +6899,7 @@ DeclRefExpr *NewDRE = DeclRefExpr::Create( Context, DRE->getQualifierLoc(), SourceLocation(), NewBuiltinDecl, /*enclosing*/ false, DRE->getLocation(), Context.BuiltinFnTy, - DRE->getValueKind(), nullptr, nullptr, DRE->isNonOdrUse()); + DRE->getValueKind(), nullptr, nullptr, nullptr, DRE->isNonOdrUse()); // Set the callee in the CallExpr. // FIXME: This loses syntactic information. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3599,9 +3599,14 @@ return; } } else if (auto *ULE = dyn_cast(E)) { - if (ULE->hasExplicitTemplateArgs()) + if (ULE->hasExplicitTemplateArgs()) { S.Diag(Loc, diag::warn_cleanup_ext); - FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); + TemplateArgumentListInfo ExplicitTemplateArgs; + const TemplateArgumentList *ConvertedArgs; + ULE->copyTemplateArgumentsInto(ExplicitTemplateArgs); + FD = S.ResolveSingleFunctionTemplateSpecialization( + ULE, ExplicitTemplateArgs, ConvertedArgs, /*Complain=*/true); + } NI = ULE->getNameInfo(); if (!FD) { S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2007,11 +2007,12 @@ const DeclarationNameInfo &NameInfo, const CXXScopeSpec *SS, NamedDecl *FoundD, SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs) { NestedNameSpecifierLoc NNS = SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(); return BuildDeclRefExpr(D, Ty, VK, NameInfo, NNS, FoundD, TemplateKWLoc, - TemplateArgs); + TemplateArgs, ConvertedArgs); } // CUDA/HIP: Check whether a captured reference variable is referencing a @@ -2078,13 +2079,16 @@ const DeclarationNameInfo &NameInfo, NestedNameSpecifierLoc NNS, NamedDecl *FoundD, SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs) { bool RefersToCapturedVariable = isa(D) && NeedToCaptureVariable(D, NameInfo.getLoc()); - DeclRefExpr *E = DeclRefExpr::Create( - Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty, - VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D)); + assert(!TemplateArgs || ConvertedArgs); + DeclRefExpr *E = DeclRefExpr::Create(Context, NNS, TemplateKWLoc, D, + RefersToCapturedVariable, NameInfo, Ty, + VK, FoundD, TemplateArgs, ConvertedArgs, + getNonOdrUseReasonInCurrentContext(D)); MarkDeclRefReferenced(E); // C++ [except.spec]p17: @@ -3223,7 +3227,7 @@ !R.getAsSingle() && !ShouldLookupResultBeMultiVersionOverload(R)) return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), - R.getRepresentativeDecl(), nullptr, + R.getRepresentativeDecl(), nullptr, nullptr, AcceptInvalidDecl); // We only need to check the declaration if there's exactly one @@ -3256,10 +3260,11 @@ ExprResult Sema::BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, - bool AcceptInvalidDecl) { + const TemplateArgumentList *ConvertedArgs, bool AcceptInvalidDecl) { assert(D && "Cannot refer to a NULL declaration"); assert(!isa(D) && "Cannot refer unambiguously to a function template"); + assert(!TemplateArgs || ConvertedArgs); SourceLocation Loc = NameInfo.getLoc(); if (CheckDeclInExpr(*this, Loc, D)) { @@ -3496,7 +3501,7 @@ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD, /*FIXME: TemplateKWLoc*/ SourceLocation(), - TemplateArgs); + TemplateArgs, ConvertedArgs); } static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, @@ -6748,7 +6753,7 @@ Fn = DeclRefExpr::Create( Context, FDecl->getQualifierLoc(), SourceLocation(), FDecl, false, SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl, - nullptr, DRE->isNonOdrUse()); + nullptr, nullptr, DRE->isNonOdrUse()); } } } else if (isa(NakedFn)) @@ -9964,9 +9969,10 @@ // As a set of extensions to C, we support overloading on functions. These // functions need to be resolved here. DeclAccessPair DAP; + const TemplateArgumentList *ConvertedArgs; if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction( - RHS.get(), LHSType, /*Complain=*/false, DAP)) - RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD); + RHS.get(), LHSType, /*Complain=*/false, DAP, ConvertedArgs)) + RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD, ConvertedArgs); else return Incompatible; } @@ -14257,14 +14263,19 @@ } OverloadExpr *Ovl = cast(E); - if (isa(Ovl)) - if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) { - Diag(OpLoc, diag::err_invalid_form_pointer_member_function) - << OrigOp.get()->getSourceRange(); - return QualType(); - } - - return Context.OverloadTy; + if (!isa(Ovl)) + return Context.OverloadTy; + if (Ovl->hasExplicitTemplateArgs()) { + TemplateArgumentListInfo ExplicitTemplateArgs; + Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); + const TemplateArgumentList *ConvertedArgs; + if (ResolveSingleFunctionTemplateSpecialization( + Ovl, ExplicitTemplateArgs, ConvertedArgs)) + return Context.OverloadTy; + } + Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp.get()->getSourceRange(); + return QualType(); } if (PTy->getKind() == BuiltinType::UnknownAny) @@ -19140,7 +19151,8 @@ S.Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(), DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(), DRE->getNameInfo(), DRE->getType(), DRE->getValueKind(), - DRE->getFoundDecl(), CopiedTemplateArgs(DRE), NOUR); + DRE->getFoundDecl(), CopiedTemplateArgs(DRE), DRE->getConvertedArgs(), + NOUR); } case Expr::FunctionParmPackExprClass: { @@ -19186,8 +19198,8 @@ S.Context, Base.get(), ME->isArrow(), ME->getOperatorLoc(), ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(), - CopiedTemplateArgs(ME), ME->getType(), ME->getValueKind(), - ME->getObjectKind(), ME->isNonOdrUse()); + CopiedTemplateArgs(ME), ME->getDeduced(), ME->getType(), + ME->getValueKind(), ME->getObjectKind(), ME->isNonOdrUse()); } if (ME->getMemberDecl()->isCXXInstanceMember()) @@ -19204,7 +19216,8 @@ S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(), ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME), - ME->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR); + ME->getDeduced(), ME->getType(), ME->getValueKind(), + ME->getObjectKind(), NOUR); } case Expr::BinaryOperatorClass: { @@ -20748,7 +20761,8 @@ FD, FD->getType(), VK_LValue, DRE->getNameInfo(), DRE->hasQualifier() ? &SS : nullptr, DRE->getFoundDecl(), DRE->getTemplateKeywordLoc(), - DRE->hasExplicitTemplateArgs() ? &TemplateArgs : nullptr); + DRE->hasExplicitTemplateArgs() ? &TemplateArgs : nullptr, + DRE->getConvertedArgs()); } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2774,7 +2774,10 @@ FoundDelete.suppressDiagnostics(); - SmallVector, 2> Matches; + SmallVector< + std::tuple, + 2> + Matches; // Whether we're looking for a placement operator delete is dictated // by whether we selected a placement operator new, not by whether @@ -2824,6 +2827,7 @@ DEnd = FoundDelete.end(); D != DEnd; ++D) { FunctionDecl *Fn = nullptr; + const TemplateArgumentList *ConvertedArgs = nullptr; if (FunctionTemplateDecl *FnTmpl = dyn_cast((*D)->getUnderlyingDecl())) { // Perform template argument deduction to try to match the @@ -2832,14 +2836,15 @@ if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn, Info)) continue; + ConvertedArgs = Info.takeSugared(); } else Fn = cast((*D)->getUnderlyingDecl()); if (Context.hasSameType(adjustCCAndNoReturn(Fn->getType(), ExpectedFunctionType, - /*AdjustExcpetionSpec*/true), + /*AdjustExcpetionSpec=*/true), ExpectedFunctionType)) - Matches.push_back(std::make_pair(D.getPair(), Fn)); + Matches.push_back({D.getPair(), Fn, ConvertedArgs}); } if (getLangOpts().CUDA) @@ -2859,12 +2864,12 @@ /*WantAlign*/ hasNewExtendedAlignment(*this, AllocElemType), &BestDeallocFns); if (Selected) - Matches.push_back(std::make_pair(Selected.Found, Selected.FD)); + Matches.push_back({Selected.Found, Selected.FD, nullptr}); else { // If we failed to select an operator, all remaining functions are viable // but ambiguous. for (auto Fn : BestDeallocFns) - Matches.push_back(std::make_pair(Fn.Found, Fn.FD)); + Matches.push_back({Fn.Found, Fn.FD, nullptr}); } } @@ -2873,7 +2878,7 @@ // function, that function will be called; otherwise, no // deallocation function will be called. if (Matches.size() == 1) { - OperatorDelete = Matches[0].second; + OperatorDelete = std::get<1>(Matches[0]); // C++1z [expr.new]p23: // If the lookup finds a usual deallocation function (3.7.4.2) @@ -2912,7 +2917,7 @@ } CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(), - Matches[0].first); + std::get<0>(Matches[0])); } else if (!Matches.empty()) { // We found multiple suitable operators. Per [expr.new]p20, that means we // call no 'operator delete' function, but we should at least warn the user. @@ -2921,8 +2926,8 @@ << DeleteName << AllocElemType; for (auto &Match : Matches) - Diag(Match.second->getLocation(), - diag::note_member_declared_here) << DeleteName; + Diag(std::get<1>(Match)->getLocation(), diag::note_member_declared_here) + << DeleteName; } return false; @@ -4242,15 +4247,16 @@ // Resolve overloaded function references. if (Context.hasSameType(FromType, Context.OverloadTy)) { DeclAccessPair Found; - FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, - true, Found); + const TemplateArgumentList *ConvertedArgs; + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true, + Found, ConvertedArgs); if (!Fn) return ExprError(); if (DiagnoseUseOfDecl(Fn, From->getBeginLoc())) return ExprError(); - From = FixOverloadedFunctionReference(From, Found, Fn); + From = FixOverloadedFunctionReference(From, Found, Fn, ConvertedArgs); // We might get back another placeholder expression if we resolved to a // builtin. diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -897,12 +897,13 @@ SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *Deduced) { NestedNameSpecifierLoc NNS = SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(); return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty, - VK, OK, TemplateArgs); + VK, OK, TemplateArgs, Deduced); } MemberExpr *Sema::BuildMemberExpr( @@ -910,13 +911,14 @@ SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *Deduced) { assert((!IsArrow || Base->isPRValue()) && "-> base must be a pointer prvalue"); - MemberExpr *E = - MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, - Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, - VK, OK, getNonOdrUseReasonInCurrentContext(Member)); + MemberExpr *E = MemberExpr::Create( + Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, FoundDecl, + MemberNameInfo, TemplateArgs, Deduced, Ty, VK, OK, + getNonOdrUseReasonInCurrentContext(Member)); E->setHadMultipleCandidates(HadMultipleCandidates); MarkMemberReferenced(E); @@ -1146,8 +1148,10 @@ return ExprError(); } - DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, - MemberNameInfo.getLoc(), *TemplateArgs); + const TemplateArgumentList *ConvertedArgs; + DeclResult VDecl = + CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), + *TemplateArgs, ConvertedArgs); if (VDecl.isInvalid()) return ExprError(); @@ -1164,7 +1168,7 @@ return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, Var->getType().getNonReferenceType(), - VK_LValue, OK_Ordinary, TemplateArgs); + VK_LValue, OK_Ordinary, TemplateArgs, ConvertedArgs); } // We found something that we didn't expect. Complain. diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3594,17 +3594,16 @@ return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization; } -void -InitializationSequence -::AddAddressOverloadResolutionStep(FunctionDecl *Function, - DeclAccessPair Found, - bool HadMultipleCandidates) { +void InitializationSequence ::AddAddressOverloadResolutionStep( + FunctionDecl *Function, DeclAccessPair Found, + const TemplateArgumentList *ConvertedArgs, bool HadMultipleCandidates) { Step S; S.Kind = SK_ResolveAddressOfOverloadedFunction; S.Type = Function->getType(); S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = Found; + S.Function.ConvertedArgs = ConvertedArgs; Steps.push_back(S); } @@ -4255,13 +4254,12 @@ if (S.Context.getCanonicalType(UnqualifiedSourceType) == S.Context.OverloadTy) { DeclAccessPair Found; + const TemplateArgumentList *ConvertedArgs; bool HadMultipleCandidates = false; - if (FunctionDecl *Fn - = S.ResolveAddressOfOverloadedFunction(Initializer, - UnqualifiedTargetType, - false, Found, - &HadMultipleCandidates)) { - Sequence.AddAddressOverloadResolutionStep(Fn, Found, + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( + Initializer, UnqualifiedTargetType, false, Found, ConvertedArgs, + &HadMultipleCandidates)) { + Sequence.AddAddressOverloadResolutionStep(Fn, Found, ConvertedArgs, HadMultipleCandidates); SourceType = Fn->getType(); UnqualifiedSourceType = SourceType.getUnqualifiedType(); @@ -6083,11 +6081,12 @@ AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy); } else if (ICS.isBad()) { DeclAccessPair dap; + const TemplateArgumentList *ConvertedArgs; if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) { AddZeroInitializationStep(Entity.getType()); } else if (Initializer->getType() == Context.OverloadTy && !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, - false, dap)) + false, dap, ConvertedArgs)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (Initializer->getType()->isFunctionType() && isExprAnUnaddressableFunction(S, Initializer)) @@ -8261,9 +8260,9 @@ S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); if (S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation())) return ExprError(); - CurInit = S.FixOverloadedFunctionReference(CurInit, - Step->Function.FoundDecl, - Step->Function.Function); + CurInit = S.FixOverloadedFunctionReference( + CurInit, Step->Function.FoundDecl, Step->Function.Function, + Step->Function.ConvertedArgs); // We might get back another placeholder expression if we resolved to a // builtin. if (!CurInit.isInvalid()) @@ -9136,10 +9135,9 @@ case FK_AddressOfOverloadFailed: { DeclAccessPair Found; - S.ResolveAddressOfOverloadedFunction(OnlyArg, - DestType.getNonReferenceType(), - true, - Found); + const TemplateArgumentList *ConvertedArgs; + S.ResolveAddressOfOverloadedFunction( + OnlyArg, DestType.getNonReferenceType(), true, Found, ConvertedArgs); break; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1720,9 +1720,9 @@ if (FromType == S.Context.OverloadTy) { DeclAccessPair AccessPair; - if (FunctionDecl *Fn - = S.ResolveAddressOfOverloadedFunction(From, ToType, false, - AccessPair)) { + const TemplateArgumentList *ConvertedArgs; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( + From, ToType, false, AccessPair, ConvertedArgs)) { // We were able to resolve the address of the overloaded function, // so we can convert to the type of that function. FromType = Fn->getType(); @@ -4757,8 +4757,9 @@ // type of the resulting function. if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { DeclAccessPair Found; - if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType, - false, Found)) + const TemplateArgumentList *ConvertedArgs; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( + Init, DeclType, false, Found, ConvertedArgs)) T2 = Fn->getType(); } @@ -5234,8 +5235,9 @@ // type of the resulting function. if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { DeclAccessPair Found; + const TemplateArgumentList *ConvertedArgs; if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction( - Init, ToType, false, Found)) + Init, ToType, false, Found, ConvertedArgs)) T2 = Fn->getType(); } @@ -6332,7 +6334,7 @@ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO) { + OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced) { const FunctionProtoType *Proto = dyn_cast(Function->getType()->getAs()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6351,7 +6353,7 @@ AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), Args, CandidateSet, SuppressUserConversions, - PartialOverloading, EarlyConversions, PO); + PartialOverloading, EarlyConversions, PO, Deduced); return; } // We treat a constructor like a non-member function, since its object @@ -6396,6 +6398,7 @@ Candidate.IsADLCandidate = IsADLCandidate; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); + Candidate.Deduced = Deduced; // Explicit functions are not actually candidates at all if we're not // allowing them in this context, but keep them around so we can point @@ -6930,16 +6933,13 @@ /// both @c a1 and @c a2. If @p SuppressUserConversions, then don't /// allow user-defined conversions via constructors or conversion /// operators. -void -Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef Args, - OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading, - ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO) { +void Sema::AddMethodCandidate( + CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, ArrayRef Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, ConversionSequenceList EarlyConversions, + OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced) { const FunctionProtoType *Proto = dyn_cast(Method->getType()->getAs()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -6970,6 +6970,7 @@ Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); + Candidate.Deduced = Deduced; unsigned NumParams = Proto->getNumParams(); @@ -7146,7 +7147,7 @@ AddMethodCandidate(cast(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, CandidateSet, SuppressUserConversions, PartialOverloading, - Conversions, PO); + Conversions, PO, Info.takeSugared()); } /// Determine whether a given function template has a simple explicit specifier @@ -7226,10 +7227,11 @@ // Add the function template specialization produced by template argument // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - AddOverloadCandidate( - Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, - PartialOverloading, AllowExplicit, - /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions, PO); + AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, + SuppressUserConversions, PartialOverloading, + AllowExplicit, + /*AllowExplicitConversions*/ false, IsADLCandidate, + Conversions, PO, Info.takeSugared()); } /// Check that implicit conversion sequences can be formed for each argument @@ -12057,7 +12059,10 @@ OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; TemplateArgumentListInfo OvlExplicitTemplateArgs; - SmallVector, 4> Matches; + SmallVector< + std::tuple, + 4> + Matches; TemplateSpecCandidateSet FailedCandidates; public: @@ -12075,15 +12080,22 @@ FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) { ExtractUnqualifiedFunctionTypeFromTargetType(); + if (OvlExpr->hasExplicitTemplateArgs()) + OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs); + + const TemplateArgumentList *ConvertedArgs; if (TargetFunctionType->isFunctionType()) { if (UnresolvedMemberExpr *UME = dyn_cast(OvlExpr)) if (!UME->isImplicitAccess() && - !S.ResolveSingleFunctionTemplateSpecialization(UME)) + (!OvlExpr->hasExplicitTemplateArgs() || + !S.ResolveSingleFunctionTemplateSpecialization( + UME, OvlExplicitTemplateArgs, ConvertedArgs))) StaticMemberFunctionFromBoundPointer = true; } else if (OvlExpr->hasExplicitTemplateArgs()) { DeclAccessPair dap; if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization( - OvlExpr, false, &dap)) { + OvlExpr, OvlExplicitTemplateArgs, ConvertedArgs, + /*Complain=*/false, &dap)) { if (CXXMethodDecl *Method = dyn_cast(Fn)) if (!Method->isStatic()) { // If the target type is a non-function type and the function found @@ -12097,14 +12109,11 @@ return; } - Matches.push_back(std::make_pair(dap, Fn)); + Matches.push_back({dap, Fn, ConvertedArgs}); } return; } - if (OvlExpr->hasExplicitTemplateArgs()) - OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs); - if (FindAllFunctionsThatMatchTargetTypeExactly()) { // C++ [over.over]p4: // If more than one function is selected, [...] @@ -12146,15 +12155,17 @@ // Same algorithm as overload resolution -- one pass to pick the "best", // another pass to be sure that nothing is better than the best. auto Best = Matches.begin(); - for (auto I = Matches.begin()+1, E = Matches.end(); I != E; ++I) - if (isBetterCandidate(I->second, Best->second)) + for (auto I = Matches.begin() + 1, E = Matches.end(); I != E; ++I) + if (isBetterCandidate(std::get<1>(*I), std::get<1>(*Best))) Best = I; - const FunctionDecl *BestFn = Best->second; - auto IsBestOrInferiorToBest = [this, BestFn]( - const std::pair &Pair) { - return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second); - }; + const FunctionDecl *BestFn = std::get<1>(*Best); + auto IsBestOrInferiorToBest = + [this, BestFn](const std::tuple &Tuple) { + return BestFn == std::get<1>(Tuple) || + isBetterCandidate(BestFn, std::get<1>(Tuple)); + }; // Note: We explicitly leave Matches unmodified if there isn't a clear best // option, so we can potentially give the user a better error @@ -12221,7 +12232,7 @@ if (!S.checkAddressOfFunctionIsAvailable(Specialization)) return false; - Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); + Matches.push_back({CurAccessFunPair, Specialization, Info.takeSugared()}); return true; } @@ -12261,8 +12272,9 @@ // If we're in C, we need to support types that aren't exactly identical. if (!S.getLangOpts().CPlusPlus || candidateHasExactlyCorrectType(FunDecl)) { - Matches.push_back(std::make_pair( - CurAccessFunPair, cast(FunDecl->getCanonicalDecl()))); + Matches.push_back({CurAccessFunPair, + cast(FunDecl->getCanonicalDecl()), + nullptr}); FoundNonTemplateFunction = true; return true; } @@ -12319,7 +12331,8 @@ UnresolvedSet<4> MatchesCopy; // TODO: avoid! for (unsigned I = 0, E = Matches.size(); I != E; ++I) - MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); + MatchesCopy.addDecl(std::get<1>(Matches[I]), + std::get<0>(Matches[I]).getAccess()); // TODO: It looks like FailedCandidates does not serve much purpose // here, since the no_viable diagnostic has index 0. @@ -12327,15 +12340,16 @@ MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, SourceExpr->getBeginLoc(), S.PDiag(), S.PDiag(diag::err_addr_ovl_ambiguous) - << Matches[0].second->getDeclName(), + << std::get<1>(Matches[0])->getDeclName(), S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function << (unsigned)ocs_described_template, Complain, TargetFunctionType); if (Result != MatchesCopy.end()) { // Make it the first and only element - Matches[0].first = Matches[Result - MatchesCopy.begin()].first; - Matches[0].second = cast(*Result); + const auto &Old = Matches[Result - MatchesCopy.begin()]; + Matches[0] = {std::get<0>(Old), cast(*Result), + std::get<2>(Old)}; Matches.resize(1); } else HasComplained |= Complain; @@ -12345,7 +12359,7 @@ // [...] any function template specializations in the set are // eliminated if the set also contains a non-template function, [...] for (unsigned I = 0, N = Matches.size(); I != N; ) { - if (Matches[I].second->getPrimaryTemplate() == nullptr) + if (std::get<1>(Matches[I])->getPrimaryTemplate() == nullptr) ++I; else { Matches[I] = Matches[--N]; @@ -12426,12 +12440,18 @@ FunctionDecl* getMatchingFunctionDecl() const { if (Matches.size() != 1) return nullptr; - return Matches[0].second; + return std::get<1>(Matches[0]); } const DeclAccessPair* getMatchingFunctionAccessPair() const { if (Matches.size() != 1) return nullptr; - return &Matches[0].first; + return &std::get<0>(Matches[0]); + } + + const TemplateArgumentList *getMatchingFunctionConvertedArgs() const { + if (Matches.size() != 1) + return nullptr; + return std::get<2>(Matches[0]); } }; } @@ -12451,12 +12471,10 @@ /// This routine returns the resulting FunctionDecl if it could be /// resolved, and NULL otherwise. When @p Complain is true, this /// routine will emit diagnostics if there is an error. -FunctionDecl * -Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, - QualType TargetType, - bool Complain, - DeclAccessPair &FoundResult, - bool *pHadMultipleCandidates) { +FunctionDecl *Sema::ResolveAddressOfOverloadedFunction( + Expr *AddressOfExpr, QualType TargetType, bool Complain, + DeclAccessPair &FoundResult, const TemplateArgumentList *&ConvertedArgs, + bool *pHadMultipleCandidates) { assert(AddressOfExpr->getType() == Context.OverloadTy); AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, @@ -12478,6 +12496,7 @@ if (auto *FPT = Fn->getType()->getAs()) ResolveExceptionSpec(AddressOfExpr->getExprLoc(), FPT); FoundResult = *Resolver.getMatchingFunctionAccessPair(); + ConvertedArgs = Resolver.getMatchingFunctionConvertedArgs(); if (Complain) { if (Resolver.IsStaticMemberFunctionFromBoundPointer()) Resolver.ComplainIsStaticMemberFunctionFromBoundPointer(); @@ -12590,7 +12609,7 @@ // for both. DiagnoseUseOfDecl(Found, E->getExprLoc()); CheckAddressOfMemberAccess(E, DAP); - Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found); + Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found, nullptr); if (DoFunctionPointerConversion && Fixed->getType()->isFunctionType()) SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false); else @@ -12608,10 +12627,10 @@ /// /// If no template-ids are found, no diagnostics are emitted and NULL is /// returned. -FunctionDecl * -Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, - bool Complain, - DeclAccessPair *FoundResult) { +FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( + OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs, + const TemplateArgumentList *&ConvertedArgs, bool Complain, + DeclAccessPair *FoundResult) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] @@ -12619,12 +12638,9 @@ // [...] The overloaded function name can be preceded by the & // operator. - // If we didn't actually find any template-ids, we're done. - if (!ovl->hasExplicitTemplateArgs()) - return nullptr; + // Specializations must have template args. + assert(ovl->hasExplicitTemplateArgs()); - TemplateArgumentListInfo ExplicitTemplateArgs; - ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc()); // Look through all of the overloaded functions, searching for one @@ -12675,6 +12691,7 @@ Matched = Specialization; if (FoundResult) *FoundResult = I.getPair(); + ConvertedArgs = Info.takeSugared(); } if (Matched && @@ -12699,50 +12716,55 @@ assert(SrcExpr.get()->getType() == Context.OverloadTy); OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get()); - - DeclAccessPair found; ExprResult SingleFunctionExpression; - if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( - ovl.Expression, /*complain*/ false, &found)) { - if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) { - SrcExpr = ExprError(); - return true; - } + if (ovl.Expression->hasExplicitTemplateArgs()) { + TemplateArgumentListInfo ExplicitTemplateArgs; + ovl.Expression->copyTemplateArgumentsInto(ExplicitTemplateArgs); + + const TemplateArgumentList *ConvertedArgs; + DeclAccessPair found; + if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( + ovl.Expression, ExplicitTemplateArgs, ConvertedArgs, + /*Complain=*/false, &found)) { + if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) { + SrcExpr = ExprError(); + return true; + } - // 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(fn) && - cast(fn)->isInstance()) { - if (!complain) return false; - - Diag(ovl.Expression->getExprLoc(), - diag::err_bound_member_function) - << 0 << 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. - SrcExpr = ExprError(); - return true; - } + // 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(fn) && + cast(fn)->isInstance()) { + if (!complain) + return false; - // Fix the expression to refer to 'fn'. - SingleFunctionExpression = - FixOverloadedFunctionReference(SrcExpr.get(), found, fn); + Diag(ovl.Expression->getExprLoc(), diag::err_bound_member_function) + << 0 << ovl.Expression->getSourceRange(); - // If desired, do function-to-pointer decay. - if (doFunctionPointerConversion) { - SingleFunctionExpression = - DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.get()); - if (SingleFunctionExpression.isInvalid()) { + // 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. SrcExpr = ExprError(); return true; } + + // Fix the expression to refer to 'fn'. + SingleFunctionExpression = FixOverloadedFunctionReference( + SrcExpr.get(), found, fn, ConvertedArgs); + + // If desired, do function-to-pointer decay. + if (doFunctionPointerConversion) { + SingleFunctionExpression = DefaultFunctionArrayLvalueConversion( + SingleFunctionExpression.get()); + if (SingleFunctionExpression.isInvalid()) { + SrcExpr = ExprError(); + return true; + } + } } } @@ -13255,7 +13277,8 @@ SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl); if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc())) return ExprError(); - Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl, + (*Best)->Deduced); return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, ExecConfig, /*IsExecConfig=*/false, (*Best)->IsADLCandidate); @@ -13313,7 +13336,8 @@ // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. FunctionDecl *FDecl = (*Best)->Function; - Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl, + (*Best)->Deduced); return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, ExecConfig, /*IsExecConfig=*/false, (*Best)->IsADLCandidate); @@ -14581,7 +14605,8 @@ if (!Succeeded) return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best)); - MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); + MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method, + Best->Deduced); // If overload resolution picked a static member, build a // non-member call based on that function. @@ -15196,11 +15221,13 @@ /// perhaps a '&' around it). We have resolved the overloaded function /// to the function declaration Fn, so patch up the expression E to /// refer (possibly indirectly) to Fn. Returns the new expr. -Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, - FunctionDecl *Fn) { +Expr * +Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced) { if (ParenExpr *PE = dyn_cast(E)) { - Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), - Found, Fn); + Expr *SubExpr = + FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn, Deduced); if (SubExpr == PE->getSubExpr()) return PE; @@ -15208,8 +15235,8 @@ } if (ImplicitCastExpr *ICE = dyn_cast(E)) { - Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), - Found, Fn); + Expr *SubExpr = + FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn, Deduced); assert(Context.hasSameType(ICE->getSubExpr()->getType(), SubExpr->getType()) && "Implicit cast type cannot be determined from overload"); @@ -15224,8 +15251,8 @@ if (auto *GSE = dyn_cast(E)) { if (!GSE->isResultDependent()) { - Expr *SubExpr = - FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn); + Expr *SubExpr = FixOverloadedFunctionReference(GSE->getResultExpr(), + Found, Fn, Deduced); if (SubExpr == GSE->getResultExpr()) return GSE; @@ -15259,7 +15286,7 @@ // UnresolvedLookupExpr holding an overloaded member function // or template. Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), - Found, Fn); + Found, Fn, Deduced); if (SubExpr == UnOp->getSubExpr()) return UnOp; @@ -15284,8 +15311,8 @@ UnOp->getOperatorLoc(), false, CurFPFeatureOverrides()); } } - Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), - Found, Fn); + Expr *SubExpr = + FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn, Deduced); if (SubExpr == UnOp->getSubExpr()) return UnOp; @@ -15315,7 +15342,7 @@ DeclRefExpr *DRE = BuildDeclRefExpr( Fn, Type, ValueKind, ULE->getNameInfo(), ULE->getQualifierLoc(), - Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs); + Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs, Deduced); DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1); return DRE; } @@ -15337,7 +15364,7 @@ DeclRefExpr *DRE = BuildDeclRefExpr( Fn, Fn->getType(), VK_LValue, MemExpr->getNameInfo(), MemExpr->getQualifierLoc(), Found.getDecl(), - MemExpr->getTemplateKeywordLoc(), TemplateArgs); + MemExpr->getTemplateKeywordLoc(), TemplateArgs, Deduced); DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1); return DRE; } else { @@ -15370,10 +15397,11 @@ llvm_unreachable("Invalid reference to overloaded function"); } -ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, - DeclAccessPair Found, - FunctionDecl *Fn) { - return FixOverloadedFunctionReference(E.get(), Found, Fn); +ExprResult +Sema::FixOverloadedFunctionReference(ExprResult E, DeclAccessPair Found, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced) { + return FixOverloadedFunctionReference(E.get(), Found, Fn, Deduced); } bool clang::shouldEnforceArgLimit(bool PartialOverloading, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4583,14 +4583,15 @@ /// a given template-id. struct PartialSpecMatchResult { VarTemplatePartialSpecializationDecl *Partial; - TemplateArgumentList *Args; + TemplateArgumentList *CanonicalArgs, *SugaredArgs; }; } // end anonymous namespace DeclResult Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) { + const TemplateArgumentListInfo &TemplateArgs, + const TemplateArgumentList *&ConvertedArgs) { assert(Template && "A variable template id without template?"); // Check that the template argument list is well-formed for this template. @@ -4608,6 +4609,8 @@ TemplateArgs, CanonicalConverted)) return DeclResult(); + ConvertedArgs = TemplateArgumentList::CreateCopy(Context, SugaredConverted); + // Find the variable template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; @@ -4623,9 +4626,11 @@ // the set of specializations, based on the closest partial specialization // that it represents. That is, VarDecl *InstantiationPattern = Template->getTemplatedDecl(); - TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, - CanonicalConverted); - TemplateArgumentList *InstantiationArgs = &TemplateArgList; + TemplateArgumentList SugaredArgList(TemplateArgumentList::OnStack, + SugaredConverted); + TemplateArgumentList CanonicalArgList(TemplateArgumentList::OnStack, + CanonicalConverted); + TemplateArgumentList *InstantiationArgs = &CanonicalArgList; bool AmbiguousPartialSpec = false; typedef PartialSpecMatchResult MatchResult; SmallVector Matched; @@ -4646,7 +4651,7 @@ TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (TemplateDeductionResult Result = - DeduceTemplateArguments(Partial, TemplateArgList, Info)) { + DeduceTemplateArguments(Partial, SugaredArgList, Info)) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate().set( @@ -4656,7 +4661,8 @@ } else { Matched.push_back(PartialSpecMatchResult()); Matched.back().Partial = Partial; - Matched.back().Args = Info.takeCanonical(); + Matched.back().SugaredArgs = Info.takeSugared(); + Matched.back().CanonicalArgs = Info.takeCanonical(); } } @@ -4699,7 +4705,7 @@ // Instantiate using the best variable template partial specialization. InstantiationPattern = Best->Partial; - InstantiationArgs = Best->Args; + InstantiationArgs = Best->CanonicalArgs; } else { // -- If no match is found, the instantiation is generated // from the primary template. @@ -4724,9 +4730,10 @@ // Print the matching partial specializations. for (MatchResult P : Matched) + // FIXME: Use SugaredArgs here. Diag(P.Partial->getLocation(), diag::note_partial_spec_match) << getTemplateArgumentBindingsText(P.Partial->getTemplateParameters(), - *P.Args); + *P.CanonicalArgs); return true; } @@ -4745,9 +4752,9 @@ const DeclarationNameInfo &NameInfo, VarTemplateDecl *Template, SourceLocation TemplateLoc, const TemplateArgumentListInfo *TemplateArgs) { - + const TemplateArgumentList *ConvertedArgs; DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(), - *TemplateArgs); + *TemplateArgs, ConvertedArgs); if (Decl.isInvalid()) return ExprError(); @@ -4761,7 +4768,8 @@ // Build an ordinary singleton decl ref. return BuildDeclarationNameExpr(SS, NameInfo, Var, - /*FoundD=*/nullptr, TemplateArgs); + /*FoundD=*/nullptr, TemplateArgs, + ConvertedArgs); } void Sema::diagnoseMissingTemplateArguments(TemplateName Name, @@ -7438,13 +7446,14 @@ ->isFunctionType())) { if (Arg->getType() == Context.OverloadTy) { - if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, - true, - FoundResult)) { + const TemplateArgumentList *ConvertedArgs; + if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction( + Arg, ParamType, true, FoundResult, ConvertedArgs)) { if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc())) return ExprError(); - Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + Arg = + FixOverloadedFunctionReference(Arg, FoundResult, Fn, ConvertedArgs); ArgType = Arg->getType(); } else return ExprError(); @@ -7489,14 +7498,15 @@ "Only object references allowed here"); if (Arg->getType() == Context.OverloadTy) { - if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, - ParamRefType->getPointeeType(), - true, - FoundResult)) { + const TemplateArgumentList *ConvertedArgs; + if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction( + Arg, ParamRefType->getPointeeType(), true, FoundResult, + ConvertedArgs)) { if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc())) return ExprError(); - Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + Arg = + FixOverloadedFunctionReference(Arg, FoundResult, Fn, ConvertedArgs); ArgType = Arg->getType(); } else return ExprError(); @@ -10276,8 +10286,10 @@ TemplateArgumentListInfo TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId); - DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc, - D.getIdentifierLoc(), TemplateArgs); + const TemplateArgumentList *ConvertedArgs; + DeclResult Res = + CheckVarTemplateId(PrevTemplate, TemplateLoc, D.getIdentifierLoc(), + TemplateArgs, ConvertedArgs); if (Res.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3687,7 +3687,8 @@ /// Gets the type of a function for template-argument-deducton /// purposes when it's considered as part of an overload set. static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, - FunctionDecl *Fn) { + FunctionDecl *Fn, + ArrayRef Args) { // We may need to deduce the return type of the function now. if (S.getLangOpts().CPlusPlus14 && Fn->getReturnType()->isUndeducedType() && S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false)) @@ -3728,6 +3729,11 @@ if (R.IsAddressOfOperand) TDF |= TDF_IgnoreQualifiers; + // Gather the explicit template arguments, if any. + TemplateArgumentListInfo ExplicitTemplateArgs; + if (Ovl->hasExplicitTemplateArgs()) + Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); + // C++0x [temp.deduct.call]p6: // When P is a function type, pointer to function type, or pointer // to member function type: @@ -3737,28 +3743,27 @@ !ParamType->isMemberFunctionPointerType()) { if (Ovl->hasExplicitTemplateArgs()) { // But we can still look for an explicit specialization. - if (FunctionDecl *ExplicitSpec - = S.ResolveSingleFunctionTemplateSpecialization(Ovl)) - return GetTypeOfFunction(S, R, ExplicitSpec); + const TemplateArgumentList *ConvertedArgs; + if (FunctionDecl *ExplicitSpec = + S.ResolveSingleFunctionTemplateSpecialization( + Ovl, ExplicitTemplateArgs, ConvertedArgs)) + return GetTypeOfFunction(S, R, ExplicitSpec, ConvertedArgs->asArray()); } DeclAccessPair DAP; if (FunctionDecl *Viable = S.resolveAddressOfSingleOverloadCandidate(Arg, DAP)) - return GetTypeOfFunction(S, R, Viable); + return GetTypeOfFunction(S, R, Viable, None); return {}; } - // Gather the explicit template arguments, if any. - TemplateArgumentListInfo ExplicitTemplateArgs; - if (Ovl->hasExplicitTemplateArgs()) - Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); QualType Match; for (UnresolvedSetIterator I = Ovl->decls_begin(), E = Ovl->decls_end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); + const TemplateArgumentList *ConvertedArgs = nullptr; if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) { // - If the argument is an overload set containing one or more // function templates, the parameter is treated as a @@ -3774,10 +3779,12 @@ continue; D = Specialization; + ConvertedArgs = Info.takeSugared(); } FunctionDecl *Fn = cast(D); - QualType ArgType = GetTypeOfFunction(S, R, Fn); + QualType ArgType = GetTypeOfFunction( + S, R, Fn, ConvertedArgs ? ConvertedArgs->asArray() : None); if (ArgType.isNull()) continue; // Function-to-pointer conversion. diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -563,6 +563,9 @@ NamedDecl *FirstQualifierInScope = nullptr, bool AllowInjectedClassName = false); + Optional + TransformTemplateArgument(const TemplateArgument &Arg); + /// Transform the given template argument. /// /// By default, this operation transforms the type, expression, or @@ -2496,11 +2499,12 @@ ValueDecl *VD, const DeclarationNameInfo &NameInfo, NamedDecl *Found, - TemplateArgumentListInfo *TemplateArgs) { + TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD, Found, - TemplateArgs); + TemplateArgs, ConvertedArgs); } /// Build a new expression in parentheses. @@ -4373,6 +4377,76 @@ llvm_unreachable("overloaded function decl survived to here"); } +template +Optional +TreeTransform::TransformTemplateArgument(const TemplateArgument &Arg) { + switch (auto Kind = Arg.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Unexpected TemplateArgument Null"); + case TemplateArgument::Expression: + llvm_unreachable("Unexpected TemplateArgument Expr"); + + case TemplateArgument::Pack: { + SmallVector Args(Arg.getPackAsArray()); + for (auto &I : Args) { + const auto Arg = getDerived().TransformTemplateArgument(I); + if (!Arg) + return None; + I = *Arg; + } + return TemplateArgument( + TemplateArgumentList::CreateCopy(getSema().Context, Args)->asArray()); + } + + case TemplateArgument::Integral: + case TemplateArgument::NullPtr: + case TemplateArgument::Declaration: { + QualType T = Arg.getNonTypeTemplateArgumentType(); + QualType NewT = getDerived().TransformType(T); + if (NewT.isNull()) + return None; + + ValueDecl *D = Arg.getKind() == TemplateArgument::Declaration + ? Arg.getAsDecl() + : nullptr; + ValueDecl *NewD = D ? cast_or_null(getDerived().TransformDecl( + getDerived().getBaseLocation(), D)) + : nullptr; + if (D && !NewD) + return None; + if (NewT == T && D == NewD) + return Arg; + if (Kind == TemplateArgument::Integral) + return TemplateArgument(getSema().Context, Arg.getAsIntegral(), NewT); + if (Kind == TemplateArgument::NullPtr) + return TemplateArgument(NewT, /*IsNullPtr=*/true); + assert(Kind == TemplateArgument::Declaration); + return TemplateArgument(NewD, NewT); + } + case TemplateArgument::Type: + if (QualType T = getDerived().TransformType(Arg.getAsType()); !T.isNull()) + return TemplateArgument(T); + return None; + case TemplateArgument::Template: { + CXXScopeSpec SS; + if (TemplateName Template = getDerived().TransformTemplateName( + SS, Arg.getAsTemplate(), SourceLocation()); + !Template.isNull()) + return TemplateArgument(Template); + return None; + } + case TemplateArgument::TemplateExpansion: { + CXXScopeSpec SS; + if (TemplateName Template = getDerived().TransformTemplateName( + SS, Arg.getAsTemplateOrTemplatePattern(), SourceLocation()); + !Template.isNull()) + return TemplateArgument(Template, Arg.getNumTemplateExpansions()); + return None; + } + } + llvm_unreachable("Unexpected Template Kind"); +} + template void TreeTransform::InventTemplateArgumentLoc( const TemplateArgument &Arg, @@ -4393,39 +4467,15 @@ case TemplateArgument::Integral: case TemplateArgument::NullPtr: - case TemplateArgument::Declaration: { + case TemplateArgument::Declaration: // Transform a resolved template argument straight to a resolved template // argument. We get here when substituting into an already-substituted // template type argument during concept satisfaction checking. - QualType T = Arg.getNonTypeTemplateArgumentType(); - QualType NewT = getDerived().TransformType(T); - if (NewT.isNull()) - return true; - - ValueDecl *D = Arg.getKind() == TemplateArgument::Declaration - ? Arg.getAsDecl() - : nullptr; - ValueDecl *NewD = D ? cast_or_null(getDerived().TransformDecl( - getDerived().getBaseLocation(), D)) - : nullptr; - if (D && !NewD) - return true; - - if (NewT == T && D == NewD) - Output = Input; - else if (Arg.getKind() == TemplateArgument::Integral) - Output = TemplateArgumentLoc( - TemplateArgument(getSema().Context, Arg.getAsIntegral(), NewT), - TemplateArgumentLocInfo()); - else if (Arg.getKind() == TemplateArgument::NullPtr) - Output = TemplateArgumentLoc(TemplateArgument(NewT, /*IsNullPtr=*/true), - TemplateArgumentLocInfo()); - else - Output = TemplateArgumentLoc(TemplateArgument(NewD, NewT), - TemplateArgumentLocInfo()); - - return false; - } + if (const auto Out = getDerived().TransformTemplateArgument(Arg)) { + Output = TemplateArgumentLoc(*Out, TemplateArgumentLocInfo()); + return false; + } + return true; case TemplateArgument::Type: { TypeSourceInfo *DI = Input.getTypeSourceInfo(); @@ -6690,6 +6740,7 @@ ArgIterator(*this, ConvertedArgs.begin()), ArgIterator(*this, ConvertedArgs.end()), NewTemplateArgs)) return QualType(); + assert(NewTemplateArgs.size() != 0); } else { using ArgIterator = TemplateArgumentLocContainerIterator; @@ -10581,9 +10632,22 @@ TransArgs)) return ExprError(); } + const TemplateArgumentList *NewConvertedArgs = nullptr; + if (const TemplateArgumentList *OldConvertedArgs = E->getConvertedArgs()) { + assert(OldConvertedArgs->size() != 0); + SmallVector NewArgs(OldConvertedArgs->asArray()); + for (auto I : NewArgs) { + const auto Arg = getDerived().TransformTemplateArgument(I); + if (!Arg) + return ExprError(); + I = *Arg; + } + NewConvertedArgs = + TemplateArgumentList::CreateCopy(getSema().Context, NewArgs); + } - return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, - Found, TemplateArgs); + return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, Found, + TemplateArgs, NewConvertedArgs); } template diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8844,6 +8844,15 @@ TemplArgs.push_back(readTemplateArgument(Canonicalize)); } +const TemplateArgumentList * +ASTRecordReader::readTemplateArgumentList(bool Canonicalize) { + SmallVector Args; + readTemplateArgumentList(Args, Canonicalize); + if (Args.size() == 0) + return nullptr; + return TemplateArgumentList::CreateCopy(getContext(), Args); +} + /// Read a UnresolvedSet structure. void ASTRecordReader::readUnresolvedSet(LazyASTUnresolvedSet &Set) { unsigned NumDecls = readInt(); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -595,6 +595,7 @@ E->DeclRefExprBits.HadMultipleCandidates = Record.readInt(); E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); E->DeclRefExprBits.NonOdrUseReason = Record.readInt(); + unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record.readInt(); @@ -612,6 +613,7 @@ E->getTrailingObjects(), NumTemplateArgs); E->D = readDeclAs(); + E->ConvertedArgs = Record.readTemplateArgumentList(); E->setLocation(readSourceLocation()); E->DNLoc = Record.readDeclarationNameLoc(E->getDecl()->getDeclName()); } @@ -1027,6 +1029,7 @@ E->MemberExprBits.HadMultipleCandidates = Record.readInt(); E->MemberExprBits.NonOdrUseReason = Record.readInt(); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); + E->Deduced = Record.readTemplateArgumentList(); if (HasQualifier || HasFoundDecl) { DeclAccessPair FoundDecl; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2311,6 +2311,7 @@ Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConvertedArgs Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -621,7 +621,8 @@ if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && (E->getDecl() == E->getFoundDecl()) && nk == DeclarationName::Identifier && - !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse()) { + !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse() && + !E->getConvertedArgs()) { AbbrevToUse = Writer.getDeclRefExprAbbrev(); } @@ -636,6 +637,10 @@ E->getTrailingObjects()); Record.AddDeclRef(E->getDecl()); + if (E->ConvertedArgs) + Record.AddTemplateArgumentList(E->ConvertedArgs); + else + Record.push_back(0); Record.AddSourceLocation(E->getLocation()); Record.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName()); Code = serialization::EXPR_DECL_REF; @@ -911,6 +916,10 @@ Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->isNonOdrUse()); Record.AddSourceLocation(E->getOperatorLoc()); + if (E->Deduced) + Record.AddTemplateArgumentList(E->Deduced); + else + Record.push_back(0); if (HasFoundDecl) { DeclAccessPair FoundDecl = E->getFoundDecl();