[clang] [lldb] [clang] implement CWG1980 and CWG2064: instantiation-dependency improvements (PR #190495)

Matheus Izvekov via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 31 08:35:39 PDT 2026


================
@@ -406,39 +406,41 @@ namespace PR42362 {
 namespace QualConv {
   int *X;
   template<const int *const *P> void f() {
-    using T = decltype(P);
-    using T = const int* const*;
+    using T = decltype(P);       // expected-note  {{previous definition}}
+    using T = const int* const*; // expected-error {{redefinition with different types ('const int *const *' vs 'decltype(P)' (aka 'const int *const *'))}}
   }
   template void f<&X>();
 
   template<const int *const &R> void g() {
-    using T = decltype(R);
-    using T = const int *const &;
+    using T = decltype(R);        // expected-note  {{previous definition}}
+    using T = const int *const &; // expected-error {{redefinition with different types ('const int *const &' vs 'decltype(R)' (aka 'const int *const &'))}}
   }
   template void g<(const int *const&)X>();
 }
 
 namespace FunctionConversion {
   struct a { void c(char *) noexcept; };
   template<void (a::*f)(char*)> void g() {
-    using T = decltype(f);
+    using T = decltype(f);        // expected-note  {{previous definition}}
     using T = void (a::*)(char*); // (not 'noexcept')
+    // expected-error at -1 {{redefinition with different types ('void (a::*)(char *)' vs 'decltype(f)' (aka 'void (a::*)(char *)'))}}
   }
   template void g<&a::c>();
 
   void c() noexcept;
   template<void (*p)()> void h() {
-    using T = decltype(p);
+    using T = decltype(p);// expected-note  {{previous definition}}
     using T = void (*)(); // (not 'noexcept')
+    // expected-error at -1 {{redefinition with different types ('void (*)()' vs 'decltype(p)' (aka 'void (*)()'))}}
   }
   template void h<&c>();
 }
 
 namespace VoidPtr {
   // Note, this is an extension in C++17 but valid in C++20.
   template<void *P> void f() {
-    using T = decltype(P);
-    using T = void*;
+    using T = decltype(P); // expected-note  {{previous definition}}
+    using T = void*;       // expected-error {{redefinition with different types ('void *' vs 'decltype(P)' (aka 'void *'))}}
----------------
mizvekov wrote:

We do extend this outcome in this PR to all declarations, so typedef is included.

It's not only a consistency issue.

It has been long standing practice in WG21 not to mandate that all implementations must track and remember every redeclaration of an entity, that remembering just one would be sufficient.

But that can't lead to consistent outcomes if we allow different redeclarations of the same entity to be subject to different outcomes in substitution. For example, that for a particular template argument, some redeclaration would be invalid and another not.

https://github.com/llvm/llvm-project/pull/190495


More information about the cfe-commits mailing list