-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang] Emit a diagnostic note at the class declaration when the method definition does not match any declaration. #110638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: None (c8ef) ChangesFixes #110558. In this patch, we will emit a diagnostic note pointing to the class declaration when a method definition does not match any declaration. This approach, similar to what GCC does, makes the diagnostic more user-friendly. Patch is 22.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110638.diff 24 Files Affected:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0e536f71a2f70d..e4c45cbc09e0f7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9086,9 +9086,14 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
SemaRef.Diag(NewFD->getLocation(), DiagMsg)
<< Name << NewDC << IsDefinition << NewFD->getLocation();
- bool NewFDisConst = false;
- if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
- NewFDisConst = NewMD->isConst();
+ CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD);
+ if (NewMD && DiagMsg == diag::err_member_decl_does_not_match) {
+ CXXRecordDecl *RD = NewMD->getParent();
+ SemaRef.Diag(RD->getLocation(), diag::note_defined_here)
+ << RD->getName() << RD->getLocation();
+ }
+
+ bool NewFDisConst = NewMD && NewMD->isConst();
for (SmallVectorImpl<std::pair<FunctionDecl *, unsigned> >::iterator
NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
index 9e890204c78bd6..f0901733f8afeb 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
@@ -170,5 +170,6 @@ namespace ImplicitConstexprDef {
constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}}
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}}
+ // expected-note@-6 {{A defined here}}
}
#endif
diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp
index 0454412229fad7..fbd26cfd7b9db7 100644
--- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp
@@ -6,3 +6,4 @@ void A::f(enum { e2 }) {} // expected-error{{cannot be defined in a parameter}}
enum { e3 } A::g() { } // expected-error{{cannot be defined in the result type}} \
// expected-error{{out-of-line definition}}
+// expected-note@-6{{defined here}}
diff --git a/clang/test/CXX/dcl/dcl.fct/p17.cpp b/clang/test/CXX/dcl/dcl.fct/p17.cpp
index d7487233f5d5c2..34b0c9f3ce0273 100644
--- a/clang/test/CXX/dcl/dcl.fct/p17.cpp
+++ b/clang/test/CXX/dcl/dcl.fct/p17.cpp
@@ -110,6 +110,7 @@ namespace unconstrained {
template<typename U>
constexpr auto S<T>::f2(auto x, U u, T t) -> decltype(x + u + t) { return x + u + t; }
// expected-error@-1 {{out-of-line definition of 'f2' does not match any declaration in 'S<T>'}}
+ // expected-note@-14 {{S defined here}}
template<typename T>
template<typename U>
diff --git a/clang/test/CXX/drs/cwg22xx.cpp b/clang/test/CXX/drs/cwg22xx.cpp
index 797c3ed8546ef1..a16a74a43a859a 100644
--- a/clang/test/CXX/drs/cwg22xx.cpp
+++ b/clang/test/CXX/drs/cwg22xx.cpp
@@ -108,6 +108,7 @@ namespace MultilevelSpecialization {
template<> template<int a, int b>
void B<int, int>::f(int i, int (&arr1)[a], int (&arr2)[b]) {}
// since-cxx11-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}}
+ // expected-note@-6 {{defined here}}
template<> template<>
void B<int, int>::f<1, 1>(int i, int (&arr1a)[1], int (&arr2a)[1]) {}
}
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 7157feed3f7626..1ef878dab4e56a 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -600,6 +600,7 @@ namespace cwg336 { // cwg336: yes
template<> template<class X> class A<int>::B {};
template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {}
// expected-error@-1 {{out-of-line definition of 'mf1' does not match any declaration in 'cwg336::Pre::A<int>::B<double>'}}
+ // expected-note@-3 {{defined here}}
template<class Y> template<> void A<Y>::B<double>::mf2() {}
// expected-error@-1 {{nested name specifier 'A<Y>::B<double>::' for declaration does not refer into a class, class template or class template partial specialization}}
}
@@ -766,8 +767,10 @@ namespace cwg347 { // cwg347: yes
// expected-error@-1 {{no member named 'n' in 'cwg347::derived'}}
void derived::f() {}
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg347::derived'}}
+ // expected-note@-8 {{defined here}}
void derived::g() {}
// expected-error@-1 {{out-of-line definition of 'g' does not match any declaration in 'cwg347::derived'}}
+ // expected-note@-11 {{defined here}}
}
// cwg348: na
@@ -1014,13 +1017,15 @@ namespace cwg357 { // cwg357: yes
};
template<typename T> void A<T>::f() {}
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'A<T>'}}
- // expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
+ // expected-note@-5 {{defined here}}
+ // expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
struct B {
template<typename T> void f();
};
template<typename T> void B::f() const {}
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg357::B'}}
+ // expected-note@-5 {{defined here}}
}
namespace cwg358 { // cwg358: yes
diff --git a/clang/test/CXX/special/class.inhctor/p8.cpp b/clang/test/CXX/special/class.inhctor/p8.cpp
index 58c01d2b912d4a..fe17d6e44351f4 100644
--- a/clang/test/CXX/special/class.inhctor/p8.cpp
+++ b/clang/test/CXX/special/class.inhctor/p8.cpp
@@ -30,3 +30,4 @@ struct D : C {
static_assert(D(123).v == 123, "");
template<typename T> constexpr D::D(T t) : C(t) {} // expected-error {{does not match any declaration in 'D'}}
+ // expected-note@-6 {{defined here}}
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
index 30fbec64eea782..e511404ffac38c 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
@@ -55,5 +55,6 @@ struct TA {
template <unsigned N>
template <template <unsigned> class TT> int TA<N>::A() { return sizeof(TT<N>); }
// expected-error@-1{{out-of-line definition of 'A' does not match any declaration in 'TA<N>'}}
+// expected-note@-8{{defined here}}
} // end namespace diag
diff --git a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
index 56599985da06e9..4cc48e16699a6b 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
@@ -127,19 +127,19 @@ namespace SearchClassBetweenTemplateParameterLists {
template<typename T> template<typename BB>
void A<T>::B<BB>::g(BB) { // expected-error {{does not match}}
BB bb; // expected-error {{incomplete type}}
- }
+ } // expected-note@-58 {{defined here}}
// error, 'AA' found in (4)
template<typename AA> template<typename U>
void A<AA>::B<U>::h(AA) { // expected-error {{does not match}}
AA aa; // expected-error {{incomplete type}}
- }
+ } // expected-note@-64 {{defined here}}
// error, 'BB' found in (2)
template<typename BB> template<typename U>
void A<BB>::B<U>::i(BB) { // expected-error {{does not match}}
BB bb; // expected-error {{incomplete type}}
- }
+ } // expected-note@-70 {{defined here}}
// OK, 'BB' found in (1)
template<typename T> template<typename U> template<typename BB>
@@ -151,7 +151,7 @@ namespace SearchClassBetweenTemplateParameterLists {
template<typename T> template<typename BB> template<typename V>
void A<T>::B<BB>::k(V) { // expected-error {{does not match}}
BB bb; // expected-error {{incomplete type}}
- }
+ } // expected-note@-82 {{defined here}}
int CC;
template <typename> struct C;
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp
index 2a574890836956..bd36ea2318d761 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp
@@ -49,11 +49,13 @@ template<>
constexpr void B<short>::g0(); // since-cxx14-error {{constexpr declaration of 'g0' follows non-constexpr declaration}}
// cxx11-error@-1 {{out-of-line declaration of 'g0' does not match any declaration in 'B<short>'}}
// cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
+ // expected-note@-18 {{defined here}}
template<>
constexpr void B<short>::g1(); // since-cxx14-error {{out-of-line declaration of 'g1' does not match any declaration in 'B<short>'}}
// cxx11-error@-1 {{constexpr declaration of 'g1' follows non-constexpr declaration}}
// cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
+ // expected-note@-24 {{defined here}}
template<>
template<typename U>
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14-23.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14-23.cpp
index a023bf84137d78..cf800dce3a37f5 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14-23.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14-23.cpp
@@ -56,6 +56,7 @@ namespace N0 {
template<>
constexpr int A<0>::h() { return 2; } // expected-error {{out-of-line definition of 'h' does not match any declaration in 'N0::A<0>'}}
+ // expected-note@-48 {{defined here}}
static_assert(A<5>::h() == 0);
static_assert(A<4>::h() == 1);
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp
index 4d175a8860870d..390a47c8942690 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp
@@ -14,6 +14,7 @@ template<> template<> template<class T>
template<> template<> template<class T>
void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}}
+ // expected-note@-7{{defined here}}
// FIXME: This diagnostic could probably be better.
template<class Y> template<>
diff --git a/clang/test/FixIt/member-mismatch.cpp b/clang/test/FixIt/member-mismatch.cpp
index 2d2aec2e176b2b..531184933c09ab 100644
--- a/clang/test/FixIt/member-mismatch.cpp
+++ b/clang/test/FixIt/member-mismatch.cpp
@@ -8,5 +8,7 @@ class Foo {
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:15-[[@LINE+1]]:15}:" const"
int Foo::get() {} // expected-error {{does not match any declaration}}
+ // expected-note@-7 {{defined here}}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:20-[[@LINE+1]]:26}:""
void Foo::set(int) const {} // expected-error {{does not match any declaration}}
+ // expected-note@-10 {{defined here}}
diff --git a/clang/test/Parser/cxx-class.cpp b/clang/test/Parser/cxx-class.cpp
index c90c7e030a8bd5..583534afa83408 100644
--- a/clang/test/Parser/cxx-class.cpp
+++ b/clang/test/Parser/cxx-class.cpp
@@ -103,6 +103,7 @@ namespace ctor_error {
class Foo {};
// By [class.qual]p2, this is a constructor declaration.
Foo::Foo (F) = F(); // expected-error{{does not match any declaration in 'ctor_error::Foo'}}
+ // expected-note@-3{{defined here}}
class Ctor { // expected-note{{not complete until the closing '}'}}
Ctor(f)(int); // ok
diff --git a/clang/test/SemaCXX/attr-target-mv.cpp b/clang/test/SemaCXX/attr-target-mv.cpp
index 5b2f0fc825f399..004ac0469492fb 100644
--- a/clang/test/SemaCXX/attr-target-mv.cpp
+++ b/clang/test/SemaCXX/attr-target-mv.cpp
@@ -187,7 +187,8 @@ struct BadOutOfLine {
int __attribute__((target("sse4.2"))) BadOutOfLine::foo(int) { return 0; }
int __attribute__((target("default"))) BadOutOfLine::foo(int) { return 1; }
-// expected-error@+3 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
-// expected-note@-3 {{member declaration nearly matches}}
-// expected-note@-3 {{member declaration nearly matches}}
+// expected-error@+4 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
+// expected-note@-8 {{defined here}}
+// expected-note@-4 {{member declaration nearly matches}}
+// expected-note@-4 {{member declaration nearly matches}}
int __attribute__((target("arch=atom"))) BadOutOfLine::foo(int) { return 1; }
diff --git a/clang/test/SemaCXX/attr-target-version.cpp b/clang/test/SemaCXX/attr-target-version.cpp
index b3385f043590f8..c8a05e99c80ddd 100644
--- a/clang/test/SemaCXX/attr-target-version.cpp
+++ b/clang/test/SemaCXX/attr-target-version.cpp
@@ -103,7 +103,8 @@ class Out {
};
int __attribute__((target_version("bti"))) Out::func(void) { return 1; }
int __attribute__((target_version("ssbs2"))) Out::func(void) { return 2; }
-// expected-error@+3 {{out-of-line definition of 'func' does not match any declaration in 'Out'}}
-// expected-note@-3 {{member declaration nearly matches}}
-// expected-note@-3 {{member declaration nearly matches}}
+// expected-error@+4 {{out-of-line definition of 'func' does not match any declaration in 'Out'}}
+// expected-note@-2 {{member declaration nearly matches}}
+// expected-note@-4 {{member declaration nearly matches}}
+// expected-note@-9 {{defined here}}
int __attribute__((target_version("rng"))) Out::func(void) { return 3; }
diff --git a/clang/test/SemaCXX/enable_if.cpp b/clang/test/SemaCXX/enable_if.cpp
index 5eec02a643340a..1c307881e5d4a5 100644
--- a/clang/test/SemaCXX/enable_if.cpp
+++ b/clang/test/SemaCXX/enable_if.cpp
@@ -5,7 +5,7 @@ int surrogate(int);
struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} \
// expected-note {{forward declaration of 'Incomplete'}}
-struct X {
+struct X { // expected-note{{defined here}}
X() = default; // expected-note{{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
X(const X&) = default; // expected-note{{candidate constructor not viable: no known conversion from 'bool' to 'const X' for 1st argument}}
X(bool b) __attribute__((enable_if(b, "chosen when 'b' is true"))); // expected-note{{candidate disabled: chosen when 'b' is true}}
diff --git a/clang/test/SemaCXX/function-redecl.cpp b/clang/test/SemaCXX/function-redecl.cpp
index 34d2acc75430c3..8c0e9a880d070e 100644
--- a/clang/test/SemaCXX/function-redecl.cpp
+++ b/clang/test/SemaCXX/function-redecl.cpp
@@ -61,7 +61,7 @@ void B::Notypocorrection(int) { // expected-error {{out-of-line definition of 'N
}
struct X { int f(); };
-struct Y : public X {};
+struct Y : public X {}; // expected-note {{defined here}}
int Y::f() { return 3; } // expected-error {{out-of-line definition of 'f' does not match any declaration in 'Y'}}
namespace test1 {
@@ -70,7 +70,7 @@ struct Foo {
};
}
-class Bar {
+class Bar { // expected-note {{defined here}}
void f(test1::Foo::Inner foo) const; // expected-note {{member declaration does not match because it is const qualified}}
};
@@ -80,7 +80,8 @@ void Bar::f(Foo::Inner foo) { // expected-error {{out-of-line definition of 'f'
(void)foo;
}
-class Crash {
+class Crash { // expected-note {{defined here}}
+ // expected-note@-1 {{defined here}}
public:
void GetCart(int count) const;
};
@@ -89,7 +90,8 @@ void Crash::cart(int count) const {} // expected-error {{out-of-line definition
// ...while this one crashed clang
void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'}}
-class TestConst {
+class TestConst { // expected-note {{defined here}}
+ // expected-note@-1 {{defined here}}
public:
int getit() const; // expected-note {{member declaration does not match because it is const qualified}}
void setit(int); // expected-note {{member declaration does not match because it is not const qualified}}
@@ -102,7 +104,7 @@ int TestConst::getit() { // expected-error {{out-of-line definition of 'getit' d
void TestConst::setit(int) const { // expected-error {{out-of-line definition of 'setit' does not match any declaration in 'TestConst'}}
}
-struct J { int typo() const; };
+struct J { int typo() const; }; // expected-note {{defined here}}
int J::typo_() { return 3; } // expected-error {{out-of-line definition of 'typo_' does not match any declaration in 'J'}}
// Ensure we correct the redecl of Foo::isGood to Bar::Foo::isGood and not
@@ -126,7 +128,7 @@ bool Foo::isGood() { // expected-error {{out-of-line definition of 'isGood' does
void Foo::beEvil() {} // expected-error {{out-of-line definition of 'beEvil' does not match any declaration in namespace 'redecl_typo::Foo'; did you mean 'BeEvil'?}}
}
-struct CVQualFun {
+struct CVQualFun { // expected-note {{defined here}}
void func(int a, int &b); // expected-note {{type of 2nd parameter of member declaration does not match definition ('int &' vs 'int')}}
};
diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
index 39ee89bc797f84..f0ebfef029d16e 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -76,6 +76,7 @@ struct A {
template <class T>
void A<T>::spam(decltype([] {})) // expected-error{{out-of-line definition of 'spam' does not match}}
+ // expected-note@-6{{defined here}}
{}
struct B {
@@ -85,6 +86,7 @@ struct B {
template <class T>
void B::spam(decltype([] {})) {} // expected-error{{out-of-line definition of 'spam' does not match}}
+ // expected-note@-7{{defined here}}
} // namespace GH51416
diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp
index 920ef42bc15646..cd66792f4852b5 100644
--- a/clang/test/SemaCXX/nested-name-spec.cpp
+++ b/clang/test/SemaCXX/nested-name-spec.cpp
@@ -36,8 +36,10 @@ class C2 {
};
void C2::m() const { } // expected-error{{out-of-line definition of 'm' does not match any declaration in 'C2'}}
+ // expected-note@-11{{defined here}}
void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'C2'}}
+ // expected-note@-14{{defined here}}
void C2::m() {
x = 0;
@@ -128,6 +130,7 @@ class Operators {
};
Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition of 'operator+' does not match any declaration in 'Operators'}}
+ // expected-note@-6{{defined here}}
Operators ops;
return ops;
}
@@ -152,6 +155,7 @@ void A::g(const int&) { } // expected-error{{out-of-line definition of 'g' does
struct Struct { };
void Struct::f() { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'Struct'}}
+ // expected-note@-3{{defined here}}
void global_func(int);
void global_func2(int);
diff --git a/clang/test/SemaCXX/out-of-line-def-mismatch.cpp b/clang/test/SemaCXX/out-of-line-def-mismatch.cpp
index a4e130d234353a..1ce1cc0c7dfc0b 100644
--- a/clang/test/SemaCXX/out-of-line-def-mismatch.cpp
+++ b/clang/test/SemaCXX/out-of-line-def-mismatch.cpp
@@ -6,7 +6,11 @@ namespace N2 {
namespace N1 {
class C1 {};
- struct S2 {
+ struct S2 { // expected-note {{defined here}}
+ // expected-note@-1 {{defined here}}
+ // expected-note@-2 {{defined here}}
+ // expected-note@-3 {{defined here}}
+ // expected-note@-4 {{defined here}}
void func(S1*); // expected-note {{type of 1st parameter of member declaration does not match definition ('S1 *' (aka 'N2::S1 *') vs 'S1 *' (aka 'N2::N1::S1 *'))}}
void func(C1&, unsigned, const S1*); // expected-note {{type of 3rd parameter of member declaration does not match definition ('const S1 *' (aka 'const N2::...
[truncated]
|
clang/test/CXX/drs/cwg22xx.cpp
Outdated
@@ -108,6 +108,7 @@ namespace MultilevelSpecialization { | |||
template<> template<int a, int b> | |||
void B<int, int>::f(int i, int (&arr1)[a], int (&arr2)[b]) {} | |||
// since-cxx11-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}} | |||
// expected-note@-6 {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@-6 {{defined here}} | |
// expected-note@#cwg2233-blah {{defined here}} |
We shouldn't make the readers count lines to understand, which line the diagnostic is emitted for. Use bookmarks instead (with a proper name, see other tests for the reference).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. I'll update the test case. Does the implementation itself look good? I just want to make sure since many test cases are affected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, adding a diagnostic that’s very general like this one tends to require updating a lot of tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. The current test cases now use bookmarks to pinpoint class declarations.
clang/test/CXX/drs/cwg3xx.cpp
Outdated
@@ -600,6 +600,7 @@ namespace cwg336 { // cwg336: yes | |||
template<> template<class X> class A<int>::B {}; | |||
template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {} | |||
// expected-error@-1 {{out-of-line definition of 'mf1' does not match any declaration in 'cwg336::Pre::A<int>::B<double>'}} | |||
// expected-note@-3 {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@-3 {{defined here}} | |
// expected-note@#cwg366-blah {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation seems fine to me, but wait for other reviewers before merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, the change looks good to me.
Please also add a note in the clang/docs/ReleaseNotes.rst
clang/test/CXX/drs/cwg22xx.cpp
Outdated
@@ -108,6 +108,7 @@ namespace MultilevelSpecialization { | |||
template<> template<int a, int b> | |||
void B<int, int>::f(int i, int (&arr1)[a], int (&arr2)[b]) {} | |||
// since-cxx11-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}} | |||
// expected-note@-6 {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, adding a diagnostic that’s very general like this one tends to require updating a lot of tests.
Done. |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
@@ -597,9 +597,10 @@ namespace cwg336 { // cwg336: yes | |||
void mf2(); | |||
}; | |||
}; | |||
template<> template<class X> class A<int>::B {}; | |||
template<> template<class X> class A<int>::B {}; // #defined-here-cwg336 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template<> template<class X> class A<int>::B {}; // #defined-here-cwg336 | |
template<> template<class X> class A<int>::B {}; // #cwg336-B |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {} | ||
// expected-error@-1 {{out-of-line definition of 'mf1' does not match any declaration in 'cwg336::Pre::A<int>::B<double>'}} | ||
// expected-note@#defined-here-cwg336 {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@#defined-here-cwg336 {{defined here}} | |
// expected-note@#cwg336-B {{defined here}} |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
@@ -758,16 +759,18 @@ namespace cwg347 { // cwg347: yes | |||
void g(); | |||
}; | |||
|
|||
struct derived : base {}; | |||
struct derived : base {}; // #defined-here-derived |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct derived : base {}; // #defined-here-derived | |
struct derived : base {}; // #cwg347-derived |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
|
||
struct derived::nested {}; | ||
// expected-error@-1 {{no struct named 'nested' in 'cwg347::derived'}} | ||
int derived::n; | ||
// expected-error@-1 {{no member named 'n' in 'cwg347::derived'}} | ||
void derived::f() {} | ||
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg347::derived'}} | ||
// expected-note@#defined-here-derived {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@#defined-here-derived {{defined here}} | |
// expected-note@#cwg347-derived {{defined here}} |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
void derived::g() {} | ||
// expected-error@-1 {{out-of-line definition of 'g' does not match any declaration in 'cwg347::derived'}} | ||
// expected-note@#defined-here-derived {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@#defined-here-derived {{defined here}} | |
// expected-note@#cwg347-derived {{defined here}} |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
void f() const; // #cwg357-f | ||
}; | ||
template<typename T> void A<T>::f() {} | ||
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'A<T>'}} | ||
// expected-note@#cwg357-f {{member declaration does not match because it is const qualified}} | ||
// expected-note@#defined-here-cwg357-A {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@#defined-here-cwg357-A {{defined here}} | |
// expected-note@#cwg357-A {{defined here}} |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
|
||
struct B { | ||
struct B { // #defined-here-cwg357-B |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct B { // #defined-here-cwg357-B | |
struct B { // #cwg357-B |
clang/test/CXX/drs/cwg3xx.cpp
Outdated
template<typename T> void f(); | ||
}; | ||
template<typename T> void B::f() const {} | ||
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg357::B'}} | ||
// expected-note@#defined-here-cwg357-B {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@#defined-here-cwg357-B {{defined here}} | |
// expected-note@#cwg357-B {{defined here}} |
clang/test/CXX/drs/cwg22xx.cpp
Outdated
@@ -102,12 +102,13 @@ namespace MultilevelSpecialization { | |||
// default argument -- how far back do we look when determining whether a | |||
// parameter was expanded from a pack? | |||
// -- zygoloid 2020-06-02 | |||
template<typename ...T> struct B { | |||
template<typename ...T> struct B { // #defined-here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template<typename ...T> struct B { // #defined-here | |
template<typename ...T> struct B { // #cwg2233-B |
clang/test/CXX/drs/cwg22xx.cpp
Outdated
template <T... V> void f(int i = 0, int (&... arr)[V]); | ||
}; | ||
template<> template<int a, int b> | ||
void B<int, int>::f(int i, int (&arr1)[a], int (&arr2)[b]) {} | ||
// since-cxx11-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}} | ||
// expected-note@#defined-here {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// expected-note@#defined-here {{defined here}} | |
// since-cxx11-note@#cwg2233-B {{defined here}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM otherwise
Co-authored-by: Vlad Serebrennikov <[email protected]>
Thanks for your work on this. The buildbot is green, so I’ll merge it now. |
Thanks for all your thorough review and guidance! |
…od definition does not match any declaration. (llvm#110638) Fixes llvm#110558. In this patch, we will emit a diagnostic note pointing to the class declaration when a method definition does not match any declaration. This approach, similar to what GCC does, makes the diagnostic more user-friendly. --------- Co-authored-by: Vlad Serebrennikov <[email protected]>
Fixes #110558.
In this patch, we will emit a diagnostic note pointing to the class declaration when a method definition does not match any declaration. This approach, similar to what GCC does, makes the diagnostic more user-friendly.