Author: Krystian Stasiowski
Date: 2024-01-17T09:13:18-05:00
New Revision: fc0253264445be7f88d4cf0f9129dcb10c2fb84b

URL: 
https://github.com/llvm/llvm-project/commit/fc0253264445be7f88d4cf0f9129dcb10c2fb84b
DIFF: 
https://github.com/llvm/llvm-project/commit/fc0253264445be7f88d4cf0f9129dcb10c2fb84b.diff

LOG: [Clang][Sema] Diagnose function/variable templates that shadow their own 
template parameters (#78274)

Previously, we skipped through template parameter scopes (until we hit a
declaration scope) prior to redeclaration lookup for declarators. For
template declarations, the meant that their template parameters would
not be found and shadowing would not be diagnosed. With these changes
applied, the following declarations are correctly diagnosed:
```cpp
template<typename T> void T(); // error: declaration of 'T' shadows template 
parameter
template<typename U> int U; // error: declaration of 'U' shadows template 
parameter
```

The reason for skipping past non-declaration & template parameter scopes
prior to lookup appears to have been because `GetTypeForDeclarator`
needed this adjusted scope... but it doesn't actually use this parameter
anymore. 

The scope adjustment now happens prior to calling
`ActOnFunctionDeclarator`/`ActOnVariableDeclarator`/`ActOnTypedefDeclarator`
(just in case they depend on this behavior... I didn't check in depth).

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaDecl.cpp
    clang/test/CXX/temp/temp.res/temp.local/p6.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 83fe442dbc15fb..d63781cf8b11bf 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -568,6 +568,7 @@ Improvements to Clang's diagnostics
 - Clang now diagnoses the requirement that non-template friend declarations 
with requires clauses
   and template friend declarations with a constraint that depends on a 
template parameter from an
   enclosing template must be a definition.
+- Clang now diagnoses function/variable templates that shadow their own 
template parameters, e.g. ``template<class T> void T();``.
 
 
 Improvements to Clang's time-trace

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9e6e4ab882c0be..dae98f3a7406e8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6377,12 +6377,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator 
&D,
   } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
     return nullptr;
 
-  // The scope passed in may not be a decl scope.  Zip up the scope tree until
-  // we find one that is.
-  while ((S->getFlags() & Scope::DeclScope) == 0 ||
-         (S->getFlags() & Scope::TemplateParamScope) != 0)
-    S = S->getParent();
-
   DeclContext *DC = CurContext;
   if (D.getCXXScopeSpec().isInvalid())
     D.setInvalidType();
@@ -6535,6 +6529,12 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator 
&D,
   if (getLangOpts().CPlusPlus)
     CheckExtraCXXDefaultArguments(D);
 
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  while ((S->getFlags() & Scope::DeclScope) == 0 ||
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
+    S = S->getParent();
+
   NamedDecl *New;
 
   bool AddToScope = true;

diff  --git a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp 
b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
index e2aa0ff344291d..0702966e568548 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
@@ -127,16 +127,30 @@ template<int T> struct Z { // expected-note 16{{declared 
here}}
 template<typename T> // expected-note {{declared here}}
 void f(int T) {} // expected-error {{declaration of 'T' shadows template 
parameter}}
 
-// FIXME: These are ill-formed: a template-parameter shall not have the same 
name as the template name.
 namespace A {
   template<typename T> struct T {};  // expected-error{{declaration of 'T' 
shadows template parameter}}
                                      // expected-note@-1{{template parameter 
is declared here}}
+  template<typename T> struct U {
+    template<typename V> struct V {}; // expected-error{{declaration of 'V' 
shadows template parameter}}
+                                      // expected-note@-1{{template parameter 
is declared here}}
+  };
 }
 namespace B {
-  template<typename T> void T() {}
+  template<typename T> void T() {} // expected-error{{declaration of 'T' 
shadows template parameter}}
+                                   // expected-note@-1{{template parameter is 
declared here}}
+
+  template<typename T> struct U {
+    template<typename V> void V(); // expected-error{{declaration of 'V' 
shadows template parameter}}
+                                   // expected-note@-1{{template parameter is 
declared here}}
+  };
 }
 namespace C {
-  template<typename T> int T;
+  template<typename T> int T; // expected-error{{declaration of 'T' shadows 
template parameter}}
+                              // expected-note@-1{{template parameter is 
declared here}}
+  template<typename T> struct U {
+    template<typename V> static int V; // expected-error{{declaration of 'V' 
shadows template parameter}}
+                                       // expected-note@-1{{template parameter 
is declared here}}
+  };
 }
 
 namespace PR28023 {


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to