r256985 - PR26048, PR26050: put non-type template parameters and indirect field decls

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 6 14:49:11 PST 2016


Author: rsmith
Date: Wed Jan  6 16:49:11 2016
New Revision: 256985

URL: http://llvm.org/viewvc/llvm-project?rev=256985&view=rev
Log:
PR26048, PR26050: put non-type template parameters and indirect field decls
into IDNS_Tag in C++, because they conflict with redeclarations of tags. (This
doesn't affect elaborated-type-specifier lookup, which looks for IDNS_Type in
C++).

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp
    cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Jan  6 16:49:11 2016
@@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDe
   NamedDecl **Chaining;
   unsigned ChainingSize;
 
-  IndirectFieldDecl(DeclContext *DC, SourceLocation L,
+  IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
                     DeclarationName N, QualType T,
-                    NamedDecl **CH, unsigned CHS)
-    : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
+                    NamedDecl **CH, unsigned CHS);
 
 public:
   static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Jan  6 16:49:11 2016
@@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(AST
 
 void IndirectFieldDecl::anchor() { }
 
+IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
+                                     SourceLocation L, DeclarationName N,
+                                     QualType T, NamedDecl **CH, unsigned CHS)
+    : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {
+  // In C++, indirect field declarations conflict with tag declarations in the
+  // same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
+  if (C.getLangOpts().CPlusPlus)
+    IdentifierNamespace |= IDNS_Tag;
+}
+
 IndirectFieldDecl *
 IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
                           IdentifierInfo *Id, QualType T, NamedDecl **CH,
                           unsigned CHS) {
-  return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS);
+  return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS);
 }
 
 IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
                                                          unsigned ID) {
-  return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(),
+  return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
                                        DeclarationName(), QualType(), nullptr,
                                        0);
 }

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Wed Jan  6 16:49:11 2016
@@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceFor
     case Var:
     case ImplicitParam:
     case ParmVar:
-    case NonTypeTemplateParm:
     case ObjCMethod:
     case ObjCProperty:
     case MSProperty:
@@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceFor
     case IndirectField:
       return IDNS_Ordinary | IDNS_Member;
 
+    case NonTypeTemplateParm:
+      // Non-type template parameters are not found by lookups that ignore
+      // non-types, but they are found by redeclaration lookups for tag types,
+      // so we include them in the tag namespace.
+      return IDNS_Ordinary | IDNS_Tag;
+
     case ObjCCompatibleAlias:
     case ObjCInterface:
       return IDNS_Ordinary | IDNS_Type;

Modified: cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp (original)
+++ cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp Wed Jan  6 16:49:11 2016
@@ -13,14 +13,12 @@ struct X {
     int d; // expected-error {{member of anonymous union redeclares}}
     int e; // expected-note {{previous}}
     int f; // expected-note {{previous}}
-    int g;
+    int g; // expected-note {{previous}}
     int h; // expected-note {{previous}}
   };
 
   int e; // expected-error {{duplicate member}}
   void f(); // expected-error {{redefinition}}
-  // FIXME: This is ill-formed, even though one name is a tag and the other is
-  // an anonymous union member. Reject this.
-  struct g;
+  struct g; // expected-error {{redefinition}}
   typedef int h; // expected-error {{redefinition}}
 };

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=256985&r1=256984&r2=256985&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 Wed Jan  6 16:49:11 2016
@@ -5,7 +5,7 @@ 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 16{{declared here}}
+template<typename T> struct Y { // expected-note 17{{declared here}}
   template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
 
   struct B {
@@ -56,9 +56,74 @@ template<typename T> struct Y { // expec
     namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}}
   }
 
+  // FIXME: These diagnostics are poorly worded. Lookup for the elaborated type
+  // specifier finds the template parameter in this case, which is ill-formed
+  // because it's not a struct.
+  void f() {
+    struct T *p; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
   friend struct T; // expected-error {{declaration of 'T' shadows template parameter}}
 };
 
+template<int T> struct Z { // expected-note 15{{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}}
+  };
+  struct C {
+    template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct D {
+    struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct E {
+    typedef int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct F {
+    using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct G {
+    int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct H {
+    static int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct I {
+    void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct J {
+    enum T { e }; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  struct K {
+    enum E { T }; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+
+  void a() {
+    extern int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void b() {
+    int T; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void c() {
+    try {}
+    catch (int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void d() {
+    void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+  void e() {
+    namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+
+  // These cases are valid when 'T' is a non-type template parameter, as T
+  // names an injected struct ::T, which doesn't shadow the template parameter.
+  void f() {
+    struct T *p;
+  }
+  friend struct T;
+};
+
 template<typename T> // expected-note {{declared here}}
 void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
 




More information about the cfe-commits mailing list