mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-02 07:06:33 +00:00
[Sema] Improve diagnostic about addr spaces for overload candidates
Allow sending address spaces into diagnostics to simplify and improve error reporting. Improved wording of diagnostics for address spaces in overloading. Tags: #clang Differential Revision: https://reviews.llvm.org/D71111
This commit is contained in:
parent
be15dfa88f
commit
ed8dadb37c
@ -553,6 +553,8 @@ public:
|
||||
std::string getAsString() const;
|
||||
std::string getAsString(const PrintingPolicy &Policy) const;
|
||||
|
||||
static std::string getAddrSpaceAsString(LangAS AS);
|
||||
|
||||
bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const;
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool appendSpaceIfNonEmpty = false) const;
|
||||
@ -6838,6 +6840,23 @@ inline const Type *Type::getPointeeOrArrayElementType() const {
|
||||
return type->getBaseElementTypeUnsafe();
|
||||
return type;
|
||||
}
|
||||
/// Insertion operator for diagnostics. This allows sending address spaces into
|
||||
/// a diagnostic with <<.
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
LangAS AS) {
|
||||
DB.AddTaggedVal(static_cast<std::underlying_type_t<LangAS>>(AS),
|
||||
DiagnosticsEngine::ArgumentKind::ak_addrspace);
|
||||
return DB;
|
||||
}
|
||||
|
||||
/// Insertion operator for partial diagnostics. This allows sending adress
|
||||
/// spaces into a diagnostic with <<.
|
||||
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
LangAS AS) {
|
||||
PD.AddTaggedVal(static_cast<std::underlying_type_t<LangAS>>(AS),
|
||||
DiagnosticsEngine::ArgumentKind::ak_addrspace);
|
||||
return PD;
|
||||
}
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending Qualifiers into a
|
||||
/// diagnostic with <<.
|
||||
|
@ -177,6 +177,9 @@ public:
|
||||
/// IdentifierInfo
|
||||
ak_identifierinfo,
|
||||
|
||||
/// address space
|
||||
ak_addrspace,
|
||||
|
||||
/// Qualifiers
|
||||
ak_qual,
|
||||
|
||||
|
@ -3987,8 +3987,12 @@ def note_ovl_candidate_bad_lvalue : Note<
|
||||
"%select{%ordinal4 argument|object argument}3">;
|
||||
def note_ovl_candidate_bad_addrspace : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
|
||||
"address space mismatch in %select{%ordinal6|'this'}5 argument (%3), "
|
||||
"parameter type must be %4">;
|
||||
"cannot %select{pass pointer to|bind reference in}5 %3 "
|
||||
"%select{as a pointer to|to object in}5 %4 in %ordinal6 "
|
||||
"argument">;
|
||||
def note_ovl_candidate_bad_addrspace_this : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
|
||||
"'this' object is in %3, but method expects object in %4">;
|
||||
def note_ovl_candidate_bad_gc : Note<
|
||||
"candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: "
|
||||
"%select{%ordinal7|'this'}6 argument (%3) has %select{no|__weak|__strong}4 "
|
||||
|
@ -338,6 +338,21 @@ void clang::FormatASTNodeDiagnosticArgument(
|
||||
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("unknown ArgumentKind");
|
||||
case DiagnosticsEngine::ak_addrspace: {
|
||||
assert(Modifier.empty() && Argument.empty() &&
|
||||
"Invalid modifier for Qualfiers argument");
|
||||
|
||||
auto S = Qualifiers::getAddrSpaceAsString(static_cast<LangAS>(Val));
|
||||
if (S.empty()) {
|
||||
OS << (Context.getLangOpts().OpenCL ? "default" : "generic");
|
||||
OS << " address space";
|
||||
} else {
|
||||
OS << "address space";
|
||||
OS << " '" << S << "'";
|
||||
}
|
||||
NeedQuotes = false;
|
||||
break;
|
||||
}
|
||||
case DiagnosticsEngine::ak_qual: {
|
||||
assert(Modifier.empty() && Argument.empty() &&
|
||||
"Invalid modifier for Qualfiers argument");
|
||||
@ -348,7 +363,7 @@ void clang::FormatASTNodeDiagnosticArgument(
|
||||
OS << "unqualified";
|
||||
NeedQuotes = false;
|
||||
} else {
|
||||
OS << Q.getAsString();
|
||||
OS << S;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1772,6 +1772,31 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
|
||||
switch (AS) {
|
||||
case LangAS::Default:
|
||||
return "";
|
||||
case LangAS::opencl_global:
|
||||
return "__global";
|
||||
case LangAS::opencl_local:
|
||||
return "__local";
|
||||
case LangAS::opencl_private:
|
||||
return "";
|
||||
case LangAS::opencl_constant:
|
||||
return "__constant";
|
||||
case LangAS::opencl_generic:
|
||||
return "__generic";
|
||||
case LangAS::cuda_device:
|
||||
return "__device__";
|
||||
case LangAS::cuda_constant:
|
||||
return "__constant__";
|
||||
case LangAS::cuda_shared:
|
||||
return "__shared__";
|
||||
default:
|
||||
return std::to_string(toTargetAddressSpace(AS));
|
||||
}
|
||||
}
|
||||
|
||||
// Appends qualifiers to the given string, separated by spaces. Will
|
||||
// prefix a space if the string is non-empty. Will not append a final
|
||||
// space.
|
||||
@ -1790,43 +1815,18 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
|
||||
OS << "__unaligned";
|
||||
addSpace = true;
|
||||
}
|
||||
LangAS addrspace = getAddressSpace();
|
||||
if (addrspace != LangAS::Default) {
|
||||
if (addrspace != LangAS::opencl_private) {
|
||||
if (addSpace)
|
||||
OS << ' ';
|
||||
addSpace = true;
|
||||
switch (addrspace) {
|
||||
case LangAS::opencl_global:
|
||||
OS << "__global";
|
||||
break;
|
||||
case LangAS::opencl_local:
|
||||
OS << "__local";
|
||||
break;
|
||||
case LangAS::opencl_private:
|
||||
break;
|
||||
case LangAS::opencl_constant:
|
||||
OS << "__constant";
|
||||
break;
|
||||
case LangAS::opencl_generic:
|
||||
OS << "__generic";
|
||||
break;
|
||||
case LangAS::cuda_device:
|
||||
OS << "__device__";
|
||||
break;
|
||||
case LangAS::cuda_constant:
|
||||
OS << "__constant__";
|
||||
break;
|
||||
case LangAS::cuda_shared:
|
||||
OS << "__shared__";
|
||||
break;
|
||||
default:
|
||||
OS << "__attribute__((address_space(";
|
||||
OS << toTargetAddressSpace(addrspace);
|
||||
OS << ")))";
|
||||
}
|
||||
}
|
||||
auto ASStr = getAddrSpaceAsString(getAddressSpace());
|
||||
if (!ASStr.empty()) {
|
||||
if (addSpace)
|
||||
OS << ' ';
|
||||
addSpace = true;
|
||||
// Wrap target address space into an attribute syntax
|
||||
if (isTargetAddressSpace(getAddressSpace()))
|
||||
OS << "__attribute__((address_space(" << ASStr << ")))";
|
||||
else
|
||||
OS << ASStr;
|
||||
}
|
||||
|
||||
if (Qualifiers::GC gc = getObjCGCAttr()) {
|
||||
if (addSpace)
|
||||
OS << ' ';
|
||||
|
@ -982,6 +982,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
|
||||
llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
|
||||
break;
|
||||
}
|
||||
case DiagnosticsEngine::ak_addrspace:
|
||||
case DiagnosticsEngine::ak_qual:
|
||||
case DiagnosticsEngine::ak_qualtype:
|
||||
case DiagnosticsEngine::ak_declarationname:
|
||||
|
@ -10013,10 +10013,17 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
|
||||
Qualifiers ToQs = CToTy.getQualifiers();
|
||||
|
||||
if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
|
||||
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
|
||||
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
|
||||
<< ToTy << (unsigned)isObjectArgument << I + 1;
|
||||
if (isObjectArgument)
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace_this)
|
||||
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
|
||||
<< FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
|
||||
<< FromQs.getAddressSpace() << ToQs.getAddressSpace();
|
||||
else
|
||||
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
|
||||
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
|
||||
<< FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
|
||||
<< FromQs.getAddressSpace() << ToQs.getAddressSpace()
|
||||
<< ToTy->isReferenceType() << I + 1;
|
||||
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
|
||||
return;
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
typedef int __attribute__((address_space(1))) int_1;
|
||||
typedef int __attribute__((address_space(2))) int_2;
|
||||
|
||||
void f0(int_1 &); // expected-note{{candidate function not viable: address space mismatch in 1st argument ('int'), parameter type must be 'int_1 &' (aka '__attribute__((address_space(1))) int &')}} \
|
||||
// expected-note{{candidate function not viable: address space mismatch in 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')), parameter type must be 'int_1 &' (aka '__attribute__((address_space(1))) int &')}}
|
||||
void f0(const int_1 &); // expected-note{{candidate function not viable: address space mismatch in 1st argument ('int'), parameter type must be 'const int_1 &' (aka 'const __attribute__((address_space(1))) int &')}} \
|
||||
// expected-note{{candidate function not viable: address space mismatch in 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')), parameter type must be 'const int_1 &' (aka 'const __attribute__((address_space(1))) int &')}}
|
||||
void f0(int_1 &); // expected-note{{candidate function not viable: cannot bind reference in generic address space to object in address space '1' in 1st argument}} \
|
||||
// expected-note{{candidate function not viable: cannot bind reference in address space '2' to object in address space '1' in 1st argument}}
|
||||
void f0(const int_1 &); // expected-note{{candidate function not viable: cannot bind reference in generic address space to object in address space '1' in 1st argument}} \
|
||||
// expected-note{{candidate function not viable: cannot bind reference in address space '2' to object in address space '1' in 1st argument}}
|
||||
|
||||
void test_f0() {
|
||||
int i;
|
||||
|
@ -42,7 +42,7 @@ void f_glob(__global int *arg_glob) {}
|
||||
#if !__OPENCL_CPP_VERSION__
|
||||
// expected-note@-3{{passing argument to parameter 'arg_glob' here}}
|
||||
#else
|
||||
// expected-note-re@-5{{candidate function not viable: address space mismatch in 1st argument ('__{{generic|constant}} int *'), parameter type must be '__global int *'}}
|
||||
// expected-note-re@-5{{candidate function not viable: cannot pass pointer to address space '__{{generic|constant}}' as a pointer to address space '__global' in 1st argument}}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -50,7 +50,7 @@ void f_loc(__local int *arg_loc) {}
|
||||
#if !__OPENCL_CPP_VERSION__
|
||||
// expected-note@-2{{passing argument to parameter 'arg_loc' here}}
|
||||
#else
|
||||
// expected-note-re@-4{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic|constant}} int *'), parameter type must be '__local int *'}}
|
||||
// expected-note-re@-4{{candidate function not viable: cannot pass pointer to address space '__{{global|generic|constant}}' as a pointer to address space '__local' in 1st argument}}
|
||||
#endif
|
||||
|
||||
void f_const(__constant int *arg_const) {}
|
||||
@ -58,7 +58,7 @@ void f_const(__constant int *arg_const) {}
|
||||
#if !__OPENCL_CPP_VERSION__
|
||||
// expected-note@-3{{passing argument to parameter 'arg_const' here}}
|
||||
#else
|
||||
// expected-note-re@-5{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic}} int *'), parameter type must be '__constant int *'}}
|
||||
// expected-note-re@-5{{candidate function not viable: cannot pass pointer to address space '__{{global|generic}}' as a pointer to address space '__constant' in 1st argument}}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -66,7 +66,7 @@ void f_priv(__private int *arg_priv) {}
|
||||
#if !__OPENCL_CPP_VERSION__
|
||||
// expected-note@-2{{passing argument to parameter 'arg_priv' here}}
|
||||
#else
|
||||
// expected-note-re@-4{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic|constant}} int *'), parameter type must be 'int *'}}
|
||||
// expected-note-re@-4{{candidate function not viable: cannot pass pointer to address space '__{{global|generic|constant}}' as a pointer to default address space in 1st argument}}
|
||||
#endif
|
||||
|
||||
void f_gen(__generic int *arg_gen) {}
|
||||
@ -74,7 +74,7 @@ void f_gen(__generic int *arg_gen) {}
|
||||
#if !__OPENCL_CPP_VERSION__
|
||||
// expected-note@-3{{passing argument to parameter 'arg_gen' here}}
|
||||
#else
|
||||
// expected-note@-5{{candidate function not viable: address space mismatch in 1st argument ('__constant int *'), parameter type must be '__generic int *'}}
|
||||
// expected-note@-5{{candidate function not viable: cannot pass pointer to address space '__constant' as a pointer to address space '__generic' in 1st argument}}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -12,7 +12,7 @@ __kernel void test() {
|
||||
// Test lambda with default parameters
|
||||
//CHECK: CXXMethodDecl {{.*}} constexpr operator() 'void () const __generic'
|
||||
[&] {i++;} ();
|
||||
__constant auto err = [&]() {}; //expected-note-re{{candidate function not viable: address space mismatch in 'this' argument ('__constant (lambda at {{.*}})'), parameter type must be 'const __generic (lambda at {{.*}})'}}
|
||||
__constant auto err = [&]() {}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__generic'}}
|
||||
err(); //expected-error-re{{no matching function for call to object of type '__constant (lambda at {{.*}})'}}
|
||||
// FIXME: There is very limited addr space functionality
|
||||
// we can test when taking lambda type from the object.
|
||||
@ -31,19 +31,19 @@ __kernel void test_qual() {
|
||||
//CHECK: |-CXXMethodDecl {{.*}} constexpr operator() 'void () const __generic'
|
||||
auto priv2 = []() __generic {};
|
||||
priv2();
|
||||
auto priv3 = []() __global {}; //expected-note-re{{candidate function not viable: address space mismatch in 'this' argument ('(lambda at {{.*}})'), parameter type must be 'const __global (lambda at {{.*}})'}} //expected-note{{conversion candidate of type 'void (*)()'}}
|
||||
auto priv3 = []() __global {}; //expected-note{{candidate function not viable: 'this' object is in default address space, but method expects object in address space '__global'}} //expected-note{{conversion candidate of type 'void (*)()'}}
|
||||
priv3(); //expected-error{{no matching function for call to object of type}}
|
||||
|
||||
__constant auto const1 = []() __private{}; //expected-note-re{{candidate function not viable: address space mismatch in 'this' argument ('__constant (lambda at {{.*}})'), parameter type must be 'const (lambda at {{.*}}'}} //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 default address space}} //expected-note{{conversion candidate of type 'void (*)()'}}
|
||||
const1(); //expected-error{{no matching function for call to object of type '__constant (lambda at}}
|
||||
__constant auto const2 = []() __generic{}; //expected-note-re{{candidate function not viable: address space mismatch in 'this' argument ('__constant (lambda at {{.*}})'), parameter type must be 'const __generic (lambda at {{.*}}'}} //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'}} //expected-note{{conversion candidate of type 'void (*)()'}}
|
||||
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{};
|
||||
const3();
|
||||
|
||||
[&] () __global {} (); //expected-error{{no matching function for call to object of type '(lambda at}} expected-note-re{{candidate function not viable: address space mismatch in 'this' argument ('(lambda at {{.*}})'), parameter type must be 'const __global (lambda at {{.*}})'}}
|
||||
[&] () __private {} (); //expected-error{{no matching function for call to object of type '(lambda at}} expected-note-re{{candidate function not viable: address space mismatch in 'this' argument ('(lambda at {{.*}})'), parameter type must be 'const (lambda at {{.*}})'}}
|
||||
[&] () __global {} (); //expected-error{{no matching function for call to object of type '(lambda at}} expected-note{{candidate function not viable: 'this' object is in default address space, but method expects object in address space '__global'}}
|
||||
[&] () __private {} (); //expected-error{{no matching function for call to object of type '(lambda at}} expected-note{{candidate function not viable: 'this' object is in default address space, but method expects object in default address space}}
|
||||
|
||||
[&] __private {} (); //expected-error{{lambda requires '()' before attribute specifier}} expected-error{{expected body of lambda expression}}
|
||||
|
||||
|
@ -7,8 +7,8 @@ struct C {
|
||||
};
|
||||
|
||||
void bar(__local C*);
|
||||
// expected-note@-1{{candidate function not viable: address space mismatch in 1st argument ('decltype(this)' (aka '__global C *')), parameter type must be '__local C *'}}
|
||||
// expected-note@-2{{candidate function not viable: address space mismatch in 1st argument ('decltype(this)' (aka 'C *')), parameter type must be '__local C *'}}
|
||||
// expected-note@-1{{candidate function not viable: cannot pass pointer to address space '__global' as a pointer to address space '__local' in 1st argument}}
|
||||
// expected-note@-2{{candidate function not viable: cannot pass pointer to default address space as a pointer to address space '__local' in 1st argument}}
|
||||
|
||||
__global C Glob;
|
||||
void foo(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user