Update 'note-candiate' functions to skip lambda-conversion-op-overloads

In the wake of https://reviews.llvm.org/D89559, we discovered that a
couple of tests (the ones modified below to have additional triple
versions) would fail on Win32, for 1 of two reasons.  We seem to not
have a win32 buildbot anymore, so the triple is to make sure this
doesn't get broken in the future.

First, two of the three 'note-candidate' functions weren't appropriately
skipping the remaining conversion functions.

Second, in 1 situation (note surrogate candidates) we actually print the
type of the conversion operator.  The two tests that ran into that
needed updating to make sure it printed the proper one in the win32
case.
This commit is contained in:
Erich Keane 2020-11-16 15:26:22 -08:00
parent f571fe6df5
commit 6976fef05b
7 changed files with 51 additions and 24 deletions

View File

@ -10217,6 +10217,27 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
Loc);
}
// Don't print candidates other than the one that matches the calling
// convention of the call operator, since that is guaranteed to exist.
static bool shouldSkipNotingLambdaConversionDecl(FunctionDecl *Fn) {
const auto *ConvD = dyn_cast<CXXConversionDecl>(Fn);
if (!ConvD)
return false;
const auto *RD = cast<CXXRecordDecl>(Fn->getParent());
if (!RD->isLambda())
return false;
CXXMethodDecl *CallOp = RD->getLambdaCallOperator();
CallingConv CallOpCC =
CallOp->getType()->getAs<FunctionType>()->getCallConv();
QualType ConvRTy = ConvD->getType()->getAs<FunctionType>()->getReturnType();
CallingConv ConvToCC =
ConvRTy->getPointeeType()->getAs<FunctionType>()->getCallConv();
return ConvToCC != CallOpCC;
}
// Notes the location of an overload candidate.
void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
OverloadCandidateRewriteKind RewriteKind,
@ -10226,22 +10247,8 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
!Fn->getAttr<TargetAttr>()->isDefaultVersion())
return;
if (isa<CXXConversionDecl>(Fn) &&
cast<CXXRecordDecl>(Fn->getParent())->isLambda()) {
// Don't print candidates other than the one that matches the calling
// convention of the call operator, since that is guaranteed to exist.
const auto *RD = cast<CXXRecordDecl>(Fn->getParent());
CXXMethodDecl *CallOp = RD->getLambdaCallOperator();
CallingConv CallOpCC =
CallOp->getType()->getAs<FunctionType>()->getCallConv();
CXXConversionDecl *ConvD = cast<CXXConversionDecl>(Fn);
QualType ConvRTy = ConvD->getType()->getAs<FunctionType>()->getReturnType();
CallingConv ConvToCC =
ConvRTy->getPointeeType()->getAs<FunctionType>()->getCallConv();
if (ConvToCC != CallOpCC)
return;
}
if (shouldSkipNotingLambdaConversionDecl(Fn))
return;
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair =
@ -11101,6 +11108,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
bool TakingCandidateAddress,
LangAS CtorDestAS = LangAS::Default) {
FunctionDecl *Fn = Cand->Function;
if (shouldSkipNotingLambdaConversionDecl(Fn))
return;
// Note deleted candidates, but only if they're viable.
if (Cand->Viable) {
@ -11217,6 +11226,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
}
static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
if (shouldSkipNotingLambdaConversionDecl(Cand->Surrogate))
return;
// Desugar the type of the surrogate down to a function type,
// retaining as many typedefs as possible while still showing
// the function type (and, therefore, its parameter types).

View File

@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify=expected,nowin32
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify=expected,win32 -triple i386-windows
void defargs() {
auto l1 = [](int i, int j = 17, int k = 18) { return i + j + k; };
@ -9,8 +10,8 @@ void defargs() {
void defargs_errors() {
auto l1 = [](int i,
int j = 17,
auto l1 = [](int i,
int j = 17,
int k) { }; // expected-error{{missing default argument on parameter 'k'}}
auto l2 = [](int i, int j = i) {}; // expected-error{{default argument references parameter 'i'}}
@ -44,7 +45,8 @@ template<typename T>
void defargs_in_template_used() {
auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} \
// expected-note{{candidate function not viable: requires single argument 'value', but no arguments were provided}} \
// expected-note{{conversion candidate of type 'void (*)(const NoDefaultCtor &)'}}
// nowin32-note{{conversion candidate of type 'void (*)(const NoDefaultCtor &)'}}\
// win32-note{{conversion candidate of type 'void (*)(const NoDefaultCtor &) __attribute__((thiscall))'}}
l1(); // expected-error{{no matching function for call to object of type '(lambda at }}
}

View File

@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
// RUN: %clang_cc1 -fsyntax-only -std=c++1z %s -verify
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -triple i386-windows-pc -verify
// RUN: %clang_cc1 -fsyntax-only -std=c++1z %s -triple i386-windows-pc -verify
void test_conversion() {
int (*fp1)(int) = [](int x) { return x + 1; };

View File

@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s
// RUN: %clang_cc1 -std=c++2a -verify -fsyntax-only -fblocks -emit-llvm-only %s
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only -triple i386-windows-pc %s
// RUN: %clang_cc1 -std=c++2a -verify -fsyntax-only -fblocks -emit-llvm-only -triple i386-windows-pc %s
// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING

View File

@ -2,6 +2,10 @@
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows %s
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows -fms-extensions %s -DMS_EXTENSIONS
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
namespace explicit_argument_variadics {

View File

@ -2,6 +2,10 @@
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -emit-llvm-only %s
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -fms-extensions %s -DMS_EXTENSIONS
// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -triple i386-windows-pc -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
template<class F, class ...Rest> struct first_impl { typedef F type; };
template<class ...Args> using first = typename first_impl<Args...>::type;

View File

@ -1,4 +1,5 @@
//RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -ast-dump -verify | FileCheck %s
//RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -ast-dump -verify=expected,nowin32 | FileCheck %s
//RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -ast-dump -verify=expected,win32 -triple i386-windows | FileCheck %s
//CHECK: CXXMethodDecl {{.*}} constexpr operator() 'int (__private int){{.*}} const __generic'
auto glambda = [](auto a) { return a; };
@ -31,12 +32,12 @@ __kernel void test_qual() {
//CHECK: |-CXXMethodDecl {{.*}} constexpr operator() 'void () {{.*}}const __generic'
auto priv2 = []() __generic {};
priv2();
auto priv3 = []() __global {}; //expected-note{{candidate function not viable: 'this' object is in address space '__private', but method expects object in address space '__global'}} //expected-note{{conversion candidate of type 'void (*)()'}}
auto priv3 = []() __global {}; //expected-note{{candidate function not viable: 'this' object is in address space '__private', but method expects object in address space '__global'}} //nowin32-note{{conversion candidate of type 'void (*)()'}}//win32-note{{conversion candidate of type 'void (*)() __attribute__((thiscall))'}}
priv3(); //expected-error{{no matching function for call to object of type}}
__constant auto const1 = []() __private{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__private'}} //expected-note{{conversion candidate of type 'void (*)()'}}
__constant auto const1 = []() __private{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__private'}} //nowin32-note{{conversion candidate of type 'void (*)()'}} //win32-note{{conversion candidate of type 'void (*)() __attribute__((thiscall))'}}
const1(); //expected-error{{no matching function for call to object of type '__constant (lambda at}}
__constant auto const2 = []() __generic{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__generic'}} //expected-note{{conversion candidate of type 'void (*)()'}}
__constant auto const2 = []() __generic{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__generic'}} //nowin32-note{{conversion candidate of type 'void (*)()'}} //win32-note{{conversion candidate of type 'void (*)() __attribute__((thiscall))'}}
const2(); //expected-error{{no matching function for call to object of type '__constant (lambda at}}
//CHECK: |-CXXMethodDecl {{.*}} constexpr operator() 'void () {{.*}}const __constant'
__constant auto const3 = []() __constant{};