diff options
29 files changed, 578 insertions, 343 deletions
diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index c40b926..343db34 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -489,6 +489,13 @@ class TypeSourceInfo; /// error. llvm::Expected<APValue> 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<TemplateArgumentList *> 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/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 7ba21aa..d2778ae 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -265,7 +265,7 @@ public: /// Create a new template argument list that copies the given set of /// template arguments. - static TemplateArgumentList *CreateCopy(ASTContext &Context, + static TemplateArgumentList *CreateCopy(const ASTContext &Context, ArrayRef<TemplateArgument> Args); /// Retrieve the template argument at a given index. diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 08e34fd..2ba787a 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1274,6 +1274,8 @@ class DeclRefExpr final /// 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; @@ -1298,7 +1300,8 @@ class DeclRefExpr final SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, 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. @@ -1317,6 +1320,7 @@ public: 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 * @@ -1326,6 +1330,7 @@ public: 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. @@ -1433,6 +1438,8 @@ public: return getTrailingObjects<TemplateArgumentLoc>(); } + const TemplateArgumentList *getConvertedArgs() const { return ConvertedArgs; } + /// Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { @@ -3248,6 +3255,8 @@ class MemberExpr final /// 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; @@ -3277,21 +3286,21 @@ class MemberExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs, QualType T, - ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR); + const TemplateArgumentListInfo *TemplateArgs, + 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. @@ -3302,7 +3311,8 @@ public: return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), MemberDecl, DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()), - DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None); + DeclarationNameInfo(), nullptr, /*Deduced=*/{}, T, VK, OK, + NOUR_None); } static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, @@ -3328,6 +3338,8 @@ public: return *getTrailingObjects<DeclAccessPair>(); } + 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 index 0455e1f..77e3100a 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -957,6 +957,7 @@ public: bool HadMultipleCandidates; FunctionDecl *Function; DeclAccessPair FoundDecl; + const TemplateArgumentList *ConvertedArgs; }; union { @@ -1262,9 +1263,10 @@ public: /// /// \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 index 6e08762..4ec7163 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -961,6 +961,9 @@ class Sema; 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 index 069fe07..8b7d651 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6856,7 +6856,8 @@ public: const CXXScopeSpec *SS = nullptr, NamedDecl *FoundD = nullptr, SourceLocation TemplateKWLoc = SourceLocation(), - const TemplateArgumentListInfo *TemplateArgs = nullptr); + const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertArgs = nullptr); /// BuildDeclRefExpr - Build an expression that references a /// declaration that does not require a closure capture. @@ -6865,7 +6866,8 @@ public: const DeclarationNameInfo &NameInfo, NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr, SourceLocation TemplateKWLoc = SourceLocation(), - const TemplateArgumentListInfo *TemplateArgs = nullptr); + const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertArgs = nullptr); bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen); @@ -6887,6 +6889,7 @@ public: const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr, + const TemplateArgumentList *ConvertedArgs = nullptr, bool AcceptInvalidDecl = false); // ExpandFunctionLocalPredefinedMacros - Returns a new vector of Tokens, @@ -8700,14 +8703,13 @@ public: SourceLocation TemplateKWLoc, UnqualifiedId &Member, Decl *ObjCImpDecl); - 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, + 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); // Check whether the declarations we found through a nested-name // specifier in a member expression are actually members of the base @@ -10299,6 +10301,7 @@ public: ADLCallKind IsADLCandidate = ADLCallKind::NotADL, ConversionSequenceList EarlyConversions = {}, OverloadCandidateParamOrder PO = {}, + const TemplateArgumentList *Deduced = nullptr, bool AggregateCandidateDeduction = false, bool StrictPackMatch = false); /// Add all of the function declarations in the given function set to @@ -10335,6 +10338,7 @@ public: bool PartialOverloading = false, ConversionSequenceList EarlyConversions = {}, OverloadCandidateParamOrder PO = {}, + const TemplateArgumentList *Deduced = nullptr, bool StrictPackMatch = false); /// Add a C++ member function template as a candidate to the candidate @@ -10543,6 +10547,7 @@ public: FunctionDecl * ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, bool Complain, DeclAccessPair &Found, + const TemplateArgumentList *&ConvertedArgs, bool *pHadMultipleCandidates = nullptr); /// Given an expression that refers to an overloaded function, try to @@ -10576,7 +10581,9 @@ public: /// If no template-ids are found, no diagnostics are emitted and NULL is /// returned. FunctionDecl *ResolveSingleFunctionTemplateSpecialization( - OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr, + OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs, + const TemplateArgumentList *&ConvertedArgs, bool Complain = false, + DeclAccessPair *Found = nullptr, TemplateSpecCandidateSet *FailedTSC = nullptr, bool ForTypeDeduction = false); @@ -10761,11 +10768,14 @@ public: /// 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. - ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, - FunctionDecl *Fn); - ExprResult FixOverloadedFunctionReference(ExprResult, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); + ExprResult + FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced); + ExprResult + FixOverloadedFunctionReference(ExprResult, DeclAccessPair FoundDecl, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced); /// - Returns a selector which best matches given argument list or /// nullptr if none could be found @@ -11545,7 +11555,8 @@ public: 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 diff --git a/clang/include/clang/Sema/SemaCUDA.h b/clang/include/clang/Sema/SemaCUDA.h index 71f05e8..645857b 100644 --- a/clang/include/clang/Sema/SemaCUDA.h +++ b/clang/include/clang/Sema/SemaCUDA.h @@ -229,8 +229,8 @@ public: /// calling priority. void EraseUnwantedMatches( const FunctionDecl *Caller, - llvm::SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> - &Matches); + llvm::SmallVectorImpl<std::tuple<DeclAccessPair, FunctionDecl *, + const TemplateArgumentList *>> &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 index cb39748..2d16387 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7493,6 +7493,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { 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) @@ -7519,7 +7520,8 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { 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); ToE->setIsImmediateEscalating(E->isImmediateEscalating()); @@ -8444,6 +8446,7 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { 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()); @@ -8468,7 +8471,7 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { 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()); } @@ -10174,6 +10177,17 @@ llvm::Expected<APValue> ASTImporter::Import(const APValue &FromValue) { return Importer.ImportAPValue(FromValue); } +llvm::Expected<TemplateArgumentList *> +ASTImporter::Import(const TemplateArgumentList *ArgList) { + ASTNodeImporter Importer(*this); + if (!ArgList) + return nullptr; + SmallVector<TemplateArgument, 4> 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/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index fb76239a..57ec0a5 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -950,7 +950,7 @@ TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args) } TemplateArgumentList * -TemplateArgumentList::CreateCopy(ASTContext &Context, +TemplateArgumentList::CreateCopy(const ASTContext &Context, ArrayRef<TemplateArgument> Args) { void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(Args.size())); return new (Mem) TemplateArgumentList(Args); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 389fa70..7d3918c 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -431,7 +431,8 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, 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; @@ -451,9 +452,12 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, 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) @@ -491,22 +495,21 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, 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; @@ -520,9 +523,10 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, 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, @@ -1734,11 +1738,13 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs, QualType T, + const TemplateArgumentListInfo *TemplateArgs, + 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; @@ -1774,7 +1780,8 @@ MemberExpr *MemberExpr::Create( 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 HasQualifier = QualifierLoc.hasQualifier(); bool HasFoundDecl = FoundDecl.getDecl() != MemberDecl || FoundDecl.getAccess() != MemberDecl->getAccess(); @@ -1788,7 +1795,7 @@ MemberExpr *MemberExpr::Create( void *Mem = C.Allocate(Size, alignof(MemberExpr)); return new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, MemberDecl, FoundDecl, NameInfo, - TemplateArgs, T, VK, OK, NOUR); + TemplateArgs, Deduced, T, VK, OK, NOUR); } MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp index c5f35b3..058d8fa 100644 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -231,8 +231,8 @@ MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl, 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 index 7302038..01d2b3a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1867,7 +1867,8 @@ static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF, 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 index 0e5fc5e..9217a8d 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -317,25 +317,28 @@ bool SemaCUDA::isImplicitHostDeviceFunction(const FunctionDecl *D) { void SemaCUDA::EraseUnwantedMatches( const FunctionDecl *Caller, - SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) { + SmallVectorImpl<std::tuple<DeclAccessPair, FunctionDecl *, + const TemplateArgumentList *>> &Matches) { if (Matches.size() <= 1) return; - using Pair = std::pair<DeclAccessPair, FunctionDecl*>; + using Tuple = + std::tuple<DeclAccessPair, FunctionDecl *, const TemplateArgumentList *>; // Gets the CUDA function preference for a call from Caller to Match. - auto GetCFP = [&](const Pair &Match) { - return IdentifyPreference(Caller, Match.second); + auto GetCFP = [&](const Tuple &Match) { + return IdentifyPreference(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 index 2824dfc..0c961c2 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1784,9 +1784,9 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, 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<CXXMethodDecl>(Fn); SrcType = Self.Context.getMemberPointerType( Fn->getType(), /*Qualifier=*/nullptr, M->getParent()); @@ -1816,16 +1816,16 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, 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; @@ -2815,10 +2815,10 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, 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, @@ -2974,10 +2974,12 @@ void CastOperation::CheckCStyleCast() { // 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 index 5a4fa97..db61af1 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -4629,7 +4629,7 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { 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 index 0b844b4..88d5c66 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1816,7 +1816,8 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(DeallocE)) { - DeallocFD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); + DeclAccessPair DAP; + DeallocFD = S.resolveAddressOfSingleOverloadCandidate(ULE, DAP); DeallocNI = ULE->getNameInfo(); if (!DeallocFD) { S.Diag(DeallocLoc, diag::err_attribute_malloc_arg_not_function) @@ -3610,9 +3611,14 @@ static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(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 index d70e42d..dc0215f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2232,11 +2232,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, 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 @@ -2301,13 +2302,16 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, NestedNameSpecifierLoc NNS, NamedDecl *FoundD, SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + const TemplateArgumentList *ConvertedArgs) { bool RefersToCapturedVariable = isa<VarDecl, BindingDecl>(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: @@ -3221,7 +3225,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, !R.getAsSingle<FunctionTemplateDecl>() && !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 @@ -3252,10 +3256,11 @@ static void diagnoseUncapturableValueReferenceOrBinding(Sema &S, 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<FunctionTemplateDecl>(D) && "Cannot refer unambiguously to a function template"); + assert(!TemplateArgs || ConvertedArgs); SourceLocation Loc = NameInfo.getLoc(); if (CheckDeclInExpr(*this, Loc, D, AcceptInvalidDecl)) { @@ -3485,9 +3490,9 @@ ExprResult Sema::BuildDeclarationNameExpr( break; } - auto *E = - BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD, - /*FIXME: TemplateKWLoc*/ SourceLocation(), TemplateArgs); + auto *E = BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD, + /*FIXME: TemplateKWLoc*/ SourceLocation(), + TemplateArgs, ConvertedArgs); // Clang AST consumers assume a DeclRefExpr refers to a valid decl. We // wrap a DeclRefExpr referring to an invalid decl with a dependent-type // RecoveryExpr to avoid follow-up semantic analysis (thus prevent bogus @@ -6657,7 +6662,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, Fn = DeclRefExpr::Create( Context, FDecl->getQualifierLoc(), SourceLocation(), FDecl, false, SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl, - nullptr, DRE->isNonOdrUse()); + nullptr, nullptr, DRE->isNonOdrUse()); } } } else if (auto *ME = dyn_cast<MemberExpr>(NakedFn)) @@ -9758,9 +9763,10 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, // 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; } @@ -14246,14 +14252,19 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { } OverloadExpr *Ovl = cast<OverloadExpr>(E); - if (isa<UnresolvedMemberExpr>(Ovl)) - if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) { - Diag(OpLoc, diag::err_invalid_form_pointer_member_function) - << OrigOp.get()->getSourceRange(); - return QualType(); - } - - return Context.OverloadTy; + if (!isa<UnresolvedMemberExpr>(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) @@ -19473,7 +19484,8 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, 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: { @@ -19519,8 +19531,8 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, 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()) @@ -19537,7 +19549,8 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, 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: { @@ -21191,7 +21204,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { 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 index e43f5e3..0a4917c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2847,7 +2847,10 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, FoundDelete.suppressDiagnostics(); - SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches; + SmallVector< + std::tuple<DeclAccessPair, FunctionDecl *, const TemplateArgumentList *>, + 2> + Matches; // Whether we're looking for a placement operator delete is dictated // by whether we selected a placement operator new, not by whether @@ -2897,6 +2900,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, DEnd = FoundDelete.end(); D != DEnd; ++D) { FunctionDecl *Fn = nullptr; + const TemplateArgumentList *ConvertedArgs = nullptr; if (FunctionTemplateDecl *FnTmpl = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) { // Perform template argument deduction to try to match the @@ -2905,14 +2909,15 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn, Info) != TemplateDeductionResult::Success) continue; + ConvertedArgs = Info.takeSugared(); } else Fn = cast<FunctionDecl>((*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) @@ -2932,12 +2937,12 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, /*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}); } } @@ -2946,7 +2951,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // 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) @@ -2985,7 +2990,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, } 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. @@ -2994,8 +2999,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, << 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; @@ -4353,15 +4358,17 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // 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(); - ExprResult Res = FixOverloadedFunctionReference(From, Found, Fn); + ExprResult Res = + FixOverloadedFunctionReference(From, Found, Fn, ConvertedArgs); if (Res.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index b087212..f6da4ec 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -935,13 +935,14 @@ MemberExpr *Sema::BuildMemberExpr( 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); @@ -1232,8 +1233,10 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, 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(); @@ -1251,7 +1254,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SS.getWithLocInContext(Context), 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 index 87a4244..370e7ca 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3895,17 +3895,16 @@ bool InitializationSequence::isConstructorInitialization() const { 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); } @@ -4697,13 +4696,12 @@ ResolveOverloadedFunctionForReferenceBinding(Sema &S, 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(); @@ -6879,12 +6877,14 @@ void InitializationSequence::InitializeFrom(Sema &S, AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy); } else if (ICS.isBad()) { + const TemplateArgumentList *ConvertedArgs; if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) AddZeroInitializationStep(Entity.getType()); else if (DeclAccessPair Found; Initializer->getType() == Context.OverloadTy && !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, - /*Complain=*/false, Found)) + /*Complain=*/false, Found, + ConvertedArgs)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (Initializer->getType()->isFunctionType() && isExprAnUnaddressableFunction(S, Initializer)) @@ -7914,9 +7914,9 @@ ExprResult InitializationSequence::Perform(Sema &S, 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()) @@ -8795,11 +8795,13 @@ bool InitializationSequence::Diagnose(Sema &S, if (OnlyArg->getType() == S.Context.OverloadTy) { DeclAccessPair Found; + const TemplateArgumentList *ConvertedArgs; if (FunctionDecl *FD = S.ResolveAddressOfOverloadedFunction( OnlyArg, DestType.getNonReferenceType(), /*Complain=*/false, - Found)) { - if (Expr *Resolved = - S.FixOverloadedFunctionReference(OnlyArg, Found, FD).get()) + Found, ConvertedArgs)) { + if (Expr *Resolved = S.FixOverloadedFunctionReference(OnlyArg, Found, + FD, ConvertedArgs) + .get()) OnlyArg = Resolved; } } @@ -8877,10 +8879,9 @@ bool InitializationSequence::Diagnose(Sema &S, 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 index 0564557..0e6191f4 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2213,9 +2213,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, 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(); @@ -5218,8 +5218,9 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // 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(); } @@ -5708,8 +5709,9 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // 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(); } @@ -6976,8 +6978,8 @@ void Sema::AddOverloadCandidate( OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction, - bool StrictPackMatch) { + OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced, + bool AggregateCandidateDeduction, bool StrictPackMatch) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6996,7 +6998,7 @@ void Sema::AddOverloadCandidate( AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), Args, CandidateSet, SuppressUserConversions, - PartialOverloading, EarlyConversions, PO, + PartialOverloading, EarlyConversions, PO, Deduced, StrictPackMatch); return; } @@ -7041,6 +7043,7 @@ void Sema::AddOverloadCandidate( Candidate.IsADLCandidate = llvm::to_underlying(IsADLCandidate); Candidate.ExplicitCallArguments = Args.size(); Candidate.StrictPackMatch = StrictPackMatch; + 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 @@ -7612,7 +7615,8 @@ void Sema::AddMethodCandidate( Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO, bool StrictPackMatch) { + OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced, + bool StrictPackMatch) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -7644,6 +7648,7 @@ void Sema::AddMethodCandidate( CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet; Candidate.ExplicitCallArguments = Args.size(); Candidate.StrictPackMatch = StrictPackMatch; + Candidate.Deduced = Deduced; bool IgnoreExplicitObject = (Method->isExplicitObjectMemberFunction() && @@ -7853,7 +7858,8 @@ void Sema::AddMethodTemplateCandidate( AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, CandidateSet, SuppressUserConversions, PartialOverloading, - Conversions, PO, Info.hasStrictPackMatch()); + Conversions, PO, Info.takeSugared(), + Info.hasStrictPackMatch()); } /// Determine whether a given function template has a simple explicit specifier @@ -7940,7 +7946,7 @@ void Sema::AddTemplateOverloadCandidate( Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, PartialOverloading, AllowExplicit, /*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO, - Info.AggregateDeductionCandidateHasMismatchedArity, + Info.takeSugared(), Info.AggregateDeductionCandidateHasMismatchedArity, Info.hasStrictPackMatch()); } @@ -13014,7 +13020,10 @@ class AddressOfFunctionResolver { OverloadExpr::FindResult OvlExprInfo; OverloadExpr *OvlExpr; TemplateArgumentListInfo OvlExplicitTemplateArgs; - SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches; + SmallVector< + std::tuple<DeclAccessPair, FunctionDecl *, const TemplateArgumentList *>, + 4> + Matches; TemplateSpecCandidateSet FailedCandidates; public: @@ -13032,15 +13041,22 @@ public: FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) { ExtractUnqualifiedFunctionTypeFromTargetType(); + if (OvlExpr->hasExplicitTemplateArgs()) + OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs); + + const TemplateArgumentList *ConvertedArgs; if (TargetFunctionType->isFunctionType()) { if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(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<CXXMethodDecl>(Fn)) if (!Method->isStatic()) { // If the target type is a non-function type and the function found @@ -13054,14 +13070,11 @@ public: 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, [...] @@ -13104,15 +13117,17 @@ private: // 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<DeclAccessPair, FunctionDecl *> &Pair) { - return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second); - }; + const FunctionDecl *BestFn = std::get<1>(*Best); + auto IsBestOrInferiorToBest = + [this, BestFn](const std::tuple<DeclAccessPair, FunctionDecl *, + const TemplateArgumentList *> &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 @@ -13180,7 +13195,7 @@ private: if (!S.checkAddressOfFunctionIsAvailable(Specialization)) return false; - Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); + Matches.push_back({CurAccessFunPair, Specialization, Info.takeSugared()}); return true; } @@ -13227,8 +13242,9 @@ private: // 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<FunctionDecl>(FunDecl->getCanonicalDecl()))); + Matches.push_back({CurAccessFunPair, + cast<FunctionDecl>(FunDecl->getCanonicalDecl()), + nullptr}); FoundNonTemplateFunction = true; return true; } @@ -13285,7 +13301,8 @@ private: 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. @@ -13293,15 +13310,16 @@ private: 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<FunctionDecl>(*Result); + const auto &Old = Matches[Result - MatchesCopy.begin()]; + Matches[0] = {std::get<0>(Old), cast<FunctionDecl>(*Result), + std::get<2>(Old)}; Matches.resize(1); } else HasComplained |= Complain; @@ -13311,7 +13329,7 @@ private: // [...] 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]; @@ -13325,21 +13343,26 @@ private: // [...] Any given non-template function F0 is eliminated if the set // contains a second non-template function that is more // partial-ordering-constrained than F0. [...] - assert(Matches[0].second->getPrimaryTemplate() == nullptr && + auto &[_1, FD, _2] = Matches[0]; + assert(FD->getPrimaryTemplate() == nullptr && "Call EliminateAllTemplateMatches() first"); - SmallVector<std::pair<DeclAccessPair, FunctionDecl *>, 4> Results; + SmallVector<std::tuple<DeclAccessPair, FunctionDecl *, + const TemplateArgumentList *>, + 4> + Results; Results.push_back(Matches[0]); for (unsigned I = 1, N = Matches.size(); I < N; ++I) { - assert(Matches[I].second->getPrimaryTemplate() == nullptr); - FunctionDecl *F = getMorePartialOrderingConstrained( - S, Matches[I].second, Results[0].second, - /*IsFn1Reversed=*/false, - /*IsFn2Reversed=*/false); + auto &[_1, FD, _2] = Matches[I]; + assert(FD->getPrimaryTemplate() == nullptr); + FunctionDecl *F = + getMorePartialOrderingConstrained(S, FD, std::get<1>(Results[0]), + /*IsFn1Reversed=*/false, + /*IsFn2Reversed=*/false); if (!F) { Results.push_back(Matches[I]); continue; } - if (F == Matches[I].second) { + if (F == FD) { Results.clear(); Results.push_back(Matches[I]); } @@ -13419,22 +13442,26 @@ public: 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]); } }; } -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, @@ -13456,6 +13483,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>()) ResolveExceptionSpec(AddressOfExpr->getExprLoc(), FPT); FoundResult = *Resolver.getMatchingFunctionAccessPair(); + ConvertedArgs = Resolver.getMatchingFunctionConvertedArgs(); if (Complain) { if (Resolver.IsStaticMemberFunctionFromBoundPointer()) Resolver.ComplainIsStaticMemberFunctionFromBoundPointer(); @@ -13578,7 +13606,8 @@ bool Sema::resolveAndFixAddressOfSingleOverloadCandidate( // for both. DiagnoseUseOfDecl(Found, E->getExprLoc()); CheckAddressOfMemberAccess(E, DAP); - ExprResult Res = FixOverloadedFunctionReference(E, DAP, Found); + ExprResult Res = + FixOverloadedFunctionReference(E, DAP, Found, /*ConvertedArgs=*/{}); if (Res.isInvalid()) return false; Expr *Fixed = Res.get(); @@ -13590,8 +13619,10 @@ bool Sema::resolveAndFixAddressOfSingleOverloadCandidate( } FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( - OverloadExpr *ovl, bool Complain, DeclAccessPair *FoundResult, - TemplateSpecCandidateSet *FailedTSC, bool ForTypeDeduction) { + OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs, + const TemplateArgumentList *&ConvertedArgs, bool Complain, + DeclAccessPair *FoundResult, TemplateSpecCandidateSet *FailedTSC, + bool ForTypeDeduction) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] @@ -13599,12 +13630,8 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( // [...] 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; - - TemplateArgumentListInfo ExplicitTemplateArgs; - ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs); + // Specializations must have template args. + assert(ovl->hasExplicitTemplateArgs()); // Look through all of the overloaded functions, searching for one // whose type matches exactly. @@ -13662,6 +13689,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( Matched = Specialization; if (FoundResult) *FoundResult = I.getPair(); + ConvertedArgs = Info.takeSugared(); } if (Matched && @@ -13678,50 +13706,55 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( 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<CXXMethodDecl>(fn) && - cast<CXXMethodDecl>(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<CXXMethodDecl>(fn) && + cast<CXXMethodDecl>(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; + } + } } } @@ -14226,8 +14259,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl); if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc())) return ExprError(); - ExprResult Res = - SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + ExprResult Res = SemaRef.FixOverloadedFunctionReference( + Fn, (*Best)->FoundDecl, FDecl, (*Best)->Deduced); if (Res.isInvalid()) return ExprError(); return SemaRef.BuildResolvedCallExpr( @@ -14301,8 +14334,8 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. - ExprResult Res = - SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + ExprResult Res = SemaRef.FixOverloadedFunctionReference( + Fn, (*Best)->FoundDecl, FDecl, (*Best)->Deduced); if (Res.isInvalid()) return ExprError(); return SemaRef.BuildResolvedCallExpr( @@ -15742,8 +15775,8 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (!Succeeded) return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best)); - ExprResult Res = - FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); + ExprResult Res = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method, + Best->Deduced); if (Res.isInvalid()) return ExprError(); MemExprE = Res.get(); @@ -16393,11 +16426,13 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc, return FRS_Success; } -ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, - FunctionDecl *Fn) { +ExprResult +Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, + FunctionDecl *Fn, + const TemplateArgumentList *Deduced) { if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { ExprResult SubExpr = - FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn); + FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn, Deduced); if (SubExpr.isInvalid()) return ExprError(); if (SubExpr.get() == PE->getSubExpr()) @@ -16409,7 +16444,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { ExprResult SubExpr = - FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn); + FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn, Deduced); if (SubExpr.isInvalid()) return ExprError(); assert(Context.hasSameType(ICE->getSubExpr()->getType(), @@ -16426,8 +16461,8 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) { if (!GSE->isResultDependent()) { - ExprResult SubExpr = - FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn); + ExprResult SubExpr = FixOverloadedFunctionReference(GSE->getResultExpr(), + Found, Fn, Deduced); if (SubExpr.isInvalid()) return ExprError(); if (SubExpr.get() == GSE->getResultExpr()) @@ -16468,8 +16503,8 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, // Fix the subexpression, which really has to be an // UnresolvedLookupExpr holding an overloaded member function // or template. - ExprResult SubExpr = - FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn); + ExprResult SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), + Found, Fn, Deduced); if (SubExpr.isInvalid()) return ExprError(); if (SubExpr.get() == UnOp->getSubExpr()) @@ -16503,7 +16538,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, } } ExprResult SubExpr = - FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn); + FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn, Deduced); if (SubExpr.isInvalid()) return ExprError(); if (SubExpr.get() == UnOp->getSubExpr()) @@ -16537,7 +16572,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, 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; } @@ -16559,7 +16594,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, 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 { @@ -16592,10 +16627,11 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, 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 index 0b78f3d..479fcc1 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5103,14 +5103,15 @@ namespace { /// 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. @@ -5128,12 +5129,17 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgs, CTAI.CanonicalConverted)) return DeclResult(); + ConvertedArgs = + TemplateArgumentList::CreateCopy(Context, CTAI.SugaredConverted); + // Find the variable template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) { checkSpecializationReachability(TemplateNameLoc, Spec); + ConvertedArgs = + TemplateArgumentList::CreateCopy(Context, CTAI.SugaredConverted); // If we already have a variable template specialization, return it. return Spec; } @@ -5187,7 +5193,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, } else { Matched.push_back(PartialSpecMatchResult()); Matched.back().Partial = Partial; - Matched.back().Args = Info.takeSugared(); + Matched.back().SugaredArgs = Info.takeSugared(); + Matched.back().CanonicalArgs = Info.takeCanonical(); } } @@ -5230,11 +5237,13 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // Instantiate using the best variable template partial specialization. InstantiationPattern = Best->Partial; - PartialSpecArgs = Best->Args; + PartialSpecArgs = Best->SugaredArgs; } else { // -- If no match is found, the instantiation is generated // from the primary template. // InstantiationPattern = Template->getTemplatedDecl(); + ConvertedArgs = + TemplateArgumentList::CreateCopy(Context, CTAI.SugaredConverted); } // 2. Create the canonical declaration. @@ -5255,9 +5264,10 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // 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; } @@ -5275,9 +5285,9 @@ ExprResult Sema::CheckVarTemplateId( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, VarTemplateDecl *Template, NamedDecl *FoundD, SourceLocation TemplateLoc, const TemplateArgumentListInfo *TemplateArgs) { - + const TemplateArgumentList *ConvertedArgs; DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(), - *TemplateArgs); + *TemplateArgs, ConvertedArgs); if (Decl.isInvalid()) return ExprError(); @@ -5290,7 +5300,8 @@ ExprResult Sema::CheckVarTemplateId( NameInfo.getLoc()); // Build an ordinary singleton decl ref. - return BuildDeclarationNameExpr(SS, NameInfo, Var, FoundD, TemplateArgs); + return BuildDeclarationNameExpr(SS, NameInfo, Var, FoundD, TemplateArgs, + ConvertedArgs); } void Sema::diagnoseMissingTemplateArguments(TemplateName Name, @@ -8004,13 +8015,14 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ->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(); - ExprResult Res = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ExprResult Res = + FixOverloadedFunctionReference(Arg, FoundResult, Fn, ConvertedArgs); if (Res.isInvalid()) return ExprError(); Arg = Res.get(); @@ -8058,13 +8070,14 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, "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(); - ExprResult Res = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ExprResult Res = + FixOverloadedFunctionReference(Arg, FoundResult, Fn, ConvertedArgs); if (Res.isInvalid()) return ExprError(); Arg = Res.get(); @@ -11018,8 +11031,10 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, 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 index 658969b..5b79226 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4198,7 +4198,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( /// 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<TemplateArgument> 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)) @@ -4240,6 +4241,11 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, 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: @@ -4249,31 +4255,29 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, !ParamType->isMemberFunctionPointerType()) { if (Ovl->hasExplicitTemplateArgs()) { // But we can still look for an explicit specialization. + const TemplateArgumentList *ConvertedArgs; if (FunctionDecl *ExplicitSpec = S.ResolveSingleFunctionTemplateSpecialization( - Ovl, /*Complain=*/false, + Ovl, ExplicitTemplateArgs, ConvertedArgs, /*Complain=*/false, /*Found=*/nullptr, FailedTSC, /*ForTypeDeduction=*/true)) - return GetTypeOfFunction(S, R, ExplicitSpec); + 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, /*Args=*/{}); 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<FunctionTemplateDecl>(D)) { // - If the argument is an overload set containing one or more // function templates, the parameter is treated as a @@ -4290,10 +4294,12 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, continue; D = Specialization; + ConvertedArgs = Info.takeSugared(); } FunctionDecl *Fn = cast<FunctionDecl>(D); - QualType ArgType = GetTypeOfFunction(S, R, Fn); + QualType ArgType = GetTypeOfFunction( + S, R, Fn, ConvertedArgs ? ConvertedArgs->asArray() : std::nullopt); if (ArgType.isNull()) continue; // Function-to-pointer conversion. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 68c8010..5748ab8 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1635,6 +1635,7 @@ namespace { } return Type; } + using inherited::TransformTemplateArgument; // Override the default version to handle a rewrite-template-arg-pack case // for building a deduction guide. bool TransformTemplateArgument(const TemplateArgumentLoc &Input, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6767766..222dd93 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -597,6 +597,9 @@ public: NamedDecl *FirstQualifierInScope = nullptr, bool AllowInjectedClassName = false); + std::optional<TemplateArgument> + TransformTemplateArgument(const TemplateArgument &Arg); + /// Transform the given template argument. /// /// By default, this operation transforms the type, expression, or @@ -2707,11 +2710,12 @@ public: 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. @@ -4827,6 +4831,80 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, llvm_unreachable("overloaded function decl survived to here"); } +template <typename Derived> +std::optional<TemplateArgument> +TreeTransform<Derived>::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<TemplateArgument, 4> Args(Arg.getPackAsArray()); + for (auto &I : Args) { + const auto Arg = getDerived().TransformTemplateArgument(I); + if (!Arg) + return std::nullopt; + I = *Arg; + } + return TemplateArgument( + TemplateArgumentList::CreateCopy(getSema().Context, Args)->asArray()); + } + + case TemplateArgument::Integral: + case TemplateArgument::NullPtr: + case TemplateArgument::Declaration: + case TemplateArgument::StructuralValue: { + QualType T = Arg.getNonTypeTemplateArgumentType(); + QualType NewT = getDerived().TransformType(T); + if (NewT.isNull()) + return std::nullopt; + + ValueDecl *D = Arg.getKind() == TemplateArgument::Declaration + ? Arg.getAsDecl() + : nullptr; + ValueDecl *NewD = D ? cast_or_null<ValueDecl>(getDerived().TransformDecl( + getDerived().getBaseLocation(), D)) + : nullptr; + if (D && !NewD) + return std::nullopt; + 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); + if (Kind == TemplateArgument::StructuralValue) + return TemplateArgument(getSema().Context, NewT, + Arg.getAsStructuralValue()); + assert(Kind == TemplateArgument::Declaration); + return TemplateArgument(NewD, NewT); + } + case TemplateArgument::Type: + if (QualType T = getDerived().TransformType(Arg.getAsType()); !T.isNull()) + return TemplateArgument(T); + return std::nullopt; + case TemplateArgument::Template: { + CXXScopeSpec SS; + if (TemplateName Template = getDerived().TransformTemplateName( + SS, Arg.getAsTemplate(), SourceLocation()); + !Template.isNull()) + return TemplateArgument(Template); + return std::nullopt; + } + case TemplateArgument::TemplateExpansion: { + CXXScopeSpec SS; + if (TemplateName Template = getDerived().TransformTemplateName( + SS, Arg.getAsTemplateOrTemplatePattern(), SourceLocation()); + !Template.isNull()) + return TemplateArgument(Template, Arg.getNumTemplateExpansions()); + return std::nullopt; + } + } + llvm_unreachable("Unexpected Template Kind"); +} + template<typename Derived> void TreeTransform<Derived>::InventTemplateArgumentLoc( const TemplateArgument &Arg, @@ -4848,45 +4926,15 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Integral: case TemplateArgument::NullPtr: case TemplateArgument::Declaration: - case TemplateArgument::StructuralValue: { + case TemplateArgument::StructuralValue: // 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<ValueDecl>(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 if (Arg.getKind() == TemplateArgument::Declaration) - Output = TemplateArgumentLoc(TemplateArgument(NewD, NewT), - TemplateArgumentLocInfo()); - else if (Arg.getKind() == TemplateArgument::StructuralValue) - Output = TemplateArgumentLoc( - TemplateArgument(getSema().Context, NewT, Arg.getAsStructuralValue()), - TemplateArgumentLocInfo()); - else - llvm_unreachable("unexpected template argument kind"); - - return false; - } + if (const auto Out = getDerived().TransformTemplateArgument(Arg)) { + Output = TemplateArgumentLoc(*Out, TemplateArgumentLocInfo()); + return false; + } + return true; case TemplateArgument::Type: { TypeSourceInfo *DI = Input.getTypeSourceInfo(); @@ -7368,6 +7416,7 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( ArgIterator(*this, ConvertedArgs.begin()), ArgIterator(*this, ConvertedArgs.end()), NewTemplateArgs)) return QualType(); + assert(NewTemplateArgs.size() != 0); } else { using ArgIterator = TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>; @@ -12881,9 +12930,22 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { TransArgs)) return ExprError(); } + const TemplateArgumentList *NewConvertedArgs = nullptr; + if (const TemplateArgumentList *OldConvertedArgs = E->getConvertedArgs()) { + assert(OldConvertedArgs->size() != 0); + SmallVector<TemplateArgument, 4> 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<typename Derived> diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 969b1f7..06adaee 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9798,6 +9798,15 @@ void ASTRecordReader::readTemplateArgumentList( TemplArgs.push_back(readTemplateArgument(Canonicalize)); } +const TemplateArgumentList * +ASTRecordReader::readTemplateArgumentList(bool Canonicalize) { + SmallVector<TemplateArgument, 8> 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 index d26152f..a4f1856 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -623,6 +623,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.HasTemplateKWAndArgsInfo = CurrentUnpackingBits->getNextBit(); E->DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; + unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record.readInt(); @@ -640,6 +641,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs); E->D = readDeclAs<ValueDecl>(); + E->ConvertedArgs = Record.readTemplateArgumentList(); E->setLocation(readSourceLocation()); E->DNLoc = Record.readDeclarationNameLoc(E->getDecl()->getDeclName()); } @@ -1072,6 +1074,7 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { E->MemberExprBits.NonOdrUseReason = CurrentUnpackingBits->getNextBits(/*Width=*/2); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); + E->Deduced = Record.readTemplateArgumentList(); if (HasQualifier) new (E->getTrailingObjects<NestedNameSpecifierLoc>()) diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 3a7a234..13abeda 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2786,6 +2786,7 @@ void ASTWriter::WriteDeclAbbrevs() { // GetDeclFound, HasQualifier and ExplicitTemplateArgs should be 0. Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); 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 index 23bb5ff..85a89b2 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -706,7 +706,8 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) && (E->getDecl() == E->getFoundDecl()) && - nk == DeclarationName::Identifier && E->getObjectKind() == OK_Ordinary) { + nk == DeclarationName::Identifier && E->getObjectKind() == OK_Ordinary && + !E->getConvertedArgs()) { AbbrevToUse = Writer.getDeclRefExprAbbrev(); } @@ -721,6 +722,10 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { E->getTrailingObjects<TemplateArgumentLoc>()); 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; @@ -1011,6 +1016,10 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { CurrentPackingBits.addBit(E->hadMultipleCandidates()); CurrentPackingBits.addBits(E->isNonOdrUse(), /*Width=*/2); Record.AddSourceLocation(E->getOperatorLoc()); + if (E->Deduced) + Record.AddTemplateArgumentList(E->Deduced); + else + Record.push_back(0); if (HasQualifier) Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); |