[clang] [Clang] Emit a diagnostic note at the class declaration when the method definition does not match any declaration. (PR #110638)

via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 2 02:53:18 PDT 2024


https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/110638

>From 38430b6cdfc524972fbdabca6a037174eaf1549f Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 1 Oct 2024 09:08:14 +0000
Subject: [PATCH 1/8] 110558

---
 clang/lib/Sema/SemaDecl.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0e536f71a2f70d..ed189e02a51d22 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9085,6 +9085,11 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
 
   SemaRef.Diag(NewFD->getLocation(), DiagMsg)
       << Name << NewDC << IsDefinition << NewFD->getLocation();
+  if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) {
+    CXXRecordDecl *RD = NewMD->getParent();
+    SemaRef.Diag(RD->getLocation(), diag::note_defined_here)
+        << RD->getName() << RD->getLocation();
+  }
 
   bool NewFDisConst = false;
   if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))

>From 8f37ce5dec7361b0dbc1ad6f912048fa6bbc38ff Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 1 Oct 2024 10:19:00 +0000
Subject: [PATCH 2/8] fix

---
 clang/lib/Sema/SemaDecl.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ed189e02a51d22..7b62b4f6d6433d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9085,7 +9085,8 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
 
   SemaRef.Diag(NewFD->getLocation(), DiagMsg)
       << Name << NewDC << IsDefinition << NewFD->getLocation();
-  if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) {
+  CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD);
+  if (DiagMsg == diag::err_member_decl_does_not_match && NewMD) {
     CXXRecordDecl *RD = NewMD->getParent();
     SemaRef.Diag(RD->getLocation(), diag::note_defined_here)
         << RD->getName() << RD->getLocation();

>From c875c6cb3c0ec64d29a4b4c31ac4eb3605f43289 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 1 Oct 2024 11:52:22 +0000
Subject: [PATCH 3/8] fix test

---
 clang/lib/Sema/SemaDecl.cpp                        |  7 +++----
 .../test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp |  1 +
 clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp |  1 +
 clang/test/CXX/dcl/dcl.fct/p17.cpp                 |  1 +
 clang/test/CXX/drs/cwg22xx.cpp                     |  1 +
 clang/test/CXX/drs/cwg3xx.cpp                      |  7 ++++++-
 clang/test/CXX/special/class.inhctor/p8.cpp        |  1 +
 .../temp.constr.decl/func-template-decl.cpp        |  1 +
 clang/test/CXX/temp/temp.res/temp.local/p8.cpp     |  8 ++++----
 .../test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp |  2 ++
 .../CXX/temp/temp.spec/temp.expl.spec/p14-23.cpp   |  1 +
 .../test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp |  1 +
 clang/test/FixIt/member-mismatch.cpp               |  2 ++
 clang/test/Parser/cxx-class.cpp                    |  1 +
 clang/test/SemaCXX/attr-target-mv.cpp              |  7 ++++---
 clang/test/SemaCXX/attr-target-version.cpp         |  7 ++++---
 clang/test/SemaCXX/enable_if.cpp                   |  2 +-
 clang/test/SemaCXX/function-redecl.cpp             | 14 ++++++++------
 clang/test/SemaCXX/lambda-unevaluated.cpp          |  2 ++
 clang/test/SemaCXX/nested-name-spec.cpp            |  4 ++++
 clang/test/SemaCXX/out-of-line-def-mismatch.cpp    |  6 +++++-
 clang/test/SemaCXX/typo-correction.cpp             |  1 +
 .../test/SemaTemplate/concepts-out-of-line-def.cpp |  4 +++-
 clang/test/SemaTemplate/recovery-crash.cpp         |  5 +++--
 24 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7b62b4f6d6433d..e4c45cbc09e0f7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9085,16 +9085,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
 
   SemaRef.Diag(NewFD->getLocation(), DiagMsg)
       << Name << NewDC << IsDefinition << NewFD->getLocation();
+
   CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD);
-  if (DiagMsg == diag::err_member_decl_does_not_match && NewMD) {
+  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 = false;
-  if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
-    NewFDisConst = NewMD->isConst();
+  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 at -1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}}
+                            // expected-note at -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 at -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 at -1 {{out-of-line definition of 'f2' does not match any declaration in 'S<T>'}}
+  // expected-note at -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 at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}}
+    // expected-note at -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 at -1 {{out-of-line definition of 'mf1' does not match any declaration in 'cwg336::Pre::A<int>::B<double>'}}
+    // expected-note at -3 {{defined here}}
     template<class Y> template<> void A<Y>::B<double>::mf2() {}
     // expected-error at -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 at -1 {{no member named 'n' in 'cwg347::derived'}}
   void derived::f() {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg347::derived'}}
+  // expected-note at -8 {{defined here}}
   void derived::g() {}
   // expected-error at -1 {{out-of-line definition of 'g' does not match any declaration in 'cwg347::derived'}}
+  // expected-note at -11 {{defined here}}
 }
 
 // cwg348: na
@@ -1014,13 +1017,15 @@ namespace cwg357 { // cwg357: yes
   };
   template<typename T> void A<T>::f() {}
   // expected-error at -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 at -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 at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg357::B'}}
+  // expected-note at -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 at -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 at -1{{out-of-line definition of 'A' does not match any declaration in 'TA<N>'}}
+// expected-note at -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 at -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 at -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 at -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 at -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 at -1 {{out-of-line declaration of 'g0' does not match any declaration in 'B<short>'}}
                                // cxx11-warning at -2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
+                               // expected-note at -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 at -1 {{constexpr declaration of 'g1' follows non-constexpr declaration}}
                                // cxx11-warning at -2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
+                               // expected-note at -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 at -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..7e799560e63f9f 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 at -10{{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 at -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 at -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 at -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 at +3 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
-// expected-note at -3 {{member declaration nearly matches}}
-// expected-note at -3 {{member declaration nearly matches}}
+// expected-error at +4 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
+// expected-note at -8 {{defined here}}
+// expected-note at -4 {{member declaration nearly matches}}
+// expected-note at -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 at +3 {{out-of-line definition of 'func' does not match any declaration in 'Out'}}
-// expected-note at -3 {{member declaration nearly matches}}
-// expected-note at -3 {{member declaration nearly matches}}
+// expected-error at +4 {{out-of-line definition of 'func' does not match any declaration in 'Out'}}
+// expected-note at -2 {{member declaration nearly matches}}
+// expected-note at -4 {{member declaration nearly matches}}
+// expected-note at -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 at -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 at -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 at -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 at -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 at -11{{defined here}}
 
 void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'C2'}}
+                    // expected-note at -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 at -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 at -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 at -1 {{defined here}}
+                // expected-note at -2 {{defined here}}
+                // expected-note at -3 {{defined here}}
+                // expected-note at -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::S1 *') vs 'const S1 *' (aka 'const N2::N1::S1 *'))}}
       void func(const S1*, unsigned); //expected-note {{type of 1st parameter of member declaration does not match definition ('const S1 *' vs 'S1')}}
diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp
index c262a62f0cb9cf..45f42c42603589 100644
--- a/clang/test/SemaCXX/typo-correction.cpp
+++ b/clang/test/SemaCXX/typo-correction.cpp
@@ -173,6 +173,7 @@ class Parent {
 };
 class Child: public Parent {};
 void Child::add_types(int value) {} // expected-error{{out-of-line definition of 'add_types' does not match any declaration in 'Child'}}
+                                    // expected-note at -2{{defined here}}
 
 // Fix the callback based filtering of typo corrections within
 // Sema::ActOnIdExpression by Parser::ParseCastExpression to allow type names as
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index 8ca399a0f729a9..e7ca34fa6e32dd 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -524,7 +524,8 @@ struct X {
 template <class T>
 void X<T>::foo() requires requires { requires something_interesting<T>; } {}
 // expected-error at -1{{definition of 'foo' does not match any declaration}}
-// expected-note@*{{}}
+// expected-note at -8{{defined here}}
+// expected-note at -8{{member declaration nearly matches}}
 
 template <class T>
 void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok
@@ -532,6 +533,7 @@ void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok
 template <class T>
 void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {}
 // expected-error at -1{{definition of 'bar' does not match any declaration}}
+// expected-note at -17{{defined here}}
 
 template <class T>
 void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
diff --git a/clang/test/SemaTemplate/recovery-crash.cpp b/clang/test/SemaTemplate/recovery-crash.cpp
index a451d9d108da5d..37fbd6fbeca9c5 100644
--- a/clang/test/SemaTemplate/recovery-crash.cpp
+++ b/clang/test/SemaTemplate/recovery-crash.cpp
@@ -61,7 +61,8 @@ namespace test1 {
     // expected-error at +1 {{member 'UndeclaredMethod' used before its declaration}}
     UndeclaredMethod(resource_data);
   }
-  // expected-error at +2 {{out-of-line definition of 'UndeclaredMethod' does not match any declaration}}
-  // expected-note at +1 {{member is declared here}}
+  // expected-error at +3 {{out-of-line definition of 'UndeclaredMethod' does not match any declaration}}
+  // expected-note at +2 {{member is declared here}}
+  // expected-note at -16 {{defined here}}
   void NonTemplateClass::UndeclaredMethod() {}
 }

>From e20b2e65e228fe0f68f3eb03ebda616af57468eb Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 1 Oct 2024 12:16:19 +0000
Subject: [PATCH 4/8] fix test

---
 clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 7e799560e63f9f..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,7 +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 at -10{{defined here}}
+                                      // expected-note at -7{{defined here}}
 
 // FIXME: This diagnostic could probably be better.
 template<class Y> template<>

>From 2fc1074f29ff4d1abb9e5930e9fc29d0013fbab0 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 2 Oct 2024 02:53:13 +0000
Subject: [PATCH 5/8] release note

---
 clang/docs/ReleaseNotes.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6e7a5fb76b602b..5b0487ce677a99 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -375,6 +375,8 @@ Improvements to Clang's diagnostics
 
 - Clang now diagnoses when a ``requires`` expression has a local parameter of void type, aligning with the function parameter (#GH109831).
 
+- Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638).
+
 Improvements to Clang's time-trace
 ----------------------------------
 

>From e1bff7af11ca234922b13dca5ea2e5b25c2cf113 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 2 Oct 2024 03:22:43 +0000
Subject: [PATCH 6/8] fix test

---
 .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp  |  4 ++--
 .../CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp    |  4 ++--
 clang/test/CXX/dcl/dcl.fct/p17.cpp             |  4 ++--
 clang/test/CXX/drs/cwg22xx.cpp                 |  4 ++--
 clang/test/CXX/drs/cwg3xx.cpp                  | 18 +++++++++---------
 clang/test/CXX/special/class.inhctor/p8.cpp    |  4 ++--
 .../temp.constr.decl/func-template-decl.cpp    |  4 ++--
 clang/test/CXX/temp/temp.res/temp.local/p8.cpp | 10 +++++-----
 .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp  |  8 +++-----
 .../temp/temp.spec/temp.expl.spec/p14-23.cpp   |  4 ++--
 .../CXX/temp/temp.spec/temp.expl.spec/p18.cpp  |  4 ++--
 clang/test/FixIt/member-mismatch.cpp           |  6 +++---
 clang/test/Parser/cxx-class.cpp                |  4 ++--
 clang/test/SemaCXX/attr-target-mv.cpp          |  4 ++--
 clang/test/SemaCXX/attr-target-version.cpp     |  4 ++--
 clang/test/SemaCXX/lambda-unevaluated.cpp      |  8 ++++----
 clang/test/SemaCXX/nested-name-spec.cpp        | 14 +++++++-------
 .../SemaTemplate/concepts-out-of-line-def.cpp  |  6 +++---
 clang/test/SemaTemplate/recovery-crash.cpp     |  4 ++--
 19 files changed, 58 insertions(+), 60 deletions(-)

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 f0901733f8afeb..752451f3d9749c 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
@@ -164,12 +164,12 @@ namespace {
 
 #if __cplusplus < 201402L
 namespace ImplicitConstexprDef {
-  struct A {
+  struct A { // #defined-here
     void f(); // expected-note {{member declaration does not match because it is not const qualified}}
   };
 
   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 at -1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}}
-                            // expected-note at -6 {{A defined here}}
+                            // expected-note@#defined-here {{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 fbd26cfd7b9db7..32ad25e2b70541 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
@@ -1,9 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-struct A { };
+struct A { }; // #defined-here
 A::A (enum { e1 }) {} // expected-error{{cannot be defined in a parameter}}
 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 at -6{{defined here}}
+// expected-note@#defined-here{{defined here}}
diff --git a/clang/test/CXX/dcl/dcl.fct/p17.cpp b/clang/test/CXX/dcl/dcl.fct/p17.cpp
index 34b0c9f3ce0273..4a81875cb4f896 100644
--- a/clang/test/CXX/dcl/dcl.fct/p17.cpp
+++ b/clang/test/CXX/dcl/dcl.fct/p17.cpp
@@ -96,7 +96,7 @@ namespace unconstrained {
   // expected-error at -1{{no matching}}
 
   template<typename T>
-  struct S {
+  struct S { // #defined-here
     constexpr auto f1(auto x, T t) -> decltype(x + t);
 
     template<typename U>
@@ -110,7 +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 at -1 {{out-of-line definition of 'f2' does not match any declaration in 'S<T>'}}
-  // expected-note at -14 {{S defined here}}
+  // expected-note@#defined-here {{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 a16a74a43a859a..5de58efb70e39a 100644
--- a/clang/test/CXX/drs/cwg22xx.cpp
+++ b/clang/test/CXX/drs/cwg22xx.cpp
@@ -102,13 +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
     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 at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}}
-    // expected-note at -6 {{defined here}}
+    // expected-note@#defined-here {{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 1ef878dab4e56a..8c4cb0b66c50d3 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -597,10 +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
     template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {}
     // expected-error at -1 {{out-of-line definition of 'mf1' does not match any declaration in 'cwg336::Pre::A<int>::B<double>'}}
-    // expected-note at -3 {{defined here}}
+    // expected-note@#defined-here-cwg336 {{defined here}}
     template<class Y> template<> void A<Y>::B<double>::mf2() {}
     // expected-error at -1 {{nested name specifier 'A<Y>::B<double>::' for declaration does not refer into a class, class template or class template partial specialization}}
   }
@@ -759,7 +759,7 @@ namespace cwg347 { // cwg347: yes
     void g();
   };
 
-  struct derived : base {};
+  struct derived : base {}; // #defined-here-derived
 
   struct derived::nested {};
   // expected-error at -1 {{no struct named 'nested' in 'cwg347::derived'}}
@@ -767,10 +767,10 @@ namespace cwg347 { // cwg347: yes
   // expected-error at -1 {{no member named 'n' in 'cwg347::derived'}}
   void derived::f() {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg347::derived'}}
-  // expected-note at -8 {{defined here}}
+  // expected-note@#defined-here-derived {{defined here}}
   void derived::g() {}
   // expected-error at -1 {{out-of-line definition of 'g' does not match any declaration in 'cwg347::derived'}}
-  // expected-note at -11 {{defined here}}
+  // expected-note@#defined-here-derived {{defined here}}
 }
 
 // cwg348: na
@@ -1012,20 +1012,20 @@ namespace cwg355 { struct ::cwg355_S s; }
 // cwg356: na
 
 namespace cwg357 { // cwg357: yes
-  template<typename T> struct A {
+  template<typename T> struct A { // #defined-here-cwg357-A
     void f() const; // #cwg357-f
   };
   template<typename T> void A<T>::f() {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'A<T>'}}
-  // expected-note at -5 {{defined here}}
+  // expected-note@#defined-here-cwg357 {{defined here}}
   // expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
 
-  struct B {
+  struct B { // #defined-here-cwg357-B
     template<typename T> void f();
   };
   template<typename T> void B::f() const {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg357::B'}}
-  // expected-note at -5 {{defined here}}
+  // expected-note@#defined-here-cwg357-B {{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 fe17d6e44351f4..dbc357c1a8d4fc 100644
--- a/clang/test/CXX/special/class.inhctor/p8.cpp
+++ b/clang/test/CXX/special/class.inhctor/p8.cpp
@@ -24,10 +24,10 @@ struct C {
   template<typename T> constexpr C(T t) : v(t) {}
   int v;
 };
-struct D : C {
+struct D : C { // #defined-here
   using C::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 at -6 {{defined here}}
+                                                   // expected-note@#defined-here {{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 e511404ffac38c..9a8148bdf625f7 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
@@ -47,7 +47,7 @@ int AA::A() { return sizeof(T); }
 namespace diag {
 
 template <unsigned N>
-struct TA {
+struct TA { // #defined-here
   template <template <unsigned> class TT> requires TT<N>::happy
   int A();
 };
@@ -55,6 +55,6 @@ struct TA {
 template <unsigned N>
 template <template <unsigned> class TT> int TA<N>::A() { return sizeof(TT<N>); }
 // expected-error at -1{{out-of-line definition of 'A' does not match any declaration in 'TA<N>'}}
-// expected-note at -8{{defined here}}
+// expected-note@#defined-here{{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 4cc48e16699a6b..f503b4f15dd3f4 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
@@ -69,7 +69,7 @@ namespace SearchClassBetweenTemplateParameterLists {
 
   template<typename T> struct A {
     using AA = void;
-    template<typename U> struct B {
+    template<typename U> struct B { // #defined-here
       using BB = void;
       void f(U);
       void g(U);
@@ -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 at -58 {{defined here}}
+  } // expected-note@#defined-here {{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 at -64 {{defined here}}
+  } // expected-note@#defined-here {{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 at -70 {{defined here}}
+  } // expected-note@#defined-here {{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 at -82 {{defined here}}
+  } // expected-note@#defined-here {{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 bd36ea2318d761..9717fbf419b0a2 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
@@ -31,7 +31,7 @@ constexpr void A::f1<long>(); // since-cxx14-error {{no function template matche
 // members of a class template explicitly specialized for an implicitly
 // instantiated specialization of that template.
 template<typename T>
-struct B {
+struct B { // #defined-here
   void g0(); // since-cxx14-note {{previous declaration is here}}
              // cxx11-note at -1 {{member declaration does not match because it is not const qualified}}
 
@@ -49,13 +49,13 @@ template<>
 constexpr void B<short>::g0(); // since-cxx14-error {{constexpr declaration of 'g0' follows non-constexpr declaration}}
                                // cxx11-error at -1 {{out-of-line declaration of 'g0' does not match any declaration in 'B<short>'}}
                                // cxx11-warning at -2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
-                               // expected-note at -18 {{defined here}}
+                               // expected-note@#defined-here {{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 at -1 {{constexpr declaration of 'g1' follows non-constexpr declaration}}
                                // cxx11-warning at -2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
-                               // expected-note at -24 {{defined here}}
+                               // expected-note@#defined-here {{defined here}}
 
 template<>
 template<typename U>
@@ -68,5 +68,3 @@ template<typename U>
 constexpr void B<long>::h1(); // since-cxx14-error {{out-of-line declaration of 'h1' does not match any declaration in 'B<long>'}}
                               // cxx11-error at -1 {{constexpr declaration of 'h1' follows non-constexpr declaration}}
                               // cxx11-warning at -2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}}
-
-
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 cf800dce3a37f5..062c2db7db0e2b 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
@@ -8,7 +8,7 @@ namespace N0 {
   concept D = I < 8;
 
   template<int I>
-  struct A {
+  struct A { // #defined-here
     constexpr static int f() { return 0; }
     constexpr static int f() requires C<I> && D<I> { return 1; }
     constexpr static int f() requires C<I> { return 2; }
@@ -56,7 +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 at -48 {{defined here}}
+                                        // expected-note@#defined-here {{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 390a47c8942690..5351773fafe89c 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
@@ -7,14 +7,14 @@ template<class T1> class A {
 }; 
 
 template<> template<class X>
-class A<long>::B { }; 
+class A<long>::B { }; // #defined-here
 
 template<> template<> template<class T>
   void A<int>::B<double>::mf1(T t) { } 
 
 template<> template<> template<class T>
 void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}}
-                                      // expected-note at -7{{defined here}}
+                                      // expected-note@#defined-here{{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 531184933c09ab..e9c649d85c5c73 100644
--- a/clang/test/FixIt/member-mismatch.cpp
+++ b/clang/test/FixIt/member-mismatch.cpp
@@ -1,14 +1,14 @@
 // RUN: %clang_cc1 -verify %s
 // RUN: not %clang_cc1 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
 
-class Foo {
+class Foo { // #defined-here
   int get() const; // expected-note {{because it is const qualified}}
   void set(int); // expected-note {{because it is not const qualified}}
 };
 
 // CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:15-[[@LINE+1]]:15}:" const"
 int Foo::get() {} // expected-error {{does not match any declaration}}
-                  // expected-note at -7 {{defined here}}
+                  // expected-note@#defined-here {{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 at -10 {{defined here}}
+                            // expected-note@#defined-here {{defined here}}
diff --git a/clang/test/Parser/cxx-class.cpp b/clang/test/Parser/cxx-class.cpp
index 583534afa83408..a6757f39146a16 100644
--- a/clang/test/Parser/cxx-class.cpp
+++ b/clang/test/Parser/cxx-class.cpp
@@ -100,10 +100,10 @@ class F {
 #endif
 
 namespace ctor_error {
-  class Foo {};
+  class Foo {}; // #defined-here
   // 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 at -3{{defined here}}
+                      // expected-note@#defined-here{{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 004ac0469492fb..b8db6d371bd587 100644
--- a/clang/test/SemaCXX/attr-target-mv.cpp
+++ b/clang/test/SemaCXX/attr-target-mv.cpp
@@ -180,7 +180,7 @@ void constexpr_test() {
   static_assert(foo() == 2, "Should call 'default' in a constexpr context");
 }
 
-struct BadOutOfLine {
+struct BadOutOfLine { // #defined-here
   int __attribute__((target("sse4.2"))) foo(int);
   int __attribute__((target("default"))) foo(int);
 };
@@ -188,7 +188,7 @@ struct BadOutOfLine {
 int __attribute__((target("sse4.2"))) BadOutOfLine::foo(int) { return 0; }
 int __attribute__((target("default"))) BadOutOfLine::foo(int) { return 1; }
 // expected-error at +4 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}}
-// expected-note at -8 {{defined here}}
+// expected-note@#defined-here {{defined here}}
 // expected-note at -4 {{member declaration nearly matches}}
 // expected-note at -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 c8a05e99c80ddd..14460756db17bf 100644
--- a/clang/test/SemaCXX/attr-target-version.cpp
+++ b/clang/test/SemaCXX/attr-target-version.cpp
@@ -97,7 +97,7 @@ using ::Decl;
 __attribute__((target_version("jscvt"))) void Decl();
 } // namespace Nms
 
-class Out {
+class Out { // #defined-here
   int __attribute__((target_version("bti"))) func(void);
   int __attribute__((target_version("ssbs2"))) func(void);
 };
@@ -106,5 +106,5 @@ int __attribute__((target_version("ssbs2"))) Out::func(void) { return 2; }
 // expected-error at +4 {{out-of-line definition of 'func' does not match any declaration in 'Out'}}
 // expected-note at -2 {{member declaration nearly matches}}
 // expected-note at -4 {{member declaration nearly matches}}
-// expected-note at -9 {{defined here}}
+// expected-note@#defined-here {{defined here}}
 int __attribute__((target_version("rng"))) Out::func(void) { return 3; }
diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
index f0ebfef029d16e..a9bcab58464e26 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -70,23 +70,23 @@ void use_g() { g<6>(&"hello"); } // expected-error {{ambiguous}}
 namespace GH51416 {
 
 template <class T>
-struct A {
+struct A { // #defined-here-A
   void spam(decltype([] {}));
 };
 
 template <class T>
 void A<T>::spam(decltype([] {})) // expected-error{{out-of-line definition of 'spam' does not match}}
-                                 // expected-note at -6{{defined here}}
+                                 // expected-note@#defined-here-A{{defined here}}
 {}
 
-struct B {
+struct B { // #defined-here-B
   template <class T>
   void spam(decltype([] {}));
 };
 
 template <class T>
 void B::spam(decltype([] {})) {} // expected-error{{out-of-line definition of 'spam' does not match}}
-                                 // expected-note at -7{{defined here}}
+                                 // expected-note@#defined-here-B{{defined here}}
 
 } // namespace GH51416
 
diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp
index cd66792f4852b5..981152dda23f54 100644
--- a/clang/test/SemaCXX/nested-name-spec.cpp
+++ b/clang/test/SemaCXX/nested-name-spec.cpp
@@ -25,7 +25,7 @@ int A::C::cx = 17;
 
 static int A::C::cx2 = 17; // expected-error{{'static' can}}
 
-class C2 {
+class C2 { // #defined-here-C2
   void m(); // expected-note{{member declaration does not match because it is not const qualified}}
 
   void f(const int& parm); // expected-note{{type of 1st parameter of member declaration does not match definition ('const int &' vs 'int')}}
@@ -36,10 +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 at -11{{defined here}}
+                       // expected-note@#defined-here-C2{{defined here}}
 
 void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'C2'}}
-                    // expected-note at -14{{defined here}}
+                    // expected-note@#defined-here-C2{{defined here}}
 
 void C2::m() {
   x = 0;
@@ -124,13 +124,13 @@ namespace E {
 }
 
 
-class Operators {
+class Operators { // #defined-here-Operators
   Operators operator+(const Operators&) const; // expected-note{{member declaration does not match because it is const qualified}}
   operator bool();
 };
 
 Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition of 'operator+' does not match any declaration in 'Operators'}}
-                                                   // expected-note at -6{{defined here}}
+                                                   // expected-note@#defined-here-Operators{{defined here}}
   Operators ops;
   return ops;
 }
@@ -152,10 +152,10 @@ void A::f() {} // expected-error-re{{out-of-line definition of 'f' does not matc
 
 void A::g(const int&) { } // expected-error{{out-of-line definition of 'g' does not match any declaration in namespace 'A'}}
 
-struct Struct { };
+struct Struct { }; // #defined-here-Struct
 
 void Struct::f() { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'Struct'}}
-                     // expected-note at -3{{defined here}}
+                     // expected-note@#defined-here-Struct{{defined here}}
 
 void global_func(int);
 void global_func2(int);
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index e7ca34fa6e32dd..fe8f74928fc370 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -516,7 +516,7 @@ concept something_interesting = requires {
 };
 
 template <class T>
-struct X {
+struct X { // #defined-here
       void foo() requires requires { requires is_not_same_v<T, int>; };
       void bar(decltype(requires { requires is_not_same_v<T, int>; }));
 };
@@ -524,7 +524,7 @@ struct X {
 template <class T>
 void X<T>::foo() requires requires { requires something_interesting<T>; } {}
 // expected-error at -1{{definition of 'foo' does not match any declaration}}
-// expected-note at -8{{defined here}}
+// expected-note@#defined-here{{defined here}}
 // expected-note at -8{{member declaration nearly matches}}
 
 template <class T>
@@ -533,7 +533,7 @@ void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok
 template <class T>
 void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {}
 // expected-error at -1{{definition of 'bar' does not match any declaration}}
-// expected-note at -17{{defined here}}
+// expected-note@#defined-here{{defined here}}
 
 template <class T>
 void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
diff --git a/clang/test/SemaTemplate/recovery-crash.cpp b/clang/test/SemaTemplate/recovery-crash.cpp
index 37fbd6fbeca9c5..88e989aeb40649 100644
--- a/clang/test/SemaTemplate/recovery-crash.cpp
+++ b/clang/test/SemaTemplate/recovery-crash.cpp
@@ -47,7 +47,7 @@ namespace PR16225 {
 namespace test1 {
   template <typename> class ArraySlice {};
   class Foo;
-  class NonTemplateClass {
+  class NonTemplateClass { // #defined-here
     void MemberFunction(ArraySlice<Foo>, int);
     template <class T> void MemberFuncTemplate(ArraySlice<T>, int);
   };
@@ -63,6 +63,6 @@ namespace test1 {
   }
   // expected-error at +3 {{out-of-line definition of 'UndeclaredMethod' does not match any declaration}}
   // expected-note at +2 {{member is declared here}}
-  // expected-note at -16 {{defined here}}
+  // expected-note@#defined-here {{defined here}}
   void NonTemplateClass::UndeclaredMethod() {}
 }

>From 8cf3db7da46db52581af0a7f716c491a698800c2 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 2 Oct 2024 03:27:17 +0000
Subject: [PATCH 7/8] fix test

---
 clang/test/CXX/drs/cwg3xx.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 8c4cb0b66c50d3..6d4bf5b04d7689 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -1017,7 +1017,7 @@ namespace cwg357 { // cwg357: yes
   };
   template<typename T> void A<T>::f() {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'A<T>'}}
-  // expected-note@#defined-here-cwg357 {{defined here}}
+  // expected-note@#defined-here-cwg357-A {{defined here}}
   // expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
 
   struct B { // #defined-here-cwg357-B

>From 716d31cf33d532c4137901113df841ebed3f79df Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Wed, 2 Oct 2024 09:53:03 +0000
Subject: [PATCH 8/8] Address review comments.

---
 clang/test/CXX/drs/cwg22xx.cpp |  4 ++--
 clang/test/CXX/drs/cwg3xx.cpp  | 20 ++++++++++----------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/clang/test/CXX/drs/cwg22xx.cpp b/clang/test/CXX/drs/cwg22xx.cpp
index 5de58efb70e39a..0614d4f34ad5e4 100644
--- a/clang/test/CXX/drs/cwg22xx.cpp
+++ b/clang/test/CXX/drs/cwg22xx.cpp
@@ -102,13 +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 { // #defined-here
+  template<typename ...T> struct B { // #cwg2233-B
     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 at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg2233::MultilevelSpecialization::B<int, int>'}}
-    // expected-note@#defined-here {{defined here}}
+    //   since-cxx11-note@#cwg2233-B {{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 6d4bf5b04d7689..9f94f4bfc5c2b6 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -597,10 +597,10 @@ namespace cwg336 { // cwg336: yes
         void mf2();
       };
     };
-    template<> template<class X> class A<int>::B {}; // #defined-here-cwg336
+    template<> template<class X> class A<int>::B {}; // #cwg336-B
     template<> template<> template<class T> void A<int>::B<double>::mf1(T t) {}
     // expected-error at -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}}
+    //   expected-note@#cwg336-B {{defined here}}
     template<class Y> template<> void A<Y>::B<double>::mf2() {}
     // expected-error at -1 {{nested name specifier 'A<Y>::B<double>::' for declaration does not refer into a class, class template or class template partial specialization}}
   }
@@ -759,7 +759,7 @@ namespace cwg347 { // cwg347: yes
     void g();
   };
 
-  struct derived : base {}; // #defined-here-derived
+  struct derived : base {}; // #cwg347-derived
 
   struct derived::nested {};
   // expected-error at -1 {{no struct named 'nested' in 'cwg347::derived'}}
@@ -767,10 +767,10 @@ namespace cwg347 { // cwg347: yes
   // expected-error at -1 {{no member named 'n' in 'cwg347::derived'}}
   void derived::f() {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg347::derived'}}
-  // expected-note@#defined-here-derived {{defined here}}
+  //   expected-note@#cwg347-derived {{defined here}}
   void derived::g() {}
   // expected-error at -1 {{out-of-line definition of 'g' does not match any declaration in 'cwg347::derived'}}
-  // expected-note@#defined-here-derived {{defined here}}
+  //   expected-note@#cwg347-derived {{defined here}}
 }
 
 // cwg348: na
@@ -1012,20 +1012,20 @@ namespace cwg355 { struct ::cwg355_S s; }
 // cwg356: na
 
 namespace cwg357 { // cwg357: yes
-  template<typename T> struct A { // #defined-here-cwg357-A
+  template<typename T> struct A { // #cwg357-A
     void f() const; // #cwg357-f
   };
   template<typename T> void A<T>::f() {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'A<T>'}}
-  // expected-note@#defined-here-cwg357-A {{defined here}}
-  // expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
+  //   expected-note@#cwg357-A {{defined here}}
+  //   expected-note@#cwg357-f {{member declaration does not match because it is const qualified}}
 
-  struct B { // #defined-here-cwg357-B
+  struct B { // #cwg357-B
     template<typename T> void f();
   };
   template<typename T> void B::f() const {}
   // expected-error at -1 {{out-of-line definition of 'f' does not match any declaration in 'cwg357::B'}}
-  // expected-note@#defined-here-cwg357-B {{defined here}}
+  // expected-note@#cwg357-B {{defined here}}
 }
 
 namespace cwg358 { // cwg358: yes



More information about the cfe-commits mailing list