[llvm-branch-commits] [clang] WIP: [clang] Store in exprs the conveed arguments for function calls. (PR #132444)
Matheus Izvekov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 2 18:53:36 PDT 2025
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/132444
>From abefb0c0462ee13a3b08e74ef9cad29bdc02594e Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Sat, 17 Sep 2022 23:34:04 +0200
Subject: [PATCH] WIP: [clang] Store in exprs the conveed arguments for
function calls.
WIP - Not ready for review
This keeps around in expressions the sugared converted arguments.
This is a pre-requisite for adding some additional users of the
resugaring transform.
Differential Revision: https://reviews.llvm.org/D134115
---
clang/include/clang/AST/ASTImporter.h | 7 +
clang/include/clang/AST/DeclTemplate.h | 2 +-
clang/include/clang/AST/Expr.h | 38 ++-
clang/include/clang/Sema/Initialization.h | 8 +-
clang/include/clang/Sema/Overload.h | 3 +
clang/include/clang/Sema/Sema.h | 45 ++--
clang/include/clang/Sema/SemaCUDA.h | 4 +-
clang/lib/AST/ASTImporter.cpp | 18 +-
clang/lib/AST/DeclTemplate.cpp | 2 +-
clang/lib/AST/Expr.cpp | 49 ++--
clang/lib/Analysis/BodyFarm.cpp | 4 +-
clang/lib/CodeGen/CGExpr.cpp | 3 +-
clang/lib/Sema/SemaCUDA.cpp | 17 +-
clang/lib/Sema/SemaCast.cpp | 30 +--
clang/lib/Sema/SemaChecking.cpp | 2 +-
clang/lib/Sema/SemaDeclAttr.cpp | 12 +-
clang/lib/Sema/SemaExpr.cpp | 68 +++---
clang/lib/Sema/SemaExprCXX.cpp | 31 ++-
clang/lib/Sema/SemaExprMember.cpp | 19 +-
clang/lib/Sema/SemaInit.cpp | 45 ++--
clang/lib/Sema/SemaOverload.cpp | 270 ++++++++++++---------
clang/lib/Sema/SemaTemplate.cpp | 53 ++--
clang/lib/Sema/SemaTemplateDeduction.cpp | 24 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 1 +
clang/lib/Sema/TreeTransform.h | 142 ++++++++---
clang/lib/Serialization/ASTReader.cpp | 9 +
clang/lib/Serialization/ASTReaderStmt.cpp | 3 +
clang/lib/Serialization/ASTWriterDecl.cpp | 1 +
clang/lib/Serialization/ASTWriterStmt.cpp | 11 +-
29 files changed, 578 insertions(+), 343 deletions(-)
diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h
index a2550716e3c7f..f6edb2d3449f6 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 6d86f87ba8aec..0ba75a308a0fc 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -265,7 +265,7 @@ class TemplateArgumentList final
/// 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 08e34fdf2aa2f..2ba787ac6df55 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 @@ class DeclRefExpr final
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 @@ class DeclRefExpr final
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 @@ class DeclRefExpr final
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 @@ class MemberExpr final
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 @@ class MemberExpr final
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 0455e1fa5016b..77e3100a69ace 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -957,6 +957,7 @@ class InitializationSequence {
bool HadMultipleCandidates;
FunctionDecl *Function;
DeclAccessPair FoundDecl;
+ const TemplateArgumentList *ConvertedArgs;
};
union {
@@ -1262,9 +1263,10 @@ class InitializationSequence {
///
/// \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 6e08762dcc6d7..4ec7163ac1f07 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 42a7bf75c3bfc..c68f31ccab528 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6856,7 +6856,8 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
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
@@ -10296,6 +10298,7 @@ class Sema final : public SemaBase {
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
@@ -10332,6 +10335,7 @@ class Sema final : public SemaBase {
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
@@ -10540,6 +10544,7 @@ class Sema final : public SemaBase {
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
@@ -10573,7 +10578,9 @@ class Sema final : public SemaBase {
/// 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);
@@ -10758,11 +10765,14 @@ class Sema final : public SemaBase {
/// 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
@@ -11542,7 +11552,8 @@ class Sema final : public SemaBase {
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 71f05e88fb539..645857ba8b4a3 100644
--- a/clang/include/clang/Sema/SemaCUDA.h
+++ b/clang/include/clang/Sema/SemaCUDA.h
@@ -229,8 +229,8 @@ class SemaCUDA : public SemaBase {
/// 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 1886937e10799..c9bb9525a09d7 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 572b77bc932ae..8381e11dc3796 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 9d5b4a60c9fe7..d33d6cdb120cb 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 c5f35b35ad357..058d8fa1328e3 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 3d3a111f0514a..599cbfdb7b5a5 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1864,7 +1864,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 0e5fc5e1a40b4..9217a8d4810b0 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 2824dfce1572c..0c961c2f89388 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 5a4fa97366809..db61af1495793 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 0b844b44930b9..88d5c66953b40 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 d70e42d86ef10..dc0215f44137f 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 78eba8e262771..9babbba8a7ec4 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 b0872122ed740..f6da4ec339adf 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 9814c3f456f0d..afd207d605f23 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 1802f8f4e1f91..10c26596e54c2 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2210,9 +2210,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();
@@ -5215,8 +5215,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();
}
@@ -5705,8 +5706,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();
}
@@ -6973,8 +6975,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");
@@ -6993,7 +6995,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;
}
@@ -7038,6 +7040,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
@@ -7609,7 +7612,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");
@@ -7641,6 +7645,7 @@ void Sema::AddMethodCandidate(
CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet;
Candidate.ExplicitCallArguments = Args.size();
Candidate.StrictPackMatch = StrictPackMatch;
+ Candidate.Deduced = Deduced;
bool IgnoreExplicitObject =
(Method->isExplicitObjectMemberFunction() &&
@@ -7850,7 +7855,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
@@ -7937,7 +7943,7 @@ void Sema::AddTemplateOverloadCandidate(
Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
PartialOverloading, AllowExplicit,
/*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO,
- Info.AggregateDeductionCandidateHasMismatchedArity,
+ Info.takeSugared(), Info.AggregateDeductionCandidateHasMismatchedArity,
Info.hasStrictPackMatch());
}
@@ -13011,7 +13017,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:
@@ -13029,15 +13038,22 @@ class AddressOfFunctionResolver {
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
@@ -13051,14 +13067,11 @@ class AddressOfFunctionResolver {
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, [...]
@@ -13101,15 +13114,17 @@ class AddressOfFunctionResolver {
// 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
@@ -13177,7 +13192,7 @@ class AddressOfFunctionResolver {
if (!S.checkAddressOfFunctionIsAvailable(Specialization))
return false;
- Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
+ Matches.push_back({CurAccessFunPair, Specialization, Info.takeSugared()});
return true;
}
@@ -13224,8 +13239,9 @@ class AddressOfFunctionResolver {
// 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;
}
@@ -13282,7 +13298,8 @@ class AddressOfFunctionResolver {
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.
@@ -13290,15 +13307,16 @@ class AddressOfFunctionResolver {
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;
@@ -13308,7 +13326,7 @@ class AddressOfFunctionResolver {
// [...] 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];
@@ -13322,21 +13340,26 @@ class AddressOfFunctionResolver {
// [...] 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]);
}
@@ -13416,22 +13439,26 @@ class AddressOfFunctionResolver {
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,
@@ -13453,6 +13480,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();
@@ -13575,7 +13603,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();
@@ -13587,8 +13616,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). ]
@@ -13596,12 +13627,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.
@@ -13659,6 +13686,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(
Matched = Specialization;
if (FoundResult) *FoundResult = I.getPair();
+ ConvertedArgs = Info.takeSugared();
}
if (Matched &&
@@ -13675,50 +13703,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;
+ }
+ }
}
}
@@ -14223,8 +14256,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(
@@ -14298,8 +14331,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(
@@ -15739,8 +15772,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();
@@ -16390,11 +16423,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())
@@ -16406,7 +16441,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(),
@@ -16423,8 +16458,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())
@@ -16465,8 +16500,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())
@@ -16500,7 +16535,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())
@@ -16534,7 +16569,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;
}
@@ -16556,7 +16591,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 {
@@ -16589,10 +16624,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 673551bd97f3e..81e37c7a9fe97 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5104,14 +5104,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.
@@ -5129,12 +5130,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;
}
@@ -5188,7 +5194,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();
}
}
@@ -5231,11 +5238,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.
@@ -5256,9 +5265,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;
}
@@ -5276,9 +5286,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();
@@ -5291,7 +5301,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,
@@ -8006,13 +8017,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();
@@ -8060,13 +8072,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();
@@ -11020,8 +11033,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 0faf9cb405b09..048c2dff1a563 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -4197,7 +4197,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))
@@ -4239,6 +4240,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:
@@ -4248,31 +4254,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
@@ -4289,10 +4293,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 c296d7e54b57b..22cc3785ae6cd 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 94e675383100e..f61c1ab329256 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -597,6 +597,9 @@ class TreeTransform {
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 @@ class TreeTransform {
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();
@@ -7369,6 +7417,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>;
@@ -12882,9 +12931,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 3c43c05f455cd..a515e4a0f8227 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9794,6 +9794,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 7c7abcb2d49d9..0e4819a48c11d 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 b896a04a0b14b..10f26a6045bb7 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 0860704368f3b..0128df1b3fc0f 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());
More information about the llvm-branch-commits
mailing list