mizvekov created this revision.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.
Herald added a reviewer: aaron.ballman.
Herald added a reviewer: NoQ.
Herald added a project: All.
mizvekov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
WIP - Not ready for review
Signed-off-by: Matheus Izvekov <[email protected]>
Depends on D134113 <https://reviews.llvm.org/D134113>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D134115
Files:
clang/include/clang/AST/ASTImporter.h
clang/include/clang/AST/Expr.h
clang/include/clang/Sema/Overload.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/Expr.cpp
clang/lib/Analysis/BodyFarm.cpp
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaExprMember.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -911,6 +911,10 @@
Record.push_back(E->hadMultipleCandidates());
Record.push_back(E->isNonOdrUse());
Record.AddSourceLocation(E->getOperatorLoc());
+ if (E->Deduced)
+ Record.AddTemplateArgumentList(E->Deduced);
+ else
+ Record.push_back(0);
if (HasFoundDecl) {
DeclAccessPair FoundDecl = E->getFoundDecl();
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1027,6 +1027,7 @@
E->MemberExprBits.HadMultipleCandidates = Record.readInt();
E->MemberExprBits.NonOdrUseReason = Record.readInt();
E->MemberExprBits.OperatorLoc = Record.readSourceLocation();
+ E->Deduced = Record.readTemplateArgumentList();
if (HasQualifier || HasFoundDecl) {
DeclAccessPair FoundDecl;
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -8847,6 +8847,15 @@
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();
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3740,6 +3740,11 @@
if (R.IsAddressOfOperand)
TDF |= TDF_IgnoreQualifiers;
+ // Gather the explicit template arguments, if any.
+ TemplateArgumentListInfo ExplicitTemplateArgs;
+ if (Ovl->hasExplicitTemplateArgs())
+ Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+
// C++0x [temp.deduct.call]p6:
// When P is a function type, pointer to function type, or pointer
// to member function type:
@@ -3749,8 +3754,9 @@
!ParamType->isMemberFunctionPointerType()) {
if (Ovl->hasExplicitTemplateArgs()) {
// But we can still look for an explicit specialization.
- if (FunctionDecl *ExplicitSpec
- = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+ if (FunctionDecl *ExplicitSpec =
+ S.ResolveSingleFunctionTemplateSpecialization(
+ Ovl, ExplicitTemplateArgs))
return GetTypeOfFunction(S, R, ExplicitSpec);
}
@@ -3762,10 +3768,6 @@
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) {
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -7475,7 +7475,7 @@
if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
return ExprError();
- Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn, nullptr);
ArgType = Arg->getType();
} else
return ExprError();
@@ -7527,7 +7527,7 @@
if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
return ExprError();
- Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn, nullptr);
ArgType = Arg->getType();
} else
return ExprError();
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6332,7 +6332,7 @@
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
- OverloadCandidateParamOrder PO) {
+ OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -6351,7 +6351,7 @@
AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
Expr::Classification::makeSimpleLValue(), Args,
CandidateSet, SuppressUserConversions,
- PartialOverloading, EarlyConversions, PO);
+ PartialOverloading, EarlyConversions, PO, Deduced);
return;
}
// We treat a constructor like a non-member function, since its object
@@ -6396,6 +6396,7 @@
Candidate.IsADLCandidate = IsADLCandidate;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
+ Candidate.Deduced = Deduced;
// Explicit functions are not actually candidates at all if we're not
// allowing them in this context, but keep them around so we can point
@@ -6930,16 +6931,13 @@
/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
/// allow user-defined conversions via constructors or conversion
/// operators.
-void
-Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, QualType ObjectType,
- Expr::Classification ObjectClassification,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- bool SuppressUserConversions,
- bool PartialOverloading,
- ConversionSequenceList EarlyConversions,
- OverloadCandidateParamOrder PO) {
+void Sema::AddMethodCandidate(
+ CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+ bool PartialOverloading, ConversionSequenceList EarlyConversions,
+ OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -6970,6 +6968,7 @@
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
+ Candidate.Deduced = Deduced;
unsigned NumParams = Proto->getNumParams();
@@ -7146,7 +7145,7 @@
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, ObjectClassification, Args,
CandidateSet, SuppressUserConversions, PartialOverloading,
- Conversions, PO);
+ Conversions, PO, Info.takeSugared());
}
/// Determine whether a given function template has a simple explicit specifier
@@ -7226,10 +7225,11 @@
// Add the function template specialization produced by template argument
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- AddOverloadCandidate(
- Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
- PartialOverloading, AllowExplicit,
- /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions, PO);
+ AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
+ SuppressUserConversions, PartialOverloading,
+ AllowExplicit,
+ /*AllowExplicitConversions*/ false, IsADLCandidate,
+ Conversions, PO, Info.takeSugared());
}
/// Check that implicit conversion sequences can be formed for each argument
@@ -12075,15 +12075,20 @@
FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) {
ExtractUnqualifiedFunctionTypeFromTargetType();
+ if (OvlExpr->hasExplicitTemplateArgs())
+ OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
+
if (TargetFunctionType->isFunctionType()) {
if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(OvlExpr))
if (!UME->isImplicitAccess() &&
- !S.ResolveSingleFunctionTemplateSpecialization(UME))
+ (!OvlExpr->hasExplicitTemplateArgs() ||
+ !S.ResolveSingleFunctionTemplateSpecialization(
+ UME, OvlExplicitTemplateArgs)))
StaticMemberFunctionFromBoundPointer = true;
} else if (OvlExpr->hasExplicitTemplateArgs()) {
DeclAccessPair dap;
if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization(
- OvlExpr, false, &dap)) {
+ OvlExpr, OvlExplicitTemplateArgs, /*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
@@ -12102,9 +12107,6 @@
return;
}
- if (OvlExpr->hasExplicitTemplateArgs())
- OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
-
if (FindAllFunctionsThatMatchTargetTypeExactly()) {
// C++ [over.over]p4:
// If more than one function is selected, [...]
@@ -12590,7 +12592,7 @@
// for both.
DiagnoseUseOfDecl(Found, E->getExprLoc());
CheckAddressOfMemberAccess(E, DAP);
- Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found);
+ Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found, nullptr);
if (DoFunctionPointerConversion && Fixed->getType()->isFunctionType())
SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false);
else
@@ -12608,10 +12610,9 @@
///
/// If no template-ids are found, no diagnostics are emitted and NULL is
/// returned.
-FunctionDecl *
-Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
- bool Complain,
- DeclAccessPair *FoundResult) {
+FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(
+ OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs,
+ bool Complain, DeclAccessPair *FoundResult) {
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
@@ -12619,12 +12620,9 @@
// [...] The overloaded function name can be preceded by the &
// operator.
- // If we didn't actually find any template-ids, we're done.
- if (!ovl->hasExplicitTemplateArgs())
- return nullptr;
+ // Specializations must have template args.
+ assert(ovl->hasExplicitTemplateArgs());
- TemplateArgumentListInfo ExplicitTemplateArgs;
- ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
// Look through all of the overloaded functions, searching for one
@@ -12699,50 +12697,53 @@
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);
+
+ DeclAccessPair found;
+ if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+ ovl.Expression, ExplicitTemplateArgs, /*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, nullptr);
+
+ // If desired, do function-to-pointer decay.
+ if (doFunctionPointerConversion) {
+ SingleFunctionExpression = DefaultFunctionArrayLvalueConversion(
+ SingleFunctionExpression.get());
+ if (SingleFunctionExpression.isInvalid()) {
+ SrcExpr = ExprError();
+ return true;
+ }
+ }
}
}
@@ -13255,7 +13256,8 @@
SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl);
if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()))
return ExprError();
- Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
+ Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl,
+ (*Best)->Deduced);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
ExecConfig, /*IsExecConfig=*/false,
(*Best)->IsADLCandidate);
@@ -13313,7 +13315,8 @@
// We emitted an error for the unavailable/deleted function call but keep
// the call in the AST.
FunctionDecl *FDecl = (*Best)->Function;
- Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
+ Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl,
+ (*Best)->Deduced);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
ExecConfig, /*IsExecConfig=*/false,
(*Best)->IsADLCandidate);
@@ -14581,7 +14584,8 @@
if (!Succeeded)
return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best));
- MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
+ MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method,
+ Best->Deduced);
// If overload resolution picked a static member, build a
// non-member call based on that function.
@@ -15196,11 +15200,13 @@
/// perhaps a '&' around it). We have resolved the overloaded function
/// to the function declaration Fn, so patch up the expression E to
/// refer (possibly indirectly) to Fn. Returns the new expr.
-Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
- FunctionDecl *Fn) {
+Expr *
+Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
+ FunctionDecl *Fn,
+ const TemplateArgumentList *Deduced) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
- Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
- Found, Fn);
+ Expr *SubExpr =
+ FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn, Deduced);
if (SubExpr == PE->getSubExpr())
return PE;
@@ -15208,8 +15214,8 @@
}
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
- Found, Fn);
+ Expr *SubExpr =
+ FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn, Deduced);
assert(Context.hasSameType(ICE->getSubExpr()->getType(),
SubExpr->getType()) &&
"Implicit cast type cannot be determined from overload");
@@ -15224,8 +15230,8 @@
if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) {
if (!GSE->isResultDependent()) {
- Expr *SubExpr =
- FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn);
+ Expr *SubExpr = FixOverloadedFunctionReference(GSE->getResultExpr(),
+ Found, Fn, Deduced);
if (SubExpr == GSE->getResultExpr())
return GSE;
@@ -15259,7 +15265,7 @@
// UnresolvedLookupExpr holding an overloaded member function
// or template.
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
- Found, Fn);
+ Found, Fn, Deduced);
if (SubExpr == UnOp->getSubExpr())
return UnOp;
@@ -15284,8 +15290,8 @@
UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
}
}
- Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
- Found, Fn);
+ Expr *SubExpr =
+ FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn, Deduced);
if (SubExpr == UnOp->getSubExpr())
return UnOp;
@@ -15370,10 +15376,11 @@
llvm_unreachable("Invalid reference to overloaded function");
}
-ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
- DeclAccessPair Found,
- FunctionDecl *Fn) {
- return FixOverloadedFunctionReference(E.get(), Found, Fn);
+ExprResult
+Sema::FixOverloadedFunctionReference(ExprResult E, DeclAccessPair Found,
+ FunctionDecl *Fn,
+ const TemplateArgumentList *Deduced) {
+ return FixOverloadedFunctionReference(E.get(), Found, Fn, Deduced);
}
bool clang::shouldEnforceArgLimit(bool PartialOverloading,
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -8261,9 +8261,8 @@
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, nullptr);
// We might get back another placeholder expression if we resolved to a
// builtin.
if (!CurInit.isInvalid())
Index: clang/lib/Sema/SemaExprMember.cpp
===================================================================
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -897,12 +897,13 @@
SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
QualType Ty, ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ const TemplateArgumentList *Deduced) {
NestedNameSpecifierLoc NNS =
SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member,
FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty,
- VK, OK, TemplateArgs);
+ VK, OK, TemplateArgs, Deduced);
}
MemberExpr *Sema::BuildMemberExpr(
@@ -910,13 +911,14 @@
SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
QualType Ty, ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ const TemplateArgumentList *Deduced) {
assert((!IsArrow || Base->isPRValue()) &&
"-> base must be a pointer prvalue");
- MemberExpr *E =
- MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,
- Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,
- VK, OK, getNonOdrUseReasonInCurrentContext(Member));
+ MemberExpr *E = MemberExpr::Create(
+ Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, FoundDecl,
+ MemberNameInfo, TemplateArgs, Deduced, Ty, VK, OK,
+ getNonOdrUseReasonInCurrentContext(Member));
E->setHadMultipleCandidates(HadMultipleCandidates);
MarkMemberReferenced(E);
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4250,7 +4250,7 @@
if (DiagnoseUseOfDecl(Fn, From->getBeginLoc()))
return ExprError();
- From = FixOverloadedFunctionReference(From, Found, Fn);
+ From = FixOverloadedFunctionReference(From, Found, Fn, nullptr);
// We might get back another placeholder expression if we resolved to a
// builtin.
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -9967,7 +9967,7 @@
DeclAccessPair DAP;
if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction(
RHS.get(), LHSType, /*Complain=*/false, DAP))
- RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD);
+ RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD, nullptr);
else
return Incompatible;
}
@@ -14258,14 +14258,18 @@
}
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);
+ if (ResolveSingleFunctionTemplateSpecialization(Ovl,
+ ExplicitTemplateArgs))
+ return Context.OverloadTy;
+ }
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp.get()->getSourceRange();
+ return QualType();
}
if (PTy->getKind() == BuiltinType::UnknownAny)
@@ -19183,8 +19187,8 @@
S.Context, Base.get(), ME->isArrow(), ME->getOperatorLoc(),
ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
- CopiedTemplateArgs(ME), ME->getType(), ME->getValueKind(),
- ME->getObjectKind(), ME->isNonOdrUse());
+ CopiedTemplateArgs(ME), ME->getDeduced(), ME->getType(),
+ ME->getValueKind(), ME->getObjectKind(), ME->isNonOdrUse());
}
if (ME->getMemberDecl()->isCXXInstanceMember())
@@ -19201,7 +19205,8 @@
S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(),
ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(),
ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME),
- ME->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR);
+ ME->getDeduced(), ME->getType(), ME->getValueKind(),
+ ME->getObjectKind(), NOUR);
}
case Expr::BinaryOperatorClass: {
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3599,9 +3599,13 @@
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;
+ ULE->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+ FD = S.ResolveSingleFunctionTemplateSpecialization(
+ ULE, ExplicitTemplateArgs, /*Complain=*/true);
+ }
NI = ULE->getNameInfo();
if (!FD) {
S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -1808,7 +1808,8 @@
return TC_Failed;
}
- SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
+ SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn,
+ nullptr);
if (!SrcExpr.isUsable()) {
msg = 0;
return TC_Failed;
@@ -2885,7 +2886,8 @@
DeclAccessPair DAP;
if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction(
SrcExpr.get(), DestType, /*Complain=*/true, DAP))
- SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD);
+ SrcExpr =
+ Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD, nullptr);
else
return;
assert(SrcExpr.isUsable());
Index: clang/lib/Analysis/BodyFarm.cpp
===================================================================
--- clang/lib/Analysis/BodyFarm.cpp
+++ clang/lib/Analysis/BodyFarm.cpp
@@ -230,8 +230,8 @@
C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
SourceLocation(), MemberDecl, FoundDecl,
DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
- /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
- OK_Ordinary, NOUR_None);
+ /* TemplateArgumentListInfo=*/nullptr, /*Deduced=*/nullptr,
+ MemberDecl->getType(), ValueKind, OK_Ordinary, NOUR_None);
}
ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -1612,11 +1612,13 @@
MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
ValueDecl *MemberDecl,
- const DeclarationNameInfo &NameInfo, QualType T,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentList *Deduced, QualType T,
ExprValueKind VK, ExprObjectKind OK,
NonOdrUseReason NOUR)
: Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl),
- MemberDNLoc(NameInfo.getInfo()), MemberLoc(NameInfo.getLoc()) {
+ Deduced(Deduced), MemberDNLoc(NameInfo.getInfo()),
+ MemberLoc(NameInfo.getLoc()) {
assert(!NameInfo.getName() ||
MemberDecl->getDeclName() == NameInfo.getName());
MemberExprBits.IsArrow = IsArrow;
@@ -1633,7 +1635,8 @@
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs,
- QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) {
+ const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
+ ExprObjectKind OK, NonOdrUseReason NOUR) {
bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl ||
FoundDecl.getAccess() != MemberDecl->getAccess();
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
@@ -1645,7 +1648,7 @@
void *Mem = C.Allocate(Size, alignof(MemberExpr));
MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
- NameInfo, T, VK, OK, NOUR);
+ NameInfo, Deduced, T, VK, OK, NOUR);
// FIXME: remove remaining dependence computation to computeDependence().
auto Deps = E->getDependence();
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -7951,6 +7951,7 @@
auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
auto ToMemberDecl = importChecked(Err, E->getMemberDecl());
+ auto ToDeduced = importChecked(Err, E->getDeduced());
auto ToType = importChecked(Err, E->getType());
auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl());
auto ToName = importChecked(Err, E->getMemberNameInfo().getName());
@@ -7975,7 +7976,7 @@
return MemberExpr::Create(Importer.getToContext(), ToBase, E->isArrow(),
ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
ToMemberDecl, ToFoundDecl, ToMemberNameInfo,
- ResInfo, ToType, E->getValueKind(),
+ ResInfo, ToDeduced, ToType, E->getValueKind(),
E->getObjectKind(), E->isNonOdrUse());
}
@@ -9655,6 +9656,17 @@
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)
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3882,7 +3882,8 @@
bool AllowExplicitConversion = false,
ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
ConversionSequenceList EarlyConversions = None,
- OverloadCandidateParamOrder PO = {});
+ OverloadCandidateParamOrder PO = {},
+ const TemplateArgumentList *Deduced = nullptr);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
@@ -3897,16 +3898,16 @@
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false,
OverloadCandidateParamOrder PO = {});
- void AddMethodCandidate(CXXMethodDecl *Method,
- DeclAccessPair FoundDecl,
+ void AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false,
ConversionSequenceList EarlyConversions = None,
- OverloadCandidateParamOrder PO = {});
+ OverloadCandidateParamOrder PO = {},
+ const TemplateArgumentList *Deduced = nullptr);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
@@ -4042,10 +4043,9 @@
bool resolveAndFixAddressOfSingleOverloadCandidate(
ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
- FunctionDecl *
- ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
- bool Complain = false,
- DeclAccessPair *Found = nullptr);
+ FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
+ OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs,
+ bool Complain = false, DeclAccessPair *Found = nullptr);
bool ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
@@ -4053,12 +4053,13 @@
QualType DestTypeForComplaining = QualType(),
unsigned DiagIDForComplaining = 0);
- Expr *FixOverloadedFunctionReference(Expr *E,
- DeclAccessPair FoundDecl,
- FunctionDecl *Fn);
- ExprResult FixOverloadedFunctionReference(ExprResult,
- DeclAccessPair FoundDecl,
- FunctionDecl *Fn);
+ Expr *FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
+ FunctionDecl *Fn,
+ const TemplateArgumentList *Deduced);
+ ExprResult
+ FixOverloadedFunctionReference(ExprResult, DeclAccessPair FoundDecl,
+ FunctionDecl *Fn,
+ const TemplateArgumentList *Deduced);
void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
ArrayRef<Expr *> Args,
@@ -5703,22 +5704,20 @@
UnqualifiedId &Member,
Decl *ObjCImpDecl);
- MemberExpr *
- BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
- const CXXScopeSpec *SS, SourceLocation TemplateKWLoc,
- ValueDecl *Member, DeclAccessPair FoundDecl,
- bool HadMultipleCandidates,
- const DeclarationNameInfo &MemberNameInfo, QualType Ty,
- ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = nullptr);
- MemberExpr *
- BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
- NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
- ValueDecl *Member, DeclAccessPair FoundDecl,
- bool HadMultipleCandidates,
- const DeclarationNameInfo &MemberNameInfo, QualType Ty,
- ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = nullptr);
+ MemberExpr *BuildMemberExpr(
+ Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
+ SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
+ bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
+ QualType Ty, ExprValueKind VK, ExprObjectKind OK,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr,
+ const TemplateArgumentList *Deduced = nullptr);
+ MemberExpr *BuildMemberExpr(
+ Expr *Base, bool IsArrow, SourceLocation OpLoc,
+ NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK,
+ ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr,
+ const TemplateArgumentList *Deduced = nullptr);
void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
Index: clang/include/clang/Sema/Overload.h
===================================================================
--- clang/include/clang/Sema/Overload.h
+++ clang/include/clang/Sema/Overload.h
@@ -885,6 +885,9 @@
StandardConversionSequence FinalConversion;
};
+ /// Deduced Arguments for Function Templates.
+ const TemplateArgumentList *Deduced;
+
/// Get RewriteKind value in OverloadCandidateRewriteKind type (This
/// function is to workaround the spurious GCC bitfield enum warning)
OverloadCandidateRewriteKind getRewriteKind() const {
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -3175,6 +3175,8 @@
/// In X.F, this is the decl referenced by F.
ValueDecl *MemberDecl;
+ const TemplateArgumentList *Deduced;
+
/// MemberDNLoc - Provides source/type location info for the
/// declaration name embedded in MemberDecl.
DeclarationNameLoc MemberDNLoc;
@@ -3200,21 +3202,20 @@
MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
- QualType T, ExprValueKind VK, ExprObjectKind OK,
- NonOdrUseReason NOUR);
+ const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
+ ExprObjectKind OK, NonOdrUseReason NOUR);
MemberExpr(EmptyShell Empty)
: Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
public:
- static MemberExpr *Create(const ASTContext &C, Expr *Base, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
- DeclAccessPair FoundDecl,
- DeclarationNameInfo MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs,
- QualType T, ExprValueKind VK, ExprObjectKind OK,
- NonOdrUseReason NOUR);
+ static MemberExpr *
+ Create(const ASTContext &C, Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
+ DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
+ ExprObjectKind OK, NonOdrUseReason NOUR);
/// Create an implicit MemberExpr, with no location, qualifier, template
/// arguments, and so on. Suitable only for non-static member access.
@@ -3225,7 +3226,8 @@
return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
SourceLocation(), MemberDecl,
DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()),
- DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None);
+ DeclarationNameInfo(), nullptr, nullptr, T, VK, OK,
+ NOUR_None);
}
static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
@@ -3251,6 +3253,8 @@
return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
}
+ const TemplateArgumentList *getDeduced() const { return Deduced; }
+
/// Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
Index: clang/include/clang/AST/ASTImporter.h
===================================================================
--- clang/include/clang/AST/ASTImporter.h
+++ clang/include/clang/AST/ASTImporter.h
@@ -480,6 +480,13 @@
/// 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);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits