Skip to content

Commit 6ccc928

Browse files
authored
Revert "[Clang][RFC] Bypass TAD during overload resolution if a perfect match exists" (#135993)
Reverts #133426 This is failing on some bots https://lab.llvm.org/buildbot/#/builders/163/builds/17265
1 parent 1576fa1 commit 6ccc928

12 files changed

+217
-910
lines changed

clang/docs/ReleaseNotes.rst

-6
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,6 @@ C++ Language Changes
9696
asm((std::string_view("nop")) ::: (std::string_view("memory")));
9797
}
9898

99-
- Clang now implements the changes to overload resolution proposed by section 1 and 2 of
100-
`P3606 <https://wg21.link/P3606R0>`_. If a non-template candidate exists in an overload set that is
101-
a perfect match (all conversion sequences are identity conversions) template candiates are not instantiated.
102-
Diagnostics that would have resulted from the instantiation of these template candidates are no longer
103-
produced. This aligns Clang closer to the behavior of GCC, and fixes (#GH62096), (#GH74581), and (#GH74581).
104-
10599
C++2c Feature Support
106100
^^^^^^^^^^^^^^^^^^^^^
107101

clang/include/clang/Sema/Overload.h

+9-215
Original file line numberDiff line numberDiff line change
@@ -407,24 +407,6 @@ class Sema;
407407
Third == ICK_Identity;
408408
}
409409

410-
/// A conversion sequence is perfect if it is an identity conversion and
411-
/// the type of the source is the same as the type of the target.
412-
bool isPerfect(const ASTContext &C) const {
413-
if (!isIdentityConversion())
414-
return false;
415-
// If we are not performing a reference binding, we can skip comparing
416-
// the types, which has a noticeable performance impact.
417-
if (!ReferenceBinding) {
418-
assert(First || C.hasSameUnqualifiedType(getFromType(), getToType(2)));
419-
return true;
420-
}
421-
if (!C.hasSameType(getFromType(), getToType(2)))
422-
return false;
423-
if (BindsToRvalue && IsLvalueReference)
424-
return false;
425-
return true;
426-
}
427-
428410
ImplicitConversionRank getRank() const;
429411
NarrowingKind
430412
getNarrowingKind(ASTContext &Context, const Expr *Converted,
@@ -761,12 +743,6 @@ class Sema;
761743
Standard.setAllToTypes(T);
762744
}
763745

764-
/// A conversion sequence is perfect if it is an identity conversion and
765-
/// the type of the source is the same as the type of the target.
766-
bool isPerfect(const ASTContext &C) const {
767-
return isStandard() && Standard.isPerfect(C);
768-
}
769-
770746
// True iff this is a conversion sequence from an initializer list to an
771747
// array or std::initializer.
772748
bool hasInitializerListContainerType() const {
@@ -1003,20 +979,6 @@ class Sema;
1003979
return false;
1004980
}
1005981

1006-
// An overload is a perfect match if the conversion
1007-
// sequences for each argument are perfect.
1008-
bool isPerfectMatch(const ASTContext &Ctx) const {
1009-
if (!Viable)
1010-
return false;
1011-
for (const auto &C : Conversions) {
1012-
if (!C.isInitialized() || !C.isPerfect(Ctx))
1013-
return false;
1014-
}
1015-
if (isa_and_nonnull<CXXConversionDecl>(Function))
1016-
return FinalConversion.isPerfect(Ctx);
1017-
return true;
1018-
}
1019-
1020982
bool TryToFixBadConversion(unsigned Idx, Sema &S) {
1021983
bool CanFix = Fix.tryToFixConversion(
1022984
Conversions[Idx].Bad.FromExpr,
@@ -1053,65 +1015,6 @@ class Sema;
10531015
RewriteKind(CRK_None) {}
10541016
};
10551017

1056-
struct DeferredTemplateOverloadCandidate {
1057-
1058-
// intrusive linked list support for allocateDeferredCandidate
1059-
DeferredTemplateOverloadCandidate *Next = nullptr;
1060-
1061-
enum Kind { Function, Method, Conversion };
1062-
1063-
LLVM_PREFERRED_TYPE(Kind)
1064-
unsigned Kind : 2;
1065-
LLVM_PREFERRED_TYPE(bool)
1066-
unsigned AllowObjCConversionOnExplicit : 1;
1067-
LLVM_PREFERRED_TYPE(bool)
1068-
unsigned AllowResultConversion : 1;
1069-
LLVM_PREFERRED_TYPE(bool)
1070-
unsigned AllowExplicit : 1;
1071-
LLVM_PREFERRED_TYPE(bool)
1072-
unsigned SuppressUserConversions : 1;
1073-
LLVM_PREFERRED_TYPE(bool)
1074-
unsigned PartialOverloading : 1;
1075-
LLVM_PREFERRED_TYPE(bool)
1076-
unsigned AggregateCandidateDeduction : 1;
1077-
};
1078-
1079-
struct DeferredFunctionTemplateOverloadCandidate
1080-
: public DeferredTemplateOverloadCandidate {
1081-
FunctionTemplateDecl *FunctionTemplate;
1082-
DeclAccessPair FoundDecl;
1083-
ArrayRef<Expr *> Args;
1084-
CallExpr::ADLCallKind IsADLCandidate;
1085-
OverloadCandidateParamOrder PO;
1086-
};
1087-
static_assert(std::is_trivially_destructible_v<
1088-
DeferredFunctionTemplateOverloadCandidate>);
1089-
1090-
struct DeferredMethodTemplateOverloadCandidate
1091-
: public DeferredTemplateOverloadCandidate {
1092-
FunctionTemplateDecl *FunctionTemplate;
1093-
DeclAccessPair FoundDecl;
1094-
ArrayRef<Expr *> Args;
1095-
CXXRecordDecl *ActingContext;
1096-
Expr::Classification ObjectClassification;
1097-
QualType ObjectType;
1098-
OverloadCandidateParamOrder PO;
1099-
};
1100-
static_assert(std::is_trivially_destructible_v<
1101-
DeferredMethodTemplateOverloadCandidate>);
1102-
1103-
struct DeferredConversionTemplateOverloadCandidate
1104-
: public DeferredTemplateOverloadCandidate {
1105-
FunctionTemplateDecl *FunctionTemplate;
1106-
DeclAccessPair FoundDecl;
1107-
CXXRecordDecl *ActingContext;
1108-
Expr *From;
1109-
QualType ToType;
1110-
};
1111-
1112-
static_assert(std::is_trivially_destructible_v<
1113-
DeferredConversionTemplateOverloadCandidate>);
1114-
11151018
/// OverloadCandidateSet - A set of overload candidates, used in C++
11161019
/// overload resolution (C++ 13.3).
11171020
class OverloadCandidateSet {
@@ -1140,11 +1043,6 @@ class Sema;
11401043
/// C++ [over.match.call.general]
11411044
/// Resolve a call through the address of an overload set.
11421045
CSK_AddressOfOverloadSet,
1143-
1144-
/// When doing overload resolution during code completion,
1145-
/// we want to show all viable candidates, including otherwise
1146-
/// deferred template candidates.
1147-
CSK_CodeCompletion,
11481046
};
11491047

11501048
/// Information about operator rewrites to consider when adding operator
@@ -1219,27 +1117,16 @@ class Sema;
12191117
SmallVector<OverloadCandidate, 16> Candidates;
12201118
llvm::SmallPtrSet<uintptr_t, 16> Functions;
12211119

1222-
DeferredTemplateOverloadCandidate *FirstDeferredCandidate = nullptr;
1223-
unsigned DeferredCandidatesCount : 8 * sizeof(unsigned) - 2;
1224-
LLVM_PREFERRED_TYPE(bool)
1225-
unsigned HasDeferredTemplateConstructors : 1;
1226-
LLVM_PREFERRED_TYPE(bool)
1227-
unsigned ResolutionByPerfectCandidateIsDisabled : 1;
1228-
1229-
// Allocator for ConversionSequenceLists and deferred candidate args.
1230-
// We store the first few of these
1120+
// Allocator for ConversionSequenceLists. We store the first few of these
12311121
// inline to avoid allocation for small sets.
12321122
llvm::BumpPtrAllocator SlabAllocator;
12331123

12341124
SourceLocation Loc;
12351125
CandidateSetKind Kind;
12361126
OperatorRewriteInfo RewriteInfo;
12371127

1238-
/// Small storage size for ImplicitConversionSequences
1239-
/// and the persisted arguments of deferred candidates.
12401128
constexpr static unsigned NumInlineBytes =
1241-
32 * sizeof(ImplicitConversionSequence);
1242-
1129+
24 * sizeof(ImplicitConversionSequence);
12431130
unsigned NumInlineBytesUsed = 0;
12441131
alignas(void *) char InlineSpace[NumInlineBytes];
12451132

@@ -1250,13 +1137,15 @@ class Sema;
12501137
/// from the slab allocator.
12511138
/// FIXME: It would probably be nice to have a SmallBumpPtrAllocator
12521139
/// instead.
1140+
/// FIXME: Now that this only allocates ImplicitConversionSequences, do we
1141+
/// want to un-generalize this?
12531142
template <typename T>
12541143
T *slabAllocate(unsigned N) {
12551144
// It's simpler if this doesn't need to consider alignment.
12561145
static_assert(alignof(T) == alignof(void *),
12571146
"Only works for pointer-aligned types.");
1258-
static_assert(std::is_trivially_destructible_v<T> ||
1259-
(std::is_same_v<ImplicitConversionSequence, T>),
1147+
static_assert(std::is_trivial<T>::value ||
1148+
std::is_same<ImplicitConversionSequence, T>::value,
12601149
"Add destruction logic to OverloadCandidateSet::clear().");
12611150

12621151
unsigned NBytes = sizeof(T) * N;
@@ -1270,34 +1159,12 @@ class Sema;
12701159
return reinterpret_cast<T *>(FreeSpaceStart);
12711160
}
12721161

1273-
// Because the size of OverloadCandidateSet has a noticeable impact on
1274-
// performance, we store each deferred template candidate in the slab
1275-
// allocator such that deferred candidates are ultimately a singly-linked
1276-
// intrusive linked list. This ends up being much more efficient than a
1277-
// SmallVector that is empty in the common case.
1278-
template <typename T> T *allocateDeferredCandidate() {
1279-
T *C = slabAllocate<T>(1);
1280-
if (!FirstDeferredCandidate)
1281-
FirstDeferredCandidate = C;
1282-
else {
1283-
auto *F = FirstDeferredCandidate;
1284-
while (F->Next)
1285-
F = F->Next;
1286-
F->Next = C;
1287-
}
1288-
DeferredCandidatesCount++;
1289-
return C;
1290-
}
1291-
12921162
void destroyCandidates();
12931163

12941164
public:
12951165
OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
12961166
OperatorRewriteInfo RewriteInfo = {})
1297-
: FirstDeferredCandidate(nullptr), DeferredCandidatesCount(0),
1298-
HasDeferredTemplateConstructors(false),
1299-
ResolutionByPerfectCandidateIsDisabled(false), Loc(Loc), Kind(CSK),
1300-
RewriteInfo(RewriteInfo) {}
1167+
: Loc(Loc), Kind(CSK), RewriteInfo(RewriteInfo) {}
13011168
OverloadCandidateSet(const OverloadCandidateSet &) = delete;
13021169
OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
13031170
~OverloadCandidateSet() { destroyCandidates(); }
@@ -1309,9 +1176,6 @@ class Sema;
13091176
/// Whether diagnostics should be deferred.
13101177
bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc);
13111178

1312-
// Whether the resolution of template candidates should be deferred
1313-
bool shouldDeferTemplateArgumentDeduction(const LangOptions &Opts) const;
1314-
13151179
/// Determine when this overload candidate will be new to the
13161180
/// overload set.
13171181
bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO =
@@ -1335,10 +1199,8 @@ class Sema;
13351199
iterator begin() { return Candidates.begin(); }
13361200
iterator end() { return Candidates.end(); }
13371201

1338-
size_t size() const { return Candidates.size() + DeferredCandidatesCount; }
1339-
bool empty() const {
1340-
return Candidates.empty() && DeferredCandidatesCount == 0;
1341-
}
1202+
size_t size() const { return Candidates.size(); }
1203+
bool empty() const { return Candidates.empty(); }
13421204

13431205
/// Allocate storage for conversion sequences for NumConversions
13441206
/// conversions.
@@ -1354,24 +1216,6 @@ class Sema;
13541216
return ConversionSequenceList(Conversions, NumConversions);
13551217
}
13561218

1357-
/// Provide storage for any Expr* arg that must be preserved
1358-
/// until deferred template candidates are deduced.
1359-
/// Typically this should be used for reversed operator arguments
1360-
/// and any time the argument array is transformed while adding
1361-
/// a template candidate.
1362-
llvm::MutableArrayRef<Expr *> getPersistentArgsArray(unsigned N) {
1363-
Expr **Exprs = slabAllocate<Expr *>(N);
1364-
return llvm::MutableArrayRef<Expr *>(Exprs, N);
1365-
}
1366-
1367-
template <typename... T>
1368-
llvm::MutableArrayRef<Expr *> getPersistentArgsArray(T *...Exprs) {
1369-
llvm::MutableArrayRef<Expr *> Arr =
1370-
getPersistentArgsArray(sizeof...(Exprs));
1371-
llvm::copy(std::initializer_list<Expr *>{Exprs...}, Arr.data());
1372-
return Arr;
1373-
}
1374-
13751219
/// Add a new candidate with NumConversions conversion sequence slots
13761220
/// to the overload set.
13771221
OverloadCandidate &addCandidate(unsigned NumConversions = 0,
@@ -1387,32 +1231,6 @@ class Sema;
13871231
return C;
13881232
}
13891233

1390-
void AddDeferredTemplateCandidate(
1391-
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
1392-
ArrayRef<Expr *> Args, bool SuppressUserConversions,
1393-
bool PartialOverloading, bool AllowExplicit,
1394-
CallExpr::ADLCallKind IsADLCandidate, OverloadCandidateParamOrder PO,
1395-
bool AggregateCandidateDeduction);
1396-
1397-
void AddDeferredMethodTemplateCandidate(
1398-
FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
1399-
CXXRecordDecl *ActingContext, QualType ObjectType,
1400-
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
1401-
bool SuppressUserConversions, bool PartialOverloading,
1402-
OverloadCandidateParamOrder PO);
1403-
1404-
void AddDeferredConversionTemplateCandidate(
1405-
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
1406-
CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
1407-
bool AllowObjCConversionOnExplicit, bool AllowExplicit,
1408-
bool AllowResultConversion);
1409-
1410-
void InjectNonDeducedTemplateCandidates(Sema &S);
1411-
1412-
void DisableResolutionByPerfectCandidate() {
1413-
ResolutionByPerfectCandidateIsDisabled = true;
1414-
}
1415-
14161234
/// Find the best viable function on this overload set, if it exists.
14171235
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
14181236
OverloadCandidateSet::iterator& Best);
@@ -1445,15 +1263,6 @@ class Sema;
14451263
DestAS = AS;
14461264
}
14471265

1448-
private:
1449-
OverloadingResult ResultForBestCandidate(const iterator &Best);
1450-
void CudaExcludeWrongSideCandidates(
1451-
Sema &S, SmallVectorImpl<OverloadCandidate *> &Candidates);
1452-
OverloadingResult
1453-
BestViableFunctionImpl(Sema &S, SourceLocation Loc,
1454-
OverloadCandidateSet::iterator &Best);
1455-
void PerfectViableFunction(Sema &S, SourceLocation Loc,
1456-
OverloadCandidateSet::iterator &Best);
14571266
};
14581267

14591268
bool isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
@@ -1502,21 +1311,6 @@ class Sema;
15021311
// parameter.
15031312
bool shouldEnforceArgLimit(bool PartialOverloading, FunctionDecl *Function);
15041313

1505-
inline bool OverloadCandidateSet::shouldDeferTemplateArgumentDeduction(
1506-
const LangOptions &Opts) const {
1507-
return
1508-
// For user defined conversion we need to check against different
1509-
// combination of CV qualifiers and look at any explicit specifier, so
1510-
// always deduce template candidates.
1511-
Kind != CSK_InitByUserDefinedConversion
1512-
// When doing code completion, we want to see all the
1513-
// viable candidates.
1514-
&& Kind != CSK_CodeCompletion
1515-
// CUDA may prefer template candidates even when a non-candidate
1516-
// is a perfect match
1517-
&& !Opts.CUDA;
1518-
}
1519-
15201314
} // namespace clang
15211315

15221316
#endif // LLVM_CLANG_SEMA_OVERLOAD_H

clang/lib/Sema/SemaCodeComplete.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -6354,8 +6354,7 @@ SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
63546354
Expr *NakedFn = Fn->IgnoreParenCasts();
63556355
// Build an overload candidate set based on the functions we find.
63566356
SourceLocation Loc = Fn->getExprLoc();
6357-
OverloadCandidateSet CandidateSet(Loc,
6358-
OverloadCandidateSet::CSK_CodeCompletion);
6357+
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
63596358

63606359
if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {
63616360
SemaRef.AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes,
@@ -6558,8 +6557,7 @@ QualType SemaCodeCompletion::ProduceConstructorSignatureHelp(
65586557
// FIXME: Provide support for variadic template constructors.
65596558

65606559
if (CRD) {
6561-
OverloadCandidateSet CandidateSet(Loc,
6562-
OverloadCandidateSet::CSK_CodeCompletion);
6560+
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
65636561
for (NamedDecl *C : SemaRef.LookupConstructors(CRD)) {
65646562
if (auto *FD = dyn_cast<FunctionDecl>(C)) {
65656563
// FIXME: we can't yet provide correct signature help for initializer

clang/lib/Sema/SemaInit.cpp

+4-11
Original file line numberDiff line numberDiff line change
@@ -10029,19 +10029,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
1002910029
// When [...] the constructor [...] is a candidate by
1003010030
// - [over.match.copy] (in all cases)
1003110031
if (TD) {
10032-
10033-
// As template candidates are not deduced immediately,
10034-
// persist the array in the overload set.
10035-
MutableArrayRef<Expr *> TmpInits =
10036-
Candidates.getPersistentArgsArray(Inits.size());
10037-
10038-
for (auto [I, E] : llvm::enumerate(Inits)) {
10032+
SmallVector<Expr *, 8> TmpInits;
10033+
for (Expr *E : Inits)
1003910034
if (auto *DI = dyn_cast<DesignatedInitExpr>(E))
10040-
TmpInits[I] = DI->getInit();
10035+
TmpInits.push_back(DI->getInit());
1004110036
else
10042-
TmpInits[I] = E;
10043-
}
10044-
10037+
TmpInits.push_back(E);
1004510038
AddTemplateOverloadCandidate(
1004610039
TD, FoundDecl, /*ExplicitArgs=*/nullptr, TmpInits, Candidates,
1004710040
/*SuppressUserConversions=*/false,

0 commit comments

Comments
 (0)