[llvm-branch-commits] [clang] 6170581 - Revert "[Clang] Bypass TAD during overload resolution if a perfect match exis…"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Apr 17 02:00:27 PDT 2025
Author: cor3ntin
Date: 2025-04-17T11:00:23+02:00
New Revision: 61705818e19b6a2e35a4a65f1104d26ce0c1929a
URL: https://github.com/llvm/llvm-project/commit/61705818e19b6a2e35a4a65f1104d26ce0c1929a
DIFF: https://github.com/llvm/llvm-project/commit/61705818e19b6a2e35a4a65f1104d26ce0c1929a.diff
LOG: Revert "[Clang] Bypass TAD during overload resolution if a perfect match exis…"
This reverts commit 377ec36b323ea99ca316cb5cf79c0a0c93eebc37.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Sema/Overload.h
clang/lib/Sema/SemaCodeComplete.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
clang/test/SemaCUDA/function-overload.cu
clang/test/SemaCXX/implicit-member-functions.cpp
clang/test/SemaTemplate/instantiate-function-params.cpp
clang/test/Templight/templight-empty-entries-fix.cpp
Removed:
clang/test/SemaCXX/overload-resolution-deferred-templates.cpp
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fc36962b317e8..4f640697e1817 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -96,12 +96,6 @@ C++ Language Changes
asm((std::string_view("nop")) ::: (std::string_view("memory")));
}
-- Clang now implements the changes to overload resolution proposed by section 1 and 2 of
- `P3606 <https://wg21.link/P3606R0>`_. If a non-template candidate exists in an overload set that is
- a perfect match (all conversion sequences are identity conversions) template candidates are not instantiated.
- Diagnostics that would have resulted from the instantiation of these template candidates are no longer
- produced. This aligns Clang closer to the behavior of GCC, and fixes (#GH62096), (#GH74581), and (#GH74581).
-
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index e667147bfac7e..6e08762dcc6d7 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -407,26 +407,6 @@ class Sema;
Third == ICK_Identity;
}
- /// A conversion sequence is perfect if it is an identity conversion and
- /// the type of the source is the same as the type of the target.
- bool isPerfect(const ASTContext &C) const {
- if (!isIdentityConversion())
- return false;
- // If we are not performing a reference binding, we can skip comparing
- // the types, which has a noticeable performance impact.
- if (!ReferenceBinding) {
- // The types might
diff er if there is an array-to-pointer conversion
- // or lvalue-to-rvalue conversion.
- assert(First || C.hasSameUnqualifiedType(getFromType(), getToType(2)));
- return true;
- }
- if (!C.hasSameType(getFromType(), getToType(2)))
- return false;
- if (BindsToRvalue && IsLvalueReference)
- return false;
- return true;
- }
-
ImplicitConversionRank getRank() const;
NarrowingKind
getNarrowingKind(ASTContext &Context, const Expr *Converted,
@@ -763,12 +743,6 @@ class Sema;
Standard.setAllToTypes(T);
}
- /// A conversion sequence is perfect if it is an identity conversion and
- /// the type of the source is the same as the type of the target.
- bool isPerfect(const ASTContext &C) const {
- return isStandard() && Standard.isPerfect(C);
- }
-
// True iff this is a conversion sequence from an initializer list to an
// array or std::initializer.
bool hasInitializerListContainerType() const {
@@ -965,10 +939,6 @@ class Sema;
LLVM_PREFERRED_TYPE(CallExpr::ADLCallKind)
unsigned IsADLCandidate : 1;
- /// Whether FinalConversion has been set.
- LLVM_PREFERRED_TYPE(bool)
- unsigned HasFinalConversion : 1;
-
/// Whether this is a rewritten candidate, and if so, of what kind?
LLVM_PREFERRED_TYPE(OverloadCandidateRewriteKind)
unsigned RewriteKind : 2;
@@ -1009,20 +979,6 @@ class Sema;
return false;
}
- // An overload is a perfect match if the conversion
- // sequences for each argument are perfect.
- bool isPerfectMatch(const ASTContext &Ctx) const {
- if (!Viable)
- return false;
- for (const auto &C : Conversions) {
- if (!C.isInitialized() || !C.isPerfect(Ctx))
- return false;
- }
- if (HasFinalConversion)
- return FinalConversion.isPerfect(Ctx);
- return true;
- }
-
bool TryToFixBadConversion(unsigned Idx, Sema &S) {
bool CanFix = Fix.tryToFixConversion(
Conversions[Idx].Bad.FromExpr,
@@ -1056,67 +1012,8 @@ class Sema;
: IsSurrogate(false), IgnoreObjectArgument(false),
TookAddressOfOverload(false), StrictPackMatch(false),
IsADLCandidate(llvm::to_underlying(CallExpr::NotADL)),
- HasFinalConversion(false), RewriteKind(CRK_None) {}
- };
-
- struct DeferredTemplateOverloadCandidate {
-
- // intrusive linked list support for allocateDeferredCandidate
- DeferredTemplateOverloadCandidate *Next = nullptr;
-
- enum Kind { Function, Method, Conversion };
-
- LLVM_PREFERRED_TYPE(Kind)
- unsigned Kind : 2;
- LLVM_PREFERRED_TYPE(bool)
- unsigned AllowObjCConversionOnExplicit : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned AllowResultConversion : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned AllowExplicit : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned SuppressUserConversions : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned PartialOverloading : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned AggregateCandidateDeduction : 1;
- };
-
- struct DeferredFunctionTemplateOverloadCandidate
- : public DeferredTemplateOverloadCandidate {
- FunctionTemplateDecl *FunctionTemplate;
- DeclAccessPair FoundDecl;
- ArrayRef<Expr *> Args;
- CallExpr::ADLCallKind IsADLCandidate;
- OverloadCandidateParamOrder PO;
- };
- static_assert(std::is_trivially_destructible_v<
- DeferredFunctionTemplateOverloadCandidate>);
-
- struct DeferredMethodTemplateOverloadCandidate
- : public DeferredTemplateOverloadCandidate {
- FunctionTemplateDecl *FunctionTemplate;
- DeclAccessPair FoundDecl;
- ArrayRef<Expr *> Args;
- CXXRecordDecl *ActingContext;
- Expr::Classification ObjectClassification;
- QualType ObjectType;
- OverloadCandidateParamOrder PO;
+ RewriteKind(CRK_None) {}
};
- static_assert(std::is_trivially_destructible_v<
- DeferredMethodTemplateOverloadCandidate>);
-
- struct DeferredConversionTemplateOverloadCandidate
- : public DeferredTemplateOverloadCandidate {
- FunctionTemplateDecl *FunctionTemplate;
- DeclAccessPair FoundDecl;
- CXXRecordDecl *ActingContext;
- Expr *From;
- QualType ToType;
- };
-
- static_assert(std::is_trivially_destructible_v<
- DeferredConversionTemplateOverloadCandidate>);
/// OverloadCandidateSet - A set of overload candidates, used in C++
/// overload resolution (C++ 13.3).
@@ -1146,11 +1043,6 @@ class Sema;
/// C++ [over.match.call.general]
/// Resolve a call through the address of an overload set.
CSK_AddressOfOverloadSet,
-
- /// When doing overload resolution during code completion,
- /// we want to show all viable candidates, including otherwise
- /// deferred template candidates.
- CSK_CodeCompletion,
};
/// Information about operator rewrites to consider when adding operator
@@ -1225,15 +1117,7 @@ class Sema;
SmallVector<OverloadCandidate, 16> Candidates;
llvm::SmallPtrSet<uintptr_t, 16> Functions;
- DeferredTemplateOverloadCandidate *FirstDeferredCandidate = nullptr;
- unsigned DeferredCandidatesCount : 8 * sizeof(unsigned) - 2;
- LLVM_PREFERRED_TYPE(bool)
- unsigned HasDeferredTemplateConstructors : 1;
- LLVM_PREFERRED_TYPE(bool)
- unsigned ResolutionByPerfectCandidateIsDisabled : 1;
-
- // Allocator for ConversionSequenceLists and deferred candidate args.
- // We store the first few of these
+ // Allocator for ConversionSequenceLists. We store the first few of these
// inline to avoid allocation for small sets.
llvm::BumpPtrAllocator SlabAllocator;
@@ -1241,11 +1125,8 @@ class Sema;
CandidateSetKind Kind;
OperatorRewriteInfo RewriteInfo;
- /// Small storage size for ImplicitConversionSequences
- /// and the persisted arguments of deferred candidates.
constexpr static unsigned NumInlineBytes =
- 32 * sizeof(ImplicitConversionSequence);
-
+ 24 * sizeof(ImplicitConversionSequence);
unsigned NumInlineBytesUsed = 0;
alignas(void *) char InlineSpace[NumInlineBytes];
@@ -1256,13 +1137,15 @@ class Sema;
/// from the slab allocator.
/// FIXME: It would probably be nice to have a SmallBumpPtrAllocator
/// instead.
+ /// FIXME: Now that this only allocates ImplicitConversionSequences, do we
+ /// want to un-generalize this?
template <typename T>
T *slabAllocate(unsigned N) {
// It's simpler if this doesn't need to consider alignment.
static_assert(alignof(T) == alignof(void *),
"Only works for pointer-aligned types.");
- static_assert(std::is_trivially_destructible_v<T> ||
- (std::is_same_v<ImplicitConversionSequence, T>),
+ static_assert(std::is_trivial<T>::value ||
+ std::is_same<ImplicitConversionSequence, T>::value,
"Add destruction logic to OverloadCandidateSet::clear().");
unsigned NBytes = sizeof(T) * N;
@@ -1276,34 +1159,12 @@ class Sema;
return reinterpret_cast<T *>(FreeSpaceStart);
}
- // Because the size of OverloadCandidateSet has a noticeable impact on
- // performance, we store each deferred template candidate in the slab
- // allocator such that deferred candidates are ultimately a singly-linked
- // intrusive linked list. This ends up being much more efficient than a
- // SmallVector that is empty in the common case.
- template <typename T> T *allocateDeferredCandidate() {
- T *C = slabAllocate<T>(1);
- if (!FirstDeferredCandidate)
- FirstDeferredCandidate = C;
- else {
- auto *F = FirstDeferredCandidate;
- while (F->Next)
- F = F->Next;
- F->Next = C;
- }
- DeferredCandidatesCount++;
- return C;
- }
-
void destroyCandidates();
public:
OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
OperatorRewriteInfo RewriteInfo = {})
- : FirstDeferredCandidate(nullptr), DeferredCandidatesCount(0),
- HasDeferredTemplateConstructors(false),
- ResolutionByPerfectCandidateIsDisabled(false), Loc(Loc), Kind(CSK),
- RewriteInfo(RewriteInfo) {}
+ : Loc(Loc), Kind(CSK), RewriteInfo(RewriteInfo) {}
OverloadCandidateSet(const OverloadCandidateSet &) = delete;
OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
~OverloadCandidateSet() { destroyCandidates(); }
@@ -1315,9 +1176,6 @@ class Sema;
/// Whether diagnostics should be deferred.
bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc);
- // Whether the resolution of template candidates should be deferred
- bool shouldDeferTemplateArgumentDeduction(const LangOptions &Opts) const;
-
/// Determine when this overload candidate will be new to the
/// overload set.
bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO =
@@ -1341,10 +1199,8 @@ class Sema;
iterator begin() { return Candidates.begin(); }
iterator end() { return Candidates.end(); }
- size_t size() const { return Candidates.size() + DeferredCandidatesCount; }
- bool empty() const {
- return Candidates.empty() && DeferredCandidatesCount == 0;
- }
+ size_t size() const { return Candidates.size(); }
+ bool empty() const { return Candidates.empty(); }
/// Allocate storage for conversion sequences for NumConversions
/// conversions.
@@ -1360,24 +1216,6 @@ class Sema;
return ConversionSequenceList(Conversions, NumConversions);
}
- /// Provide storage for any Expr* arg that must be preserved
- /// until deferred template candidates are deduced.
- /// Typically this should be used for reversed operator arguments
- /// and any time the argument array is transformed while adding
- /// a template candidate.
- llvm::MutableArrayRef<Expr *> getPersistentArgsArray(unsigned N) {
- Expr **Exprs = slabAllocate<Expr *>(N);
- return llvm::MutableArrayRef<Expr *>(Exprs, N);
- }
-
- template <typename... T>
- llvm::MutableArrayRef<Expr *> getPersistentArgsArray(T *...Exprs) {
- llvm::MutableArrayRef<Expr *> Arr =
- getPersistentArgsArray(sizeof...(Exprs));
- llvm::copy(std::initializer_list<Expr *>{Exprs...}, Arr.data());
- return Arr;
- }
-
/// Add a new candidate with NumConversions conversion sequence slots
/// to the overload set.
OverloadCandidate &addCandidate(unsigned NumConversions = 0,
@@ -1393,32 +1231,6 @@ class Sema;
return C;
}
- void AddDeferredTemplateCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- ArrayRef<Expr *> Args, bool SuppressUserConversions,
- bool PartialOverloading, bool AllowExplicit,
- CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO,
- bool AggregateCandidateDeduction);
-
- void AddDeferredMethodTemplateCandidate(
- FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, QualType ObjectType,
- Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
- bool SuppressUserConversions, bool PartialOverloading,
- OverloadCandidateParamOrder PO);
-
- void AddDeferredConversionTemplateCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
- bool AllowObjCConversionOnExplicit, bool AllowExplicit,
- bool AllowResultConversion);
-
- void InjectNonDeducedTemplateCandidates(Sema &S);
-
- void DisableResolutionByPerfectCandidate() {
- ResolutionByPerfectCandidateIsDisabled = true;
- }
-
/// Find the best viable function on this overload set, if it exists.
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
OverloadCandidateSet::iterator& Best);
@@ -1451,15 +1263,6 @@ class Sema;
DestAS = AS;
}
- private:
- OverloadingResult ResultForBestCandidate(const iterator &Best);
- void CudaExcludeWrongSideCandidates(
- Sema &S, SmallVectorImpl<OverloadCandidate *> &Candidates);
- OverloadingResult
- BestViableFunctionImpl(Sema &S, SourceLocation Loc,
- OverloadCandidateSet::iterator &Best);
- void PerfectViableFunction(Sema &S, SourceLocation Loc,
- OverloadCandidateSet::iterator &Best);
};
bool isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
@@ -1508,21 +1311,6 @@ class Sema;
// parameter.
bool shouldEnforceArgLimit(bool PartialOverloading, FunctionDecl *Function);
- inline bool OverloadCandidateSet::shouldDeferTemplateArgumentDeduction(
- const LangOptions &Opts) const {
- return
- // For user defined conversion we need to check against
diff erent
- // combination of CV qualifiers and look at any explicit specifier, so
- // always deduce template candidates.
- Kind != CSK_InitByUserDefinedConversion
- // When doing code completion, we want to see all the
- // viable candidates.
- && Kind != CSK_CodeCompletion
- // CUDA may prefer template candidates even when a non-candidate
- // is a perfect match
- && !Opts.CUDA;
- }
-
} // namespace clang
#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 45405d4709e14..f6ec4cb0f069e 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6354,8 +6354,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
Expr *NakedFn = Fn->IgnoreParenCasts();
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
- OverloadCandidateSet CandidateSet(Loc,
- OverloadCandidateSet::CSK_CodeCompletion);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {
SemaRef.AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes,
@@ -6558,8 +6557,7 @@ QualType SemaCodeCompletion::ProduceConstructorSignatureHelp(
// FIXME: Provide support for variadic template constructors.
if (CRD) {
- OverloadCandidateSet CandidateSet(Loc,
- OverloadCandidateSet::CSK_CodeCompletion);
+ OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
for (NamedDecl *C : SemaRef.LookupConstructors(CRD)) {
if (auto *FD = dyn_cast<FunctionDecl>(C)) {
// FIXME: we can't yet provide correct signature help for initializer
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 9e802a175bb05..77d7f821f2011 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5231,7 +5231,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
// Add the final conversion sequence, if necessary.
if (NewRefRelationship == Sema::Ref_Incompatible) {
- assert(Best->HasFinalConversion && !isa<CXXConstructorDecl>(Function) &&
+ assert(!isa<CXXConstructorDecl>(Function) &&
"should not have conversion after constructor");
ImplicitConversionSequence ICS;
@@ -6200,7 +6200,6 @@ static void TryUserDefinedConversion(Sema &S,
// If the conversion following the call to the conversion function
// is interesting, add it as a separate step.
- assert(Best->HasFinalConversion);
if (Best->FinalConversion.First || Best->FinalConversion.Second ||
Best->FinalConversion.Third) {
ImplicitConversionSequence ICS;
@@ -10030,19 +10029,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
// When [...] the constructor [...] is a candidate by
// - [over.match.copy] (in all cases)
if (TD) {
-
- // As template candidates are not deduced immediately,
- // persist the array in the overload set.
- MutableArrayRef<Expr *> TmpInits =
- Candidates.getPersistentArgsArray(Inits.size());
-
- for (auto [I, E] : llvm::enumerate(Inits)) {
+ SmallVector<Expr *, 8> TmpInits;
+ for (Expr *E : Inits)
if (auto *DI = dyn_cast<DesignatedInitExpr>(E))
- TmpInits[I] = DI->getInit();
+ TmpInits.push_back(DI->getInit());
else
- TmpInits[I] = E;
- }
-
+ TmpInits.push_back(E);
AddTemplateOverloadCandidate(
TD, FoundDecl, /*ExplicitArgs=*/nullptr, TmpInits, Candidates,
/*SuppressUserConversions=*/false,
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index b7a981e08ead9..55634aa75ae25 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1123,10 +1123,6 @@ void OverloadCandidateSet::clear(CandidateSetKind CSK) {
Candidates.clear();
Functions.clear();
Kind = CSK;
- FirstDeferredCandidate = nullptr;
- DeferredCandidatesCount = 0;
- HasDeferredTemplateConstructors = false;
- ResolutionByPerfectCandidateIsDisabled = false;
}
namespace {
@@ -4079,9 +4075,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
}
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
-
- assert(Best->HasFinalConversion);
-
// C++ [over.ics.user]p1:
//
// [...] If the user-defined conversion is specified by a
@@ -5165,9 +5158,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
case OR_Success:
-
- assert(Best->HasFinalConversion);
-
// C++ [over.ics.ref]p1:
//
// [...] If the parameter binds directly to the result of
@@ -7805,14 +7795,15 @@ void Sema::AddMethodCandidate(
}
}
-static void AddMethodTemplateCandidateImmediately(
- Sema &S, OverloadCandidateSet &CandidateSet,
+void Sema::AddMethodTemplateCandidate(
FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType,
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
- bool SuppressUserConversions, bool PartialOverloading,
- OverloadCandidateParamOrder PO) {
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+ bool PartialOverloading, OverloadCandidateParamOrder PO) {
+ if (!CandidateSet.isNewCandidate(MethodTmpl, PO))
+ return;
// C++ [over.match.funcs]p7:
// In each case where a candidate is a function template, candidate
@@ -7826,12 +7817,12 @@ static void AddMethodTemplateCandidateImmediately(
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = nullptr;
ConversionSequenceList Conversions;
- if (TemplateDeductionResult Result = S.DeduceTemplateArguments(
+ if (TemplateDeductionResult Result = DeduceTemplateArguments(
MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, /*AggregateDeductionCandidate=*/false,
/*PartialOrdering=*/false, ObjectType, ObjectClassification,
[&](ArrayRef<QualType> ParamTypes) {
- return S.CheckNonDependentConversions(
+ return CheckNonDependentConversions(
MethodTmpl, ParamTypes, Args, CandidateSet, Conversions,
SuppressUserConversions, ActingContext, ObjectType,
ObjectClassification, PO);
@@ -7853,8 +7844,8 @@ static void AddMethodTemplateCandidateImmediately(
Candidate.FailureKind = ovl_fail_bad_conversion;
else {
Candidate.FailureKind = ovl_fail_bad_deduction;
- Candidate.DeductionFailure =
- MakeDeductionFailureInfo(S.Context, Result, Info);
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
}
return;
}
@@ -7864,34 +7855,10 @@ static void AddMethodTemplateCandidateImmediately(
assert(Specialization && "Missing member function template specialization?");
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
- S.AddMethodCandidate(
- cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType,
- ObjectClassification, Args, CandidateSet, SuppressUserConversions,
- PartialOverloading, Conversions, PO, Info.hasStrictPackMatch());
-}
-
-void Sema::AddMethodTemplateCandidate(
- FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext,
- TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType,
- Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
- bool PartialOverloading, OverloadCandidateParamOrder PO) {
- if (!CandidateSet.isNewCandidate(MethodTmpl, PO))
- return;
-
- if (ExplicitTemplateArgs ||
- !CandidateSet.shouldDeferTemplateArgumentDeduction(getLangOpts())) {
- AddMethodTemplateCandidateImmediately(
- *this, CandidateSet, MethodTmpl, FoundDecl, ActingContext,
- ExplicitTemplateArgs, ObjectType, ObjectClassification, Args,
- SuppressUserConversions, PartialOverloading, PO);
- return;
- }
-
- CandidateSet.AddDeferredMethodTemplateCandidate(
- MethodTmpl, FoundDecl, ActingContext, ObjectType, ObjectClassification,
- Args, SuppressUserConversions, PartialOverloading, PO);
+ AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
+ ActingContext, ObjectType, ObjectClassification, Args,
+ CandidateSet, SuppressUserConversions, PartialOverloading,
+ Conversions, PO, Info.hasStrictPackMatch());
}
/// Determine whether a given function template has a simple explicit specifier
@@ -7900,18 +7867,14 @@ static bool isNonDependentlyExplicit(FunctionTemplateDecl *FTD) {
return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).isExplicit();
}
-static bool hasDependentExplicit(FunctionTemplateDecl *FTD) {
- return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).getKind() ==
- ExplicitSpecKind::Unresolved;
-}
-
-static void AddTemplateOverloadCandidateImmediately(
- Sema &S, OverloadCandidateSet &CandidateSet,
+void Sema::AddTemplateOverloadCandidate(
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
- bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit,
- Sema::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO,
- bool AggregateCandidateDeduction) {
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+ bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate,
+ OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
+ if (!CandidateSet.isNewCandidate(FunctionTemplate, PO))
+ return;
// If the function template has a non-dependent explicit specification,
// exclude it now if appropriate; we are not permitted to perform deduction
@@ -7938,14 +7901,14 @@ static void AddTemplateOverloadCandidateImmediately(
FunctionTemplate->getTemplateDepth());
FunctionDecl *Specialization = nullptr;
ConversionSequenceList Conversions;
- if (TemplateDeductionResult Result = S.DeduceTemplateArguments(
+ if (TemplateDeductionResult Result = DeduceTemplateArguments(
FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, AggregateCandidateDeduction,
/*PartialOrdering=*/false,
/*ObjectType=*/QualType(),
/*ObjectClassification=*/Expr::Classification(),
[&](ArrayRef<QualType> ParamTypes) {
- return S.CheckNonDependentConversions(
+ return CheckNonDependentConversions(
FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions,
SuppressUserConversions, nullptr, QualType(), {}, PO);
});
@@ -7969,8 +7932,8 @@ static void AddTemplateOverloadCandidateImmediately(
Candidate.FailureKind = ovl_fail_bad_conversion;
else {
Candidate.FailureKind = ovl_fail_bad_deduction;
- Candidate.DeductionFailure =
- MakeDeductionFailureInfo(S.Context, Result, Info);
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
}
return;
}
@@ -7978,7 +7941,7 @@ static void AddTemplateOverloadCandidateImmediately(
// Add the function template specialization produced by template argument
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- S.AddOverloadCandidate(
+ AddOverloadCandidate(
Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
PartialOverloading, AllowExplicit,
/*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO,
@@ -7986,38 +7949,6 @@ static void AddTemplateOverloadCandidateImmediately(
Info.hasStrictPackMatch());
}
-void Sema::AddTemplateOverloadCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
- bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate,
- OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
- if (!CandidateSet.isNewCandidate(FunctionTemplate, PO))
- return;
-
- bool DependentExplicitSpecifier = hasDependentExplicit(FunctionTemplate);
-
- if (ExplicitTemplateArgs ||
- !CandidateSet.shouldDeferTemplateArgumentDeduction(getLangOpts()) ||
- (isa<CXXConstructorDecl>(FunctionTemplate->getTemplatedDecl()) &&
- DependentExplicitSpecifier)) {
-
- AddTemplateOverloadCandidateImmediately(
- *this, CandidateSet, FunctionTemplate, FoundDecl, ExplicitTemplateArgs,
- Args, SuppressUserConversions, PartialOverloading, AllowExplicit,
- IsADLCandidate, PO, AggregateCandidateDeduction);
-
- if (DependentExplicitSpecifier)
- CandidateSet.DisableResolutionByPerfectCandidate();
- return;
- }
-
- CandidateSet.AddDeferredTemplateCandidate(
- FunctionTemplate, FoundDecl, Args, SuppressUserConversions,
- PartialOverloading, AllowExplicit, IsADLCandidate, PO,
- AggregateCandidateDeduction);
-}
-
bool Sema::CheckNonDependentConversions(
FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes,
ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet,
@@ -8180,7 +8111,6 @@ void Sema::AddConversionCandidate(
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(ConvType);
Candidate.FinalConversion.setAllToTypes(ToType);
- Candidate.HasFinalConversion = true;
Candidate.Viable = true;
Candidate.ExplicitCallArguments = 1;
Candidate.StrictPackMatch = StrictPackMatch;
@@ -8285,7 +8215,6 @@ void Sema::AddConversionCandidate(
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
Candidate.FinalConversion = ICS.Standard;
- Candidate.HasFinalConversion = true;
// C++ [over.ics.user]p3:
// If the user-defined conversion is specified by a specialization of a
@@ -8335,12 +8264,16 @@ void Sema::AddConversionCandidate(
}
}
-static void AddTemplateConversionCandidateImmediately(
- Sema &S, OverloadCandidateSet &CandidateSet,
+void Sema::AddTemplateConversionCandidate(
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
- bool AllowObjCConversionOnExplicit, bool AllowExplicit,
- bool AllowResultConversion) {
+ CXXRecordDecl *ActingDC, Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
+ bool AllowExplicit, bool AllowResultConversion) {
+ assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
+ "Only conversion function templates permitted here");
+
+ if (!CandidateSet.isNewCandidate(FunctionTemplate))
+ return;
// If the function template has a non-dependent explicit specification,
// exclude it now if appropriate; we are not permitted to perform deduction
@@ -8355,11 +8288,11 @@ static void AddTemplateConversionCandidateImmediately(
}
QualType ObjectType = From->getType();
- Expr::Classification ObjectClassification = From->Classify(S.Context);
+ Expr::Classification ObjectClassification = From->Classify(getASTContext());
TemplateDeductionInfo Info(CandidateSet.getLocation());
CXXConversionDecl *Specialization = nullptr;
- if (TemplateDeductionResult Result = S.DeduceTemplateArguments(
+ if (TemplateDeductionResult Result = DeduceTemplateArguments(
FunctionTemplate, ObjectType, ObjectClassification, ToType,
Specialization, Info);
Result != TemplateDeductionResult::Success) {
@@ -8369,47 +8302,18 @@ static void AddTemplateConversionCandidateImmediately(
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.ExplicitCallArguments = 1;
- Candidate.DeductionFailure =
- MakeDeductionFailureInfo(S.Context, Result, Info);
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Info);
return;
}
// Add the conversion function template specialization produced by
// template argument deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- S.AddConversionCandidate(Specialization, FoundDecl, ActingContext, From,
- ToType, CandidateSet, AllowObjCConversionOnExplicit,
- AllowExplicit, AllowResultConversion,
- Info.hasStrictPackMatch());
-}
-
-void Sema::AddTemplateConversionCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingDC, Expr *From, QualType ToType,
- OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
- bool AllowExplicit, bool AllowResultConversion) {
- assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
- "Only conversion function templates permitted here");
-
- if (!CandidateSet.isNewCandidate(FunctionTemplate))
- return;
-
- if (!CandidateSet.shouldDeferTemplateArgumentDeduction(getLangOpts()) ||
- CandidateSet.getKind() ==
- OverloadCandidateSet::CSK_InitByUserDefinedConversion ||
- CandidateSet.getKind() == OverloadCandidateSet::CSK_InitByConstructor) {
- AddTemplateConversionCandidateImmediately(
- *this, CandidateSet, FunctionTemplate, FoundDecl, ActingDC, From,
- ToType, AllowObjCConversionOnExplicit, AllowExplicit,
- AllowResultConversion);
-
- CandidateSet.DisableResolutionByPerfectCandidate();
- return;
- }
-
- CandidateSet.AddDeferredConversionTemplateCandidate(
- FunctionTemplate, FoundDecl, ActingDC, From, ToType,
- AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion);
+ AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
+ CandidateSet, AllowObjCConversionOnExplicit,
+ AllowExplicit, AllowResultConversion,
+ Info.hasStrictPackMatch());
}
void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
@@ -8559,17 +8463,11 @@ void Sema::AddNonMemberOperatorCandidates(
if (FunTmpl) {
AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs,
FunctionArgs, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD)) {
-
- // As template candidates are not deduced immediately,
- // persist the array in the overload set.
- ArrayRef<Expr *> Reversed = CandidateSet.getPersistentArgsArray(
- FunctionArgs[1], FunctionArgs[0]);
- AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs,
- Reversed, CandidateSet, false, false, true,
- ADLCallKind::NotADL,
- OverloadCandidateParamOrder::Reversed);
- }
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD))
+ AddTemplateOverloadCandidate(
+ FunTmpl, F.getPair(), ExplicitTemplateArgs,
+ {FunctionArgs[1], FunctionArgs[0]}, CandidateSet, false, false,
+ true, ADLCallKind::NotADL, OverloadCandidateParamOrder::Reversed);
} else {
if (ExplicitTemplateArgs)
continue;
@@ -10301,8 +10199,6 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
// FIXME: Pass in the explicit template arguments?
ArgumentDependentLookup(Name, Loc, Args, Fns);
- ArrayRef<Expr *> ReversedArgs;
-
// Erase all of the candidates we already knew about.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
@@ -10342,15 +10238,9 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
/*AllowExplicit=*/true, ADLCallKind::UsesADL);
if (CandidateSet.getRewriteInfo().shouldAddReversed(
*this, Args, FTD->getTemplatedDecl())) {
-
- // As template candidates are not deduced immediately,
- // persist the array in the overload set.
- if (ReversedArgs.empty())
- ReversedArgs = CandidateSet.getPersistentArgsArray(Args[1], Args[0]);
-
AddTemplateOverloadCandidate(
- FTD, FoundDecl, ExplicitTemplateArgs, ReversedArgs, CandidateSet,
- /*SuppressUserConversions=*/false, PartialOverloading,
+ FTD, FoundDecl, ExplicitTemplateArgs, {Args[1], Args[0]},
+ CandidateSet, /*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit=*/true, ADLCallKind::UsesADL,
OverloadCandidateParamOrder::Reversed);
}
@@ -10764,8 +10654,6 @@ bool clang::isBetterOverloadCandidate(
Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
-
- assert(Cand1.HasFinalConversion && Cand2.HasFinalConversion);
// First check whether we prefer one of the conversion functions over the
// other. This only distinguishes the results in non-standard, extension
// cases such as the conversion from a lambda closure type to a function
@@ -11025,147 +10913,23 @@ bool OverloadCandidate::NotValidBecauseConstraintExprHasError() const {
->Satisfaction.ContainsErrors;
}
-void OverloadCandidateSet::AddDeferredTemplateCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- ArrayRef<Expr *> Args, bool SuppressUserConversions,
- bool PartialOverloading, bool AllowExplicit,
- CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO,
- bool AggregateCandidateDeduction) {
-
- auto *C =
- allocateDeferredCandidate<DeferredFunctionTemplateOverloadCandidate>();
-
- C = new (C) DeferredFunctionTemplateOverloadCandidate{
- {nullptr, DeferredFunctionTemplateOverloadCandidate::Function,
- /*AllowObjCConversionOnExplicit=*/false,
- /*AllowResultConversion=*/false, AllowExplicit, SuppressUserConversions,
- PartialOverloading, AggregateCandidateDeduction},
- FunctionTemplate,
- FoundDecl,
- Args,
- IsADLCandidate,
- PO};
-
- HasDeferredTemplateConstructors |=
- isa<CXXConstructorDecl>(FunctionTemplate->getTemplatedDecl());
-}
-
-void OverloadCandidateSet::AddDeferredMethodTemplateCandidate(
- FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, QualType ObjectType,
- Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
- bool SuppressUserConversions, bool PartialOverloading,
- OverloadCandidateParamOrder PO) {
-
- assert(!isa<CXXConstructorDecl>(MethodTmpl->getTemplatedDecl()));
-
- auto *C =
- allocateDeferredCandidate<DeferredMethodTemplateOverloadCandidate>();
-
- C = new (C) DeferredMethodTemplateOverloadCandidate{
- {nullptr, DeferredFunctionTemplateOverloadCandidate::Method,
- /*AllowObjCConversionOnExplicit=*/false,
- /*AllowResultConversion=*/false,
- /*AllowExplicit=*/false, SuppressUserConversions, PartialOverloading,
- /*AggregateCandidateDeduction=*/false},
- MethodTmpl,
- FoundDecl,
- Args,
- ActingContext,
- ObjectClassification,
- ObjectType,
- PO};
-}
-
-void OverloadCandidateSet::AddDeferredConversionTemplateCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
- bool AllowObjCConversionOnExplicit, bool AllowExplicit,
- bool AllowResultConversion) {
-
- auto *C =
- allocateDeferredCandidate<DeferredConversionTemplateOverloadCandidate>();
-
- C = new (C) DeferredConversionTemplateOverloadCandidate{
- {nullptr, DeferredFunctionTemplateOverloadCandidate::Conversion,
- AllowObjCConversionOnExplicit, AllowResultConversion,
- /*AllowExplicit=*/false,
- /*SuppressUserConversions=*/false,
- /*PartialOverloading*/ false,
- /*AggregateCandidateDeduction=*/false},
- FunctionTemplate,
- FoundDecl,
- ActingContext,
- From,
- ToType};
-}
-
-static void
-AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
- DeferredMethodTemplateOverloadCandidate &C) {
-
- AddMethodTemplateCandidateImmediately(
- S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext,
- /*ExplicitTemplateArgs=*/nullptr, C.ObjectType, C.ObjectClassification,
- C.Args, C.SuppressUserConversions, C.PartialOverloading, C.PO);
-}
-
-static void
-AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
- DeferredFunctionTemplateOverloadCandidate &C) {
- AddTemplateOverloadCandidateImmediately(
- S, CandidateSet, C.FunctionTemplate, C.FoundDecl,
- /*ExplicitTemplateArgs=*/nullptr, C.Args, C.SuppressUserConversions,
- C.PartialOverloading, C.AllowExplicit, C.IsADLCandidate, C.PO,
- C.AggregateCandidateDeduction);
-}
-
-static void
-AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet,
- DeferredConversionTemplateOverloadCandidate &C) {
- return AddTemplateConversionCandidateImmediately(
- S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext, C.From,
- C.ToType, C.AllowObjCConversionOnExplicit, C.AllowExplicit,
- C.AllowResultConversion);
-}
-
-void OverloadCandidateSet::InjectNonDeducedTemplateCandidates(Sema &S) {
- Candidates.reserve(Candidates.size() + DeferredCandidatesCount);
- DeferredTemplateOverloadCandidate *Cand = FirstDeferredCandidate;
- while (Cand) {
- switch (Cand->Kind) {
- case DeferredTemplateOverloadCandidate::Function:
- AddTemplateOverloadCandidate(
- S, *this,
- *static_cast<DeferredFunctionTemplateOverloadCandidate *>(Cand));
- break;
- case DeferredTemplateOverloadCandidate::Method:
- AddTemplateOverloadCandidate(
- S, *this,
- *static_cast<DeferredMethodTemplateOverloadCandidate *>(Cand));
- break;
- case DeferredTemplateOverloadCandidate::Conversion:
- AddTemplateOverloadCandidate(
- S, *this,
- *static_cast<DeferredConversionTemplateOverloadCandidate *>(Cand));
- break;
- }
- Cand = Cand->Next;
- }
- FirstDeferredCandidate = nullptr;
- DeferredCandidatesCount = 0;
-}
-
+/// Computes the best viable function (C++ 13.3.3)
+/// within an overload candidate set.
+///
+/// \param Loc The location of the function name (or operator symbol) for
+/// which overload resolution occurs.
+///
+/// \param Best If overload resolution was successful or found a deleted
+/// function, \p Best points to the candidate function found.
+///
+/// \returns The result of overload resolution.
OverloadingResult
-OverloadCandidateSet::ResultForBestCandidate(const iterator &Best) {
- Best->Best = true;
- if (Best->Function && Best->Function->isDeleted())
- return OR_Deleted;
- return OR_Success;
-}
+OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
+ iterator &Best) {
+ llvm::SmallVector<OverloadCandidate *, 16> Candidates;
+ std::transform(begin(), end(), std::back_inserter(Candidates),
+ [](OverloadCandidate &Cand) { return &Cand; });
-void OverloadCandidateSet::CudaExcludeWrongSideCandidates(
- Sema &S, SmallVectorImpl<OverloadCandidate *> &Candidates) {
// [CUDA] HD->H or HD->D calls are technically not allowed by CUDA but
// are accepted by both clang and NVCC. However, during a particular
// compilation mode only one call variant is viable. We need to
@@ -11177,112 +10941,27 @@ void OverloadCandidateSet::CudaExcludeWrongSideCandidates(
// -fgpu-exclude-wrong-side-overloads is off. When
// -fgpu-exclude-wrong-side-overloads is on, all candidates are compared
// uniformly in isBetterOverloadCandidate.
- if (!S.getLangOpts().CUDA || S.getLangOpts().GPUExcludeWrongSideOverloads)
- return;
- const FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true);
-
- bool ContainsSameSideCandidate =
- llvm::any_of(Candidates, [&](const OverloadCandidate *Cand) {
- // Check viable function only.
+ if (S.getLangOpts().CUDA && !S.getLangOpts().GPUExcludeWrongSideOverloads) {
+ const FunctionDecl *Caller = S.getCurFunctionDecl(/*AllowLambda=*/true);
+ bool ContainsSameSideCandidate =
+ llvm::any_of(Candidates, [&](OverloadCandidate *Cand) {
+ // Check viable function only.
+ return Cand->Viable && Cand->Function &&
+ S.CUDA().IdentifyPreference(Caller, Cand->Function) ==
+ SemaCUDA::CFP_SameSide;
+ });
+ if (ContainsSameSideCandidate) {
+ auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) {
+ // Check viable function only to avoid unnecessary data copying/moving.
return Cand->Viable && Cand->Function &&
S.CUDA().IdentifyPreference(Caller, Cand->Function) ==
- SemaCUDA::CFP_SameSide;
- });
-
- if (!ContainsSameSideCandidate)
- return;
-
- auto IsWrongSideCandidate = [&](const OverloadCandidate *Cand) {
- // Check viable function only to avoid unnecessary data copying/moving.
- return Cand->Viable && Cand->Function &&
- S.CUDA().IdentifyPreference(Caller, Cand->Function) ==
- SemaCUDA::CFP_WrongSide;
- };
- llvm::erase_if(Candidates, IsWrongSideCandidate);
-}
-
-/// Computes the best viable function (C++ 13.3.3)
-/// within an overload candidate set.
-///
-/// \param Loc The location of the function name (or operator symbol) for
-/// which overload resolution occurs.
-///
-/// \param Best If overload resolution was successful or found a deleted
-/// function, \p Best points to the candidate function found.
-///
-/// \returns The result of overload resolution.
-OverloadingResult OverloadCandidateSet::BestViableFunction(Sema &S,
- SourceLocation Loc,
- iterator &Best) {
-
- assert(shouldDeferTemplateArgumentDeduction(S.getLangOpts()) ||
- DeferredCandidatesCount == 0 &&
- "Unexpected deferred template candidates");
-
- bool TwoPhaseResolution =
- DeferredCandidatesCount != 0 && !ResolutionByPerfectCandidateIsDisabled;
-
- if (TwoPhaseResolution) {
-
- PerfectViableFunction(S, Loc, Best);
- if (Best != end())
- return ResultForBestCandidate(Best);
- }
-
- InjectNonDeducedTemplateCandidates(S);
- return BestViableFunctionImpl(S, Loc, Best);
-}
-
-void OverloadCandidateSet::PerfectViableFunction(
- Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best) {
-
- Best = end();
- for (auto It = begin(); It != end(); ++It) {
-
- if (!It->isPerfectMatch(S.getASTContext()))
- continue;
-
- // We found a suitable conversion function
- // but if there is a template constructor in the target class
- // we might prefer that instead.
- if (HasDeferredTemplateConstructors &&
- isa_and_nonnull<CXXConversionDecl>(It->Function)) {
- Best = end();
- break;
- }
-
- if (Best == end()) {
- Best = It;
- continue;
- }
- if (Best->Function && It->Function) {
- FunctionDecl *D =
- S.getMoreConstrainedFunction(Best->Function, It->Function);
- if (D == nullptr) {
- Best = end();
- break;
- }
- if (D == It->Function)
- Best = It;
- continue;
+ SemaCUDA::CFP_WrongSide;
+ };
+ llvm::erase_if(Candidates, IsWrongSideCandidate);
}
- // ambiguous
- Best = end();
- break;
}
-}
-
-OverloadingResult OverloadCandidateSet::BestViableFunctionImpl(
- Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator &Best) {
-
- llvm::SmallVector<OverloadCandidate *, 16> Candidates;
- Candidates.reserve(this->Candidates.size());
- std::transform(begin(), end(), std::back_inserter(Candidates),
- [](OverloadCandidate &Cand) { return &Cand; });
-
- if (S.getLangOpts().CUDA)
- CudaExcludeWrongSideCandidates(S, Candidates);
+ // Find the best viable function.
Best = end();
for (auto *Cand : Candidates) {
Cand->Best = false;
@@ -11304,8 +10983,9 @@ OverloadingResult OverloadCandidateSet::BestViableFunctionImpl(
if (Best == end())
return OR_No_Viable_Function;
- llvm::SmallVector<OverloadCandidate *, 4> PendingBest;
llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
+
+ llvm::SmallVector<OverloadCandidate*, 4> PendingBest;
PendingBest.push_back(&*Best);
Best->Best = true;
@@ -11328,15 +11008,25 @@ OverloadingResult OverloadCandidateSet::BestViableFunctionImpl(
}
}
+ // If we found more than one best candidate, this is ambiguous.
if (Best == end())
return OR_Ambiguous;
- OverloadingResult R = ResultForBestCandidate(Best);
+ // Best is the best viable function.
+ if (Best->Function && Best->Function->isDeleted())
+ return OR_Deleted;
+
+ if (auto *M = dyn_cast_or_null<CXXMethodDecl>(Best->Function);
+ Kind == CSK_AddressOfOverloadSet && M &&
+ M->isImplicitObjectMemberFunction()) {
+ return OR_No_Viable_Function;
+ }
if (!EquivalentCands.empty())
S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
EquivalentCands);
- return R;
+
+ return OR_Success;
}
namespace {
@@ -13043,9 +12733,6 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates(
Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
SourceLocation OpLoc,
llvm::function_ref<bool(OverloadCandidate &)> Filter) {
-
- InjectNonDeducedTemplateCandidates(S);
-
// Sort the candidates by viability and position. Sorting directly would
// be prohibitive, so we make a set of pointers and sort those.
SmallVector<OverloadCandidate*, 32> Cands;
@@ -14667,12 +14354,10 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
Expr *ExecConfig,
bool AllowTypoCorrection,
bool CalleesAddressIsTaken) {
-
- OverloadCandidateSet::CandidateSetKind CSK =
- CalleesAddressIsTaken ? OverloadCandidateSet::CSK_AddressOfOverloadSet
- : OverloadCandidateSet::CSK_Normal;
-
- OverloadCandidateSet CandidateSet(Fn->getExprLoc(), CSK);
+ OverloadCandidateSet CandidateSet(
+ Fn->getExprLoc(), CalleesAddressIsTaken
+ ? OverloadCandidateSet::CSK_AddressOfOverloadSet
+ : OverloadCandidateSet::CSK_Normal);
ExprResult result;
if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
@@ -14688,17 +14373,6 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
OverloadingResult OverloadResult =
CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best);
- // [C++23][over.call.func]
- // if overload resolution selects a non-static member function,
- // the call is ill-formed;
- if (CSK == OverloadCandidateSet::CSK_AddressOfOverloadSet &&
- Best != CandidateSet.end()) {
- if (auto *M = dyn_cast_or_null<CXXMethodDecl>(Best->Function);
- M && M->isImplicitObjectMemberFunction()) {
- OverloadResult = OR_No_Viable_Function;
- }
- }
-
// Model the case with a call to a templated function whose definition
// encloses the call and whose return type contains a placeholder type as if
// the UnresolvedLookupExpr was type-dependent.
@@ -15034,24 +14708,18 @@ void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
// rewritten candidates using these functions if necessary.
AddNonMemberOperatorCandidates(Fns, Args, CandidateSet);
- // As template candidates are not deduced immediately,
- // persist the array in the overload set.
- ArrayRef<Expr *> ReversedArgs;
- if (CandidateSet.getRewriteInfo().allowsReversed(Op) ||
- CandidateSet.getRewriteInfo().allowsReversed(ExtraOp))
- ReversedArgs = CandidateSet.getPersistentArgsArray(Args[1], Args[0]);
-
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
if (CandidateSet.getRewriteInfo().allowsReversed(Op))
- AddMemberOperatorCandidates(Op, OpLoc, ReversedArgs, CandidateSet,
+ AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet,
OverloadCandidateParamOrder::Reversed);
// In C++20, also add any rewritten member candidates.
if (ExtraOp) {
AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet);
if (CandidateSet.getRewriteInfo().allowsReversed(ExtraOp))
- AddMemberOperatorCandidates(ExtraOp, OpLoc, ReversedArgs, CandidateSet,
+ AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
+ CandidateSet,
OverloadCandidateParamOrder::Reversed);
}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 0ecdbb3ffb89f..772962ac653f7 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -6142,9 +6142,9 @@ FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1,
assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() &&
"not for function templates");
assert(!FD1->isFunctionTemplateSpecialization() ||
- (isa<CXXConversionDecl, CXXConstructorDecl>(FD1)));
+ isa<CXXConversionDecl>(FD1));
assert(!FD2->isFunctionTemplateSpecialization() ||
- (isa<CXXConversionDecl, CXXConstructorDecl>(FD2)));
+ isa<CXXConversionDecl>(FD2));
FunctionDecl *F1 = FD1;
if (FunctionDecl *P = FD1->getTemplateInstantiationPattern(false))
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
index 083e743818121..ba8e2dc372e98 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
@@ -14,7 +14,7 @@ template<typename T> struct S {
// expected-note@#FINST{{in instantiation of function template specialization}}
template<typename T> requires (S<T>{})
void f(T);
-void f(long);
+void f(int);
// Ensure this applies to operator && as well.
// expected-error at +3{{atomic constraint must be of type 'bool' (found 'S<int>')}}
@@ -22,7 +22,7 @@ void f(long);
// expected-note@#F2INST{{in instantiation of function template specialization}}
template<typename T> requires (S<T>{} && true)
void f2(T);
-void f2(long);
+void f2(int);
template<typename T> requires requires {
requires S<T>{};
@@ -36,12 +36,12 @@ template<typename T> requires requires {
//
}
void f3(T);
-void f3(long);
+void f3(int);
// Doesn't diagnose, since this is no longer a compound requirement.
template<typename T> requires (bool(1 && 2))
void f4(T);
-void f4(long);
+void f4(int);
void g() {
f(0); // #FINST
diff --git a/clang/test/SemaCUDA/function-overload.cu b/clang/test/SemaCUDA/function-overload.cu
index 3d05839af7528..4710c81763adf 100644
--- a/clang/test/SemaCUDA/function-overload.cu
+++ b/clang/test/SemaCUDA/function-overload.cu
@@ -1,3 +1,6 @@
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-linux-gnu -fsyntax-only \
// RUN: -verify=host,hostdefer,devdefer,expected %s
// RUN: %clang_cc1 -std=c++14 -triple nvptx64-nvidia-cuda -fsyntax-only \
diff --git a/clang/test/SemaCXX/implicit-member-functions.cpp b/clang/test/SemaCXX/implicit-member-functions.cpp
index 8350eac5b88a0..1554b1af5d59a 100644
--- a/clang/test/SemaCXX/implicit-member-functions.cpp
+++ b/clang/test/SemaCXX/implicit-member-functions.cpp
@@ -54,24 +54,31 @@ namespace PR7594 {
namespace Recursion {
template<typename T> struct InvokeCopyConstructor {
static const T &get();
- typedef decltype(T(get())) type;
+ typedef decltype(T(get())) type; // expected-error {{no matching conver}}
};
struct B;
struct A {
+ // expected-note at -1 {{while substituting deduced template arguments}}
typedef B type;
template<typename T,
typename = typename InvokeCopyConstructor<typename T::type>::type>
+ // expected-note at -1 {{in instantiation of template class}}
A(const T &);
+ // expected-note at -1 {{in instantiation of default argument}}
};
- struct B {
- B();
+ struct B { // expected-note {{while declaring the implicit copy constructor for 'B'}}
+ // expected-note at -1 {{candidate constructor (the implicit move }}
+ B(); // expected-note {{candidate constructor not viable}}
A a;
};
// Triggering the declaration of B's copy constructor causes overload
- // resolution to occur for A's copying constructor, which picks
- // the implicit copy constructor of A.
- // Because that copy constructor is always a perfect match the template
- // candidate is not instantiated.
+ // resolution to occur for A's copying constructor, which instantiates
+ // InvokeCopyConstructor<B>, which triggers the declaration of B's copy
+ // constructor. Notionally, this happens when we get to the end of the
+ // definition of 'struct B', so there is no declared copy constructor yet.
+ //
+ // This behavior is g++-compatible, but isn't exactly right; the class is
+ // supposed to be incomplete when we implicitly declare its special members.
B b = B();
diff --git a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp
deleted file mode 100644
index 9139fd2688790..0000000000000
--- a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -fsyntax-only -verify -std=c++11 %s
-// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -fsyntax-only -verify -std=c++20 %s
-// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -fsyntax-only -verify -std=c++2c %s
-
-template <typename T>
-struct Invalid { static_assert(false, "instantiated Invalid"); }; // #err-invalid
-
-template <typename T>
-int f(T a, Invalid<T> = {}); // #note-f
-
-// sanity check
-int e1 = f(0);
-//expected-error@#err-invalid {{static assertion failed: instantiated Invalid}}
-//expected-note at -2 {{in instantiation of default function argument expression for 'f<int>' required here}}
-//expected-note@#note-f {{in instantiation of template class 'Invalid<int>' requested here}}
-//expected-note@#note-f {{passing argument to parameter here}}
-
-int f(int);
-int ok1 = f(0);
-int e4 = f((const int&)(ok1));
-
-int f(int, int = 0);
-int ok2 = f(0, 0);
-
-int e2 = f(0L);
-//expected-error@#err-invalid {{static assertion failed: instantiated Invalid}}
-//expected-note at -2 {{in instantiation of default function argument expression for 'f<long>' required here}}
-//expected-note@#note-f {{in instantiation of template class 'Invalid<long>' requested here}}
-//expected-note@#note-f {{passing argument to parameter here}}
-
-int f(long);
-int ok3 = f(0L);
-
-template <typename T>
-struct Invalid2 { static_assert(false, "instantiated Invalid2"); }; // #err-qualifiers
-
-template <typename T>
-int ref(T a, Invalid2<T> = {}); // expected-note 2{{here}}
-int ref(int&);
-int ref1 = ref(ok3);
-int ref2 = ref((const int&)ok3); // expected-note {{here}}
-//expected-error@#err-qualifiers {{static assertion failed: instantiated Invalid2}}
-
-
-template <typename T>
-int f_alias(T a, Invalid<T> = {});
-using Alias = int;
-int f_alias(Alias);
-int ok4 = f_alias(0);
-
-#if __cplusplus >= 202002
-
-struct Copyable {
- template <typename T>
- requires __is_constructible(Copyable, T)
- explicit Copyable(T op) noexcept; // #1
- Copyable(const Copyable&) noexcept = default; // #2
-};
-static_assert(__is_constructible(Copyable, const Copyable&));
-
-struct ImplicitlyCopyable {
- template <typename T>
- requires __is_constructible(ImplicitlyCopyable, T)
- explicit ImplicitlyCopyable(T op) = delete; // #1
-};
-static_assert(__is_constructible(ImplicitlyCopyable, const ImplicitlyCopyable&));
-
-
-struct Movable {
- template <typename T>
- requires __is_constructible(Movable, T) // #err-self-constraint-1
- explicit Movable(T op) noexcept; // #1
- Movable(Movable&&) noexcept = default; // #2
-};
-static_assert(__is_constructible(Movable, Movable&&));
-static_assert(__is_constructible(Movable, const Movable&));
-// expected-error at -1 {{static assertion failed due to requirement '__is_constructible(Movable, const Movable &)'}}
-
-static_assert(__is_constructible(Movable, int));
-// expected-error at -1{{static assertion failed due to requirement '__is_constructible(Movable, int)'}} \
-// expected-note at -1 2{{}}
-// expected-error@#err-self-constraint-1{{satisfaction of constraint '__is_constructible(Movable, T)' depends on itself}}
-// expected-note@#err-self-constraint-1 4{{}}
-
-template <typename T>
-struct Members {
- constexpr auto f(auto) {
- static_assert(false, "");
- }
- constexpr auto f(int) { return 1; }
- constexpr auto f(int) requires true { return 2; }
-
- constexpr auto g(auto) {
- static_assert(false, "instantiated member"); //#err-qualified-member
- return 0;
- }
- constexpr auto g(int) & { return 1; }
-
- static constexpr auto s(auto) {
- static_assert(false, "");
- }
- static constexpr auto s(int) {
- return 1;
- }
- static constexpr auto s(int) requires true {
- return 2;
- }
-};
-
-static_assert(Members<int[1]>{}.f(0) == 2);
-static_assert(Members<int[2]>{}.g(0) == 0);
-// expected-error@#err-qualified-member {{static assertion failed: instantiated member}} \
-// expected-note at -1{{in instantiation of function template specialization 'Members<int[2]>::g<int>' }}
-Members<int[3]> m1;
-static_assert(m1.g(0) == 1);
-static_assert(Members<int[3]>{}.s(0) == 2);
-
-
-namespace ConstructorInit{
-struct S {
- template <typename T>
- S(T&&) {}
-};
-struct Test {
- operator S() = delete;
-};
-
-static_assert(__is_constructible(S, Test));
-}
-
-namespace RefBinding {
-
-template <typename> struct remove_reference;
-template <typename _Tp> struct remove_reference<_Tp &> {
- using type = _Tp;
-};
-template <typename _Tp> remove_reference<_Tp>::type move(_Tp &&);
-template <typename _Head> struct _Head_base {
- _Head_base(_Head &__h) : _M_head_impl(__h) {}
- template <typename _UHead> _Head_base(_UHead &&);
- _Head _M_head_impl;
-};
-
-template <typename _Elements> void forward_as_tuple(_Elements &&) {
- _Head_base<_Elements &&>(_Elements{});
-}
-struct StringRef {
- void operator[](const StringRef __k) { forward_as_tuple((move)(__k)); }
-};
-
-}
-
-template <class> struct tuple {};
-struct BonkersBananas {
- template <class T> operator T();
- template <class = void> explicit operator tuple<int>() = delete;
-};
-static_assert(!__is_constructible(tuple<int>, BonkersBananas));
-
-namespace GH62096 {
-template <typename T>
-struct Oops {
- static_assert(sizeof(T) == 0); // #GH62096-err
- static constexpr bool value = true;
-};
-
-template <class OPERATOR>
-concept Operator = Oops<OPERATOR>::value; // #GH62096-note1
-
-template <Operator OP> void f(OP op); // // #GH62096-note2
-void f(int);
-
-void g(int n) { f(n); } // OK
-void h(short n) { f(n); }
-// expected-error@#GH62096-err {{static assertion failed due to requirement 'sizeof(short) == 0'}} \
-// expected-note at -1{{in instantiation of function template specialization}} \
-// expected-note at -1{{while checking constraint satisfaction for template}}
-// expected-note@#GH62096-note1{{in instantiation}}
-// expected-note@#GH62096-note1{{while substituting template arguments into constraint expression here}}
-// expected-note@#GH62096-note2{{while substituting template arguments into constraint expression here}}
-// expected-note@#GH62096-note2{{while checking the satisfaction of concept}}
-// expected-note@#GH62096-err {{expression evaluates}}
-}
-
-#endif
-
-template<typename ...Ts>
-struct t1 {
-};
-struct t6 {
- template<typename T = int>
- operator t1<float>() {
- return {};
- }
-};
-
-int main() {
- t6 v6;
- v6.operator t1<float>();
-}
diff --git a/clang/test/SemaTemplate/instantiate-function-params.cpp b/clang/test/SemaTemplate/instantiate-function-params.cpp
index eb2a7c5d4e8d6..7dd5595de58a3 100644
--- a/clang/test/SemaTemplate/instantiate-function-params.cpp
+++ b/clang/test/SemaTemplate/instantiate-function-params.cpp
@@ -6,12 +6,13 @@ template<typename T1> struct if_ {
typedef if_c< static_cast<bool>(T1::value)> almost_type_; // expected-note 7{{in instantiation}}
};
template <class Model, void (Model::*)()> struct wrap_constraints { };
-template <class Model>
+template <class Model>
inline char has_constraints_(Model* , // expected-note 3{{candidate template ignored}}
- wrap_constraints<Model,&Model::constraints>* = 0);
+ wrap_constraints<Model,&Model::constraints>* = 0); // expected-note 4{{in instantiation}}
+
template <class Model> struct not_satisfied {
static const bool value = sizeof( has_constraints_((Model*)0) == 1); // expected-error 3{{no matching function}} \
- // expected-note 4{{in instantiation}}
+ // expected-note 4{{while substituting deduced template arguments into function template 'has_constraints_' [with }}
};
template <class ModelFn> struct requirement_;
template <void(*)()> struct instantiate {
diff --git a/clang/test/Templight/templight-empty-entries-fix.cpp b/clang/test/Templight/templight-empty-entries-fix.cpp
index 7f34b10134929..d13b748068efe 100644
--- a/clang/test/Templight/templight-empty-entries-fix.cpp
+++ b/clang/test/Templight/templight-empty-entries-fix.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -templight-dump -Wno-unused-value %s 2>&1 | FileCheck %s
-void a(long) {
+void a() {
[] {};
}
@@ -17,14 +17,14 @@ void a(long) {
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:4:3'$}}
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:4:3'$}}
-template <int = 0> void a(long) { a(0); }
+template <int = 0> void a() { a(); }
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+a$}}
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template non-type parameter 0 of a$}}
// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
@@ -42,29 +42,29 @@ template <int = 0> void a(long) { a(0); }
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'a<0>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'a<0>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:35'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:20:31'$}}
template <int> struct b { typedef int c; };
-template <bool d = true, class = typename b<d>::c> void a(long) { a(0); }
+template <bool d = true, class = typename b<d>::c> void a() { a(); }
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+a$}}
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
@@ -130,25 +130,25 @@ template <bool d = true, class = typename b<d>::c> void a(long) { a(0); }
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'a<true, int>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'a<true, int>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+a$}}
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template non-type parameter 0 of a$}}
// CHECK: {{^kind:[ ]+DefaultTemplateArgumentInstantiation$}}
@@ -166,10 +166,34 @@ template <bool d = true, class = typename b<d>::c> void a(long) { a(0); }
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:67'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
template <bool = true> void d(int = 0) { d(); }
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+a$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+a$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+a$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+Begin$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
+// CHECK-LABEL: {{^---$}}
+// CHECK: {{^name:[ ]+a$}}
+// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
+// CHECK: {{^event:[ ]+End$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
@@ -225,41 +249,41 @@ void e() {
}
// CHECK-LABEL: {{^---$}}
-// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
+// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
// CHECK-LABEL: {{^---$}}
-// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
+// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
// CHECK-LABEL: {{^---$}}
-// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
+// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
// CHECK-LABEL: {{^---$}}
-// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
+// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
// CHECK-LABEL: {{^---$}}
-// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
+// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
// CHECK-LABEL: {{^---$}}
-// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
+// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
// CHECK: {{^kind:[ ]+Memoization$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
template <template<typename> class>
@@ -275,71 +299,71 @@ void foo() {
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
// CHECK: {{^poi:[ ]+''$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
// CHECK: {{^poi:[ ]+''$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:5'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:5'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:5'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:5'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'d<C>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+Begin$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+'d<C>'$}}
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
// CHECK: {{^event:[ ]+End$}}
-// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+Begin$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
// CHECK-LABEL: {{^---$}}
// CHECK: {{^name:[ ]+d$}}
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
// CHECK: {{^event:[ ]+End$}}
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
-// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
+// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
More information about the llvm-branch-commits
mailing list