Skip to content

Commit 8c8aae8

Browse files
committed
Revert "recommit c77a407"
This reverts commit b46b1a9. It broke overload resolution for operator 'new' -- see reproducer in https://reviews.llvm.org/D77954.
1 parent 61b8af0 commit 8c8aae8

File tree

2 files changed

+56
-122
lines changed

2 files changed

+56
-122
lines changed

clang/lib/Sema/SemaOverload.cpp

Lines changed: 46 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -9374,22 +9374,16 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
93749374
return Comparison::Equal;
93759375
}
93769376

9377-
static Comparison
9378-
isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
9379-
const OverloadCandidate &Cand2) {
9377+
static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
9378+
const OverloadCandidate &Cand2) {
93809379
if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function ||
93819380
!Cand2.Function->isMultiVersion())
9382-
return Comparison::Equal;
9381+
return false;
93839382

9384-
// If both are invalid, they are equal. If one of them is invalid, the other
9385-
// is better.
9386-
if (Cand1.Function->isInvalidDecl()) {
9387-
if (Cand2.Function->isInvalidDecl())
9388-
return Comparison::Equal;
9389-
return Comparison::Worse;
9390-
}
9391-
if (Cand2.Function->isInvalidDecl())
9392-
return Comparison::Better;
9383+
// If Cand1 is invalid, it cannot be a better match, if Cand2 is invalid, this
9384+
// is obviously better.
9385+
if (Cand1.Function->isInvalidDecl()) return false;
9386+
if (Cand2.Function->isInvalidDecl()) return true;
93939387

93949388
// If this is a cpu_dispatch/cpu_specific multiversion situation, prefer
93959389
// cpu_dispatch, else arbitrarily based on the identifiers.
@@ -9399,18 +9393,16 @@ isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
93999393
const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>();
94009394

94019395
if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec)
9402-
return Comparison::Equal;
9396+
return false;
94039397

94049398
if (Cand1CPUDisp && !Cand2CPUDisp)
9405-
return Comparison::Better;
9399+
return true;
94069400
if (Cand2CPUDisp && !Cand1CPUDisp)
9407-
return Comparison::Worse;
9401+
return false;
94089402

94099403
if (Cand1CPUSpec && Cand2CPUSpec) {
94109404
if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size())
9411-
return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size()
9412-
? Comparison::Better
9413-
: Comparison::Worse;
9405+
return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size();
94149406

94159407
std::pair<CPUSpecificAttr::cpus_iterator, CPUSpecificAttr::cpus_iterator>
94169408
FirstDiff = std::mismatch(
@@ -9423,9 +9415,7 @@ isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
94239415
assert(FirstDiff.first != Cand1CPUSpec->cpus_end() &&
94249416
"Two different cpu-specific versions should not have the same "
94259417
"identifier list, otherwise they'd be the same decl!");
9426-
return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName()
9427-
? Comparison::Better
9428-
: Comparison::Worse;
9418+
return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName();
94299419
}
94309420
llvm_unreachable("No way to get here unless both had cpu_dispatch");
94319421
}
@@ -9485,50 +9475,6 @@ bool clang::isBetterOverloadCandidate(
94859475
else if (!Cand1.Viable)
94869476
return false;
94879477

9488-
// [CUDA] A function with 'never' preference is marked not viable, therefore
9489-
// is never shown up here. The worst preference shown up here is 'wrong side',
9490-
// e.g. a host function called by a device host function in device
9491-
// compilation. This is valid AST as long as the host device function is not
9492-
// emitted, e.g. it is an inline function which is called only by a host
9493-
// function. A deferred diagnostic will be triggered if it is emitted.
9494-
// However a wrong-sided function is still a viable candidate here.
9495-
//
9496-
// If Cand1 can be emitted and Cand2 cannot be emitted in the current
9497-
// context, Cand1 is better than Cand2. If Cand1 can not be emitted and Cand2
9498-
// can be emitted, Cand1 is not better than Cand2. This rule should have
9499-
// precedence over other rules.
9500-
//
9501-
// If both Cand1 and Cand2 can be emitted, or neither can be emitted, then
9502-
// other rules should be used to determine which is better. This is because
9503-
// host/device based overloading resolution is mostly for determining
9504-
// viability of a function. If two functions are both viable, other factors
9505-
// should take precedence in preference, e.g. the standard-defined preferences
9506-
// like argument conversion ranks or enable_if partial-ordering. The
9507-
// preference for pass-object-size parameters is probably most similar to a
9508-
// type-based-overloading decision and so should take priority.
9509-
//
9510-
// If other rules cannot determine which is better, CUDA preference will be
9511-
// used again to determine which is better.
9512-
//
9513-
// TODO: Currently IdentifyCUDAPreference does not return correct values
9514-
// for functions called in global variable initializers due to missing
9515-
// correct context about device/host. Therefore we can only enforce this
9516-
// rule when there is a caller. We should enforce this rule for functions
9517-
// in global variable initializers once proper context is added.
9518-
if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
9519-
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext)) {
9520-
auto P1 = S.IdentifyCUDAPreference(Caller, Cand1.Function);
9521-
auto P2 = S.IdentifyCUDAPreference(Caller, Cand2.Function);
9522-
assert(P1 != Sema::CFP_Never && P2 != Sema::CFP_Never);
9523-
auto Cand1Emittable = P1 > Sema::CFP_WrongSide;
9524-
auto Cand2Emittable = P2 > Sema::CFP_WrongSide;
9525-
if (Cand1Emittable && !Cand2Emittable)
9526-
return true;
9527-
if (!Cand1Emittable && Cand2Emittable)
9528-
return false;
9529-
}
9530-
}
9531-
95329478
// C++ [over.match.best]p1:
95339479
//
95349480
// -- if F is a static member function, ICS1(F) is defined such
@@ -9763,29 +9709,20 @@ bool clang::isBetterOverloadCandidate(
97639709
return Cmp == Comparison::Better;
97649710
}
97659711

9712+
if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
9713+
FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
9714+
return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
9715+
S.IdentifyCUDAPreference(Caller, Cand2.Function);
9716+
}
9717+
97669718
bool HasPS1 = Cand1.Function != nullptr &&
97679719
functionHasPassObjectSizeParams(Cand1.Function);
97689720
bool HasPS2 = Cand2.Function != nullptr &&
97699721
functionHasPassObjectSizeParams(Cand2.Function);
97709722
if (HasPS1 != HasPS2 && HasPS1)
97719723
return true;
97729724

9773-
auto MV = isBetterMultiversionCandidate(Cand1, Cand2);
9774-
if (MV == Comparison::Better)
9775-
return true;
9776-
if (MV == Comparison::Worse)
9777-
return false;
9778-
9779-
// If other rules cannot determine which is better, CUDA preference is used
9780-
// to determine which is better.
9781-
if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
9782-
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext)) {
9783-
return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
9784-
S.IdentifyCUDAPreference(Caller, Cand2.Function);
9785-
}
9786-
}
9787-
9788-
return false;
9725+
return isBetterMultiversionCandidate(Cand1, Cand2);
97899726
}
97909727

97919728
/// Determine whether two declarations are "equivalent" for the purposes of
@@ -9871,6 +9808,33 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
98719808
std::transform(begin(), end(), std::back_inserter(Candidates),
98729809
[](OverloadCandidate &Cand) { return &Cand; });
98739810

9811+
// [CUDA] HD->H or HD->D calls are technically not allowed by CUDA but
9812+
// are accepted by both clang and NVCC. However, during a particular
9813+
// compilation mode only one call variant is viable. We need to
9814+
// exclude non-viable overload candidates from consideration based
9815+
// only on their host/device attributes. Specifically, if one
9816+
// candidate call is WrongSide and the other is SameSide, we ignore
9817+
// the WrongSide candidate.
9818+
if (S.getLangOpts().CUDA) {
9819+
const FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
9820+
bool ContainsSameSideCandidate =
9821+
llvm::any_of(Candidates, [&](OverloadCandidate *Cand) {
9822+
// Check viable function only.
9823+
return Cand->Viable && Cand->Function &&
9824+
S.IdentifyCUDAPreference(Caller, Cand->Function) ==
9825+
Sema::CFP_SameSide;
9826+
});
9827+
if (ContainsSameSideCandidate) {
9828+
auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) {
9829+
// Check viable function only to avoid unnecessary data copying/moving.
9830+
return Cand->Viable && Cand->Function &&
9831+
S.IdentifyCUDAPreference(Caller, Cand->Function) ==
9832+
Sema::CFP_WrongSide;
9833+
};
9834+
llvm::erase_if(Candidates, IsWrongSideCandidate);
9835+
}
9836+
}
9837+
98749838
// Find the best viable function.
98759839
Best = end();
98769840
for (auto *Cand : Candidates) {

clang/test/SemaCUDA/function-overload.cu

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,9 @@ __device__ void test_device_calls_template_fn() {
331331
// If we have a mix of HD and H-only or D-only candidates in the overload set,
332332
// normal C++ overload resolution rules apply first.
333333
template <typename T> TemplateReturnTy template_vs_hd_function(T arg)
334+
#ifdef __CUDA_ARCH__
335+
//expected-note@-2 {{declared here}}
336+
#endif
334337
{
335338
return TemplateReturnTy();
336339
}
@@ -339,13 +342,11 @@ __host__ __device__ HostDeviceReturnTy template_vs_hd_function(float arg) {
339342
}
340343

341344
__host__ __device__ void test_host_device_calls_hd_template() {
345+
HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
346+
TemplateReturnTy ret2 = template_vs_hd_function(1);
342347
#ifdef __CUDA_ARCH__
343-
typedef HostDeviceReturnTy ExpectedReturnTy;
344-
#else
345-
typedef TemplateReturnTy ExpectedReturnTy;
348+
// expected-error@-2 {{reference to __host__ function 'template_vs_hd_function<int>' in __host__ __device__ function}}
346349
#endif
347-
HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
348-
ExpectedReturnTy ret2 = template_vs_hd_function(1);
349350
}
350351

351352
__host__ void test_host_calls_hd_template() {
@@ -366,14 +367,14 @@ __device__ void test_device_calls_hd_template() {
366367
__device__ DeviceReturnTy device_only_function(int arg) { return DeviceReturnTy(); }
367368
__device__ DeviceReturnTy2 device_only_function(float arg) { return DeviceReturnTy2(); }
368369
#ifndef __CUDA_ARCH__
369-
// expected-note@-3 2{{'device_only_function' declared here}}
370-
// expected-note@-3 2{{'device_only_function' declared here}}
370+
// expected-note@-3 {{'device_only_function' declared here}}
371+
// expected-note@-3 {{'device_only_function' declared here}}
371372
#endif
372373
__host__ HostReturnTy host_only_function(int arg) { return HostReturnTy(); }
373374
__host__ HostReturnTy2 host_only_function(float arg) { return HostReturnTy2(); }
374375
#ifdef __CUDA_ARCH__
375-
// expected-note@-3 2{{'host_only_function' declared here}}
376-
// expected-note@-3 2{{'host_only_function' declared here}}
376+
// expected-note@-3 {{'host_only_function' declared here}}
377+
// expected-note@-3 {{'host_only_function' declared here}}
377378
#endif
378379

379380
__host__ __device__ void test_host_device_single_side_overloading() {
@@ -391,37 +392,6 @@ __host__ __device__ void test_host_device_single_side_overloading() {
391392
#endif
392393
}
393394

394-
// wrong-sided overloading should not cause diagnostic unless it is emitted.
395-
// This inline function is not emitted.
396-
inline __host__ __device__ void test_host_device_wrong_side_overloading_inline_no_diag() {
397-
DeviceReturnTy ret1 = device_only_function(1);
398-
DeviceReturnTy2 ret2 = device_only_function(1.0f);
399-
HostReturnTy ret3 = host_only_function(1);
400-
HostReturnTy2 ret4 = host_only_function(1.0f);
401-
}
402-
403-
// wrong-sided overloading should cause diagnostic if it is emitted.
404-
// This inline function is emitted since it is called by an emitted function.
405-
inline __host__ __device__ void test_host_device_wrong_side_overloading_inline_diag() {
406-
DeviceReturnTy ret1 = device_only_function(1);
407-
DeviceReturnTy2 ret2 = device_only_function(1.0f);
408-
#ifndef __CUDA_ARCH__
409-
// expected-error@-3 {{reference to __device__ function 'device_only_function' in __host__ __device__ function}}
410-
// expected-error@-3 {{reference to __device__ function 'device_only_function' in __host__ __device__ function}}
411-
#endif
412-
HostReturnTy ret3 = host_only_function(1);
413-
HostReturnTy2 ret4 = host_only_function(1.0f);
414-
#ifdef __CUDA_ARCH__
415-
// expected-error@-3 {{reference to __host__ function 'host_only_function' in __host__ __device__ function}}
416-
// expected-error@-3 {{reference to __host__ function 'host_only_function' in __host__ __device__ function}}
417-
#endif
418-
}
419-
420-
__host__ __device__ void test_host_device_wrong_side_overloading_inline_diag_caller() {
421-
test_host_device_wrong_side_overloading_inline_diag();
422-
// expected-note@-1 {{called by 'test_host_device_wrong_side_overloading_inline_diag_caller'}}
423-
}
424-
425395
// Verify that we allow overloading function templates.
426396
template <typename T> __host__ T template_overload(const T &a) { return a; };
427397
template <typename T> __device__ T template_overload(const T &a) { return a; };

0 commit comments

Comments
 (0)