Skip to content

Commit 8282c58

Browse files
c8efEndilll
andauthored
[Clang] Emit a diagnostic note at the class declaration when the method definition does not match any declaration. (#110638)
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. --------- Co-authored-by: Vlad Serebrennikov <[email protected]>
1 parent 9c697b3 commit 8282c58

File tree

25 files changed

+92
-51
lines changed

25 files changed

+92
-51
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,8 @@ Improvements to Clang's diagnostics
376376

377377
- Clang now diagnoses when a ``requires`` expression has a local parameter of void type, aligning with the function parameter (#GH109831).
378378

379+
- Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638).
380+
379381
Improvements to Clang's time-trace
380382
----------------------------------
381383

clang/lib/Sema/SemaDecl.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9086,9 +9086,14 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
90869086
SemaRef.Diag(NewFD->getLocation(), DiagMsg)
90879087
<< Name << NewDC << IsDefinition << NewFD->getLocation();
90889088

9089-
bool NewFDisConst = false;
9090-
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
9091-
NewFDisConst = NewMD->isConst();
9089+
CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD);
9090+
if (NewMD && DiagMsg == diag::err_member_decl_does_not_match) {
9091+
CXXRecordDecl *RD = NewMD->getParent();
9092+
SemaRef.Diag(RD->getLocation(), diag::note_defined_here)
9093+
<< RD->getName() << RD->getLocation();
9094+
}
9095+
9096+
bool NewFDisConst = NewMD && NewMD->isConst();
90929097

90939098
for (SmallVectorImpl<std::pair<FunctionDecl *, unsigned> >::iterator
90949099
NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();

clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,12 @@ namespace {
164164

165165
#if __cplusplus < 201402L
166166
namespace ImplicitConstexprDef {
167-
struct A {
167+
struct A { // #defined-here
168168
void f(); // expected-note {{member declaration does not match because it is not const qualified}}
169169
};
170170

171171
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}}
172172
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}}
173+
// expected-note@#defined-here {{defined here}}
173174
}
174175
#endif
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s
22

3-
struct A { };
3+
struct A { }; // #defined-here
44
A::A (enum { e1 }) {} // expected-error{{cannot be defined in a parameter}}
55
void A::f(enum { e2 }) {} // expected-error{{cannot be defined in a parameter}}
66

77
enum { e3 } A::g() { } // expected-error{{cannot be defined in the result type}} \
88
// expected-error{{out-of-line definition}}
9+
// expected-note@#defined-here{{defined here}}

clang/test/CXX/dcl/dcl.fct/p17.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ namespace unconstrained {
9696
// expected-error@-1{{no matching}}
9797

9898
template<typename T>
99-
struct S {
99+
struct S { // #defined-here
100100
constexpr auto f1(auto x, T t) -> decltype(x + t);
101101

102102
template<typename U>
@@ -110,6 +110,7 @@ namespace unconstrained {
110110
template<typename U>
111111
constexpr auto S<T>::f2(auto x, U u, T t) -> decltype(x + u + t) { return x + u + t; }
112112
// expected-error@-1 {{out-of-line definition of 'f2' does not match any declaration in 'S<T>'}}
113+
// expected-note@#defined-here {{S defined here}}
113114

114115
template<typename T>
115116
template<typename U>

clang/test/CXX/drs/cwg22xx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,13 @@ namespace MultilevelSpecialization {
102102
// default argument -- how far back do we look when determining whether a
103103
// parameter was expanded from a pack?
104104
// -- zygoloid 2020-06-02
105-
template<typename ...T> struct B {
105+
template<typename ...T> struct B { // #cwg2233-B
106106
template <T... V> void f(int i = 0, int (&... arr)[V]);
107107
};
108108
template<> template<int a, int b>
109109
void B<int, int>::f(int i, int (&arr1)[a], int (&arr2)[b]) {}
110110
// since-cxx11-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}}
111+
// since-cxx11-note@#cwg2233-B {{defined here}}
111112
template<> template<>
112113
void B<int, int>::f<1, 1>(int i, int (&arr1a)[1], int (&arr2a)[1]) {}
113114
}

clang/test/CXX/drs/cwg3xx.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,10 @@ namespace cwg336 { // cwg336: yes
597597
void mf2();
598598
};
599599
};
600-
template<> template<class X> class A<int>::B {};
600+
template<> template<class X> class A<int>::B {}; // #cwg336-B
601601
template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {}
602602
// expected-error@-1 {{out-of-line definition of 'mf1' does not match any declaration in 'cwg336::Pre::A<int>::B<double>'}}
603+
// expected-note@#cwg336-B {{defined here}}
603604
template<class Y> template<> void A<Y>::B<double>::mf2() {}
604605
// 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}}
605606
}
@@ -758,16 +759,18 @@ namespace cwg347 { // cwg347: yes
758759
void g();
759760
};
760761

761-
struct derived : base {};
762+
struct derived : base {}; // #cwg347-derived
762763

763764
struct derived::nested {};
764765
// expected-error@-1 {{no struct named 'nested' in 'cwg347::derived'}}
765766
int derived::n;
766767
// expected-error@-1 {{no member named 'n' in 'cwg347::derived'}}
767768
void derived::f() {}
768769
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg347::derived'}}
770+
// expected-note@#cwg347-derived {{defined here}}
769771
void derived::g() {}
770772
// expected-error@-1 {{out-of-line definition of 'g' does not match any declaration in 'cwg347::derived'}}
773+
// expected-note@#cwg347-derived {{defined here}}
771774
}
772775

773776
// cwg348: na
@@ -1009,18 +1012,20 @@ namespace cwg355 { struct ::cwg355_S s; }
10091012
// cwg356: na
10101013

10111014
namespace cwg357 { // cwg357: yes
1012-
template<typename T> struct A {
1015+
template<typename T> struct A { // #cwg357-A
10131016
void f() const; // #cwg357-f
10141017
};
10151018
template<typename T> void A<T>::f() {}
10161019
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'A<T>'}}
1020+
// expected-note@#cwg357-A {{defined here}}
10171021
// expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
10181022

1019-
struct B {
1023+
struct B { // #cwg357-B
10201024
template<typename T> void f();
10211025
};
10221026
template<typename T> void B::f() const {}
10231027
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'cwg357::B'}}
1028+
// expected-note@#cwg357-B {{defined here}}
10241029
}
10251030

10261031
namespace cwg358 { // cwg358: yes

clang/test/CXX/special/class.inhctor/p8.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ struct C {
2424
template<typename T> constexpr C(T t) : v(t) {}
2525
int v;
2626
};
27-
struct D : C {
27+
struct D : C { // #defined-here
2828
using C::C;
2929
};
3030
static_assert(D(123).v == 123, "");
3131

3232
template<typename T> constexpr D::D(T t) : C(t) {} // expected-error {{does not match any declaration in 'D'}}
33+
// expected-note@#defined-here {{defined here}}

clang/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@ int AA::A() { return sizeof(T); }
4747
namespace diag {
4848

4949
template <unsigned N>
50-
struct TA {
50+
struct TA { // #defined-here
5151
template <template <unsigned> class TT> requires TT<N>::happy
5252
int A();
5353
};
5454

5555
template <unsigned N>
5656
template <template <unsigned> class TT> int TA<N>::A() { return sizeof(TT<N>); }
5757
// expected-error@-1{{out-of-line definition of 'A' does not match any declaration in 'TA<N>'}}
58+
// expected-note@#defined-here{{defined here}}
5859

5960
} // end namespace diag

clang/test/CXX/temp/temp.res/temp.local/p8.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ namespace SearchClassBetweenTemplateParameterLists {
6969

7070
template<typename T> struct A {
7171
using AA = void;
72-
template<typename U> struct B {
72+
template<typename U> struct B { // #defined-here
7373
using BB = void;
7474
void f(U);
7575
void g(U);
@@ -127,19 +127,19 @@ namespace SearchClassBetweenTemplateParameterLists {
127127
template<typename T> template<typename BB>
128128
void A<T>::B<BB>::g(BB) { // expected-error {{does not match}}
129129
BB bb; // expected-error {{incomplete type}}
130-
}
130+
} // expected-note@#defined-here {{defined here}}
131131

132132
// error, 'AA' found in (4)
133133
template<typename AA> template<typename U>
134134
void A<AA>::B<U>::h(AA) { // expected-error {{does not match}}
135135
AA aa; // expected-error {{incomplete type}}
136-
}
136+
} // expected-note@#defined-here {{defined here}}
137137

138138
// error, 'BB' found in (2)
139139
template<typename BB> template<typename U>
140140
void A<BB>::B<U>::i(BB) { // expected-error {{does not match}}
141141
BB bb; // expected-error {{incomplete type}}
142-
}
142+
} // expected-note@#defined-here {{defined here}}
143143

144144
// OK, 'BB' found in (1)
145145
template<typename T> template<typename U> template<typename BB>
@@ -151,7 +151,7 @@ namespace SearchClassBetweenTemplateParameterLists {
151151
template<typename T> template<typename BB> template<typename V>
152152
void A<T>::B<BB>::k(V) { // expected-error {{does not match}}
153153
BB bb; // expected-error {{incomplete type}}
154-
}
154+
} // expected-note@#defined-here {{defined here}}
155155

156156
int CC;
157157
template <typename> struct C;

0 commit comments

Comments
 (0)