r272366 - Fix recognition of shadowed template parameter

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 9 21:39:07 PDT 2016


Author: sepavloff
Date: Thu Jun  9 23:39:07 2016
New Revision: 272366

URL: http://llvm.org/viewvc/llvm-project?rev=272366&view=rev
Log:
Fix recognition of shadowed template parameter

Crash reported in PR28023 is caused by the fact that non-type template
parameters are found by tag name lookup.  In the code provided in that PR:

template<int V> struct A {
  struct B {
    template <int> friend struct V;
  };
};

the template parameter V is found when lookup for redeclarations of 'struct V'
is made. Latter on the error about shadowing of 'V' is emitted but the semantic
context of 'struct V' is already determined wrong: 'struct A' instead of
translation unit.

The fix moves the check for shadowing toward the beginning of the method and
thus prevents from wrong context calculations.

This change fixes PR28023.

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=272366&r1=272365&r2=272366&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jun  9 23:39:07 2016
@@ -929,6 +929,13 @@ Sema::CheckClassTemplate(Scope *S, unsig
   if (Previous.begin() != Previous.end())
     PrevDecl = (*Previous.begin())->getUnderlyingDecl();
 
+  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+    // Maybe we will complain about the shadowed template parameter.
+    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+    // Just pretend that we didn't see the previous declaration.
+    PrevDecl = nullptr;
+  }
+
   // If there is a previous declaration with the same name, check
   // whether this is a valid redeclaration.
   ClassTemplateDecl *PrevClassTemplate
@@ -1054,12 +1061,7 @@ Sema::CheckClassTemplate(Scope *S, unsig
         // definition, as part of error recovery?
         return true;
       }
-    }    
-  } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
-    // Maybe we will complain about the shadowed template parameter.
-    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
-    // Just pretend that we didn't see the previous declaration.
-    PrevDecl = nullptr;
+    }
   } else if (PrevDecl) {
     // C++ [temp]p5:
     //   A class template shall not have the same name as any other

Modified: cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp?rev=272366&r1=272365&r2=272366&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp Thu Jun  9 23:39:07 2016
@@ -5,11 +5,11 @@ namespace N {}
 template<typename T, // expected-note {{declared here}}
          typename T> struct X {}; // expected-error {{declaration of 'T' shadows template parameter}}
 
-template<typename T> struct Y { // expected-note 17{{declared here}}
+template<typename T> struct Y { // expected-note 18{{declared here}}
   template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
 
   struct B {
-    template<typename> struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}}
+    template<typename> struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
   };
   struct C {
     template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
@@ -65,11 +65,11 @@ template<typename T> struct Y { // expec
   friend struct T; // expected-error {{declaration of 'T' shadows template parameter}}
 };
 
-template<int T> struct Z { // expected-note 15{{declared here}}
+template<int T> struct Z { // expected-note 16{{declared here}}
   template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
 
   struct B {
-    template<typename> struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}}
+    template<typename> struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
   };
   struct C {
     template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
@@ -129,7 +129,8 @@ void f(int T) {} // expected-error {{dec
 
 // 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 {};
+  template<typename T> struct T {};  // expected-error{{declaration of 'T' shadows template parameter}}
+                                     // expected-note at -1{{template parameter is declared here}}
 }
 namespace B {
   template<typename T> void T() {}
@@ -137,3 +138,13 @@ namespace B {
 namespace C {
   template<typename T> int T;
 }
+
+namespace PR28023 {
+template<int V>  // expected-note{{template parameter is declared here}}
+struct A {
+  struct B {
+    template <int> friend struct V;  // expected-error{{declaration of 'V' shadows template parameter}}
+  };
+};
+A<0>::B a;
+}




More information about the cfe-commits mailing list