[clang] ed8dadb - [Sema] Improve diagnostic about addr spaces for overload candidates
Anastasia Stulova via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 13 04:35:48 PST 2019
Author: Anastasia Stulova
Date: 2019-12-13T12:35:18Z
New Revision: ed8dadb37c7e1a7f4889d868ac9b19bfe7762237
URL: https://github.com/llvm/llvm-project/commit/ed8dadb37c7e1a7f4889d868ac9b19bfe7762237
DIFF: https://github.com/llvm/llvm-project/commit/ed8dadb37c7e1a7f4889d868ac9b19bfe7762237.diff
LOG: [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
Added:
Modified:
clang/include/clang/AST/Type.h
clang/include/clang/Basic/Diagnostic.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/ASTDiagnostic.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/Basic/Diagnostic.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/SemaCXX/address-space-references.cpp
clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
clang/test/SemaOpenCLCXX/address-space-lambda.cl
clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index caf2a3dd79a3..6d1d69bd87a2 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -553,6 +553,8 @@ class Qualifiers {
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 <<.
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index 94ae011a0b20..ce996b615bba 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -177,6 +177,9 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
/// IdentifierInfo
ak_identifierinfo,
+ /// address space
+ ak_addrspace,
+
/// Qualifiers
ak_qual,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c91ef356f944..b91fd262c9d3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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 "
diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp
index 30985441031d..8ff3cebb1d83 100644
--- a/clang/lib/AST/ASTDiagnostic.cpp
+++ b/clang/lib/AST/ASTDiagnostic.cpp
@@ -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;
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 1065b99e0ce3..a26daabd8f1a 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -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 << ' ';
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index f686b6953e30..f258b37f2fa6 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -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:
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5b1394d7b34f..9aa338935502 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -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;
}
diff --git a/clang/test/SemaCXX/address-space-references.cpp b/clang/test/SemaCXX/address-space-references.cpp
index 5c297e76c41a..f79ffab2bd14 100644
--- a/clang/test/SemaCXX/address-space-references.cpp
+++ b/clang/test/SemaCXX/address-space-references.cpp
@@ -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;
diff --git a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
index 89cf8e3a8124..a97565f3a2e5 100644
--- a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
+++ b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
@@ -42,7 +42,7 @@ void f_glob(__global int *arg_glob) {}
#if !__OPENCL_CPP_VERSION__
// expected-note at -3{{passing argument to parameter 'arg_glob' here}}
#else
-// expected-note-re at -5{{candidate function not viable: address space mismatch in 1st argument ('__{{generic|constant}} int *'), parameter type must be '__global int *'}}
+// expected-note-re at -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 at -2{{passing argument to parameter 'arg_loc' here}}
#else
-// expected-note-re at -4{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic|constant}} int *'), parameter type must be '__local int *'}}
+// expected-note-re at -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 at -3{{passing argument to parameter 'arg_const' here}}
#else
-// expected-note-re at -5{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic}} int *'), parameter type must be '__constant int *'}}
+// expected-note-re at -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 at -2{{passing argument to parameter 'arg_priv' here}}
#else
-// expected-note-re at -4{{candidate function not viable: address space mismatch in 1st argument ('__{{global|generic|constant}} int *'), parameter type must be 'int *'}}
+// expected-note-re at -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 at -3{{passing argument to parameter 'arg_gen' here}}
#else
-// expected-note at -5{{candidate function not viable: address space mismatch in 1st argument ('__constant int *'), parameter type must be '__generic int *'}}
+// expected-note at -5{{candidate function not viable: cannot pass pointer to address space '__constant' as a pointer to address space '__generic' in 1st argument}}
#endif
#endif
diff --git a/clang/test/SemaOpenCLCXX/address-space-lambda.cl b/clang/test/SemaOpenCLCXX/address-space-lambda.cl
index cf87bfaeede2..7110afaee1ee 100644
--- a/clang/test/SemaOpenCLCXX/address-space-lambda.cl
+++ b/clang/test/SemaOpenCLCXX/address-space-lambda.cl
@@ -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}}
diff --git a/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl b/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl
index 1c0cb3731bd5..86d839d9701b 100644
--- a/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl
+++ b/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl
@@ -7,8 +7,8 @@ struct C {
};
void bar(__local C*);
-// expected-note at -1{{candidate function not viable: address space mismatch in 1st argument ('decltype(this)' (aka '__global C *')), parameter type must be '__local C *'}}
-// expected-note at -2{{candidate function not viable: address space mismatch in 1st argument ('decltype(this)' (aka 'C *')), parameter type must be '__local C *'}}
+// expected-note at -1{{candidate function not viable: cannot pass pointer to address space '__global' as a pointer to address space '__local' in 1st argument}}
+// expected-note at -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(){
More information about the cfe-commits
mailing list