]> granicus.if.org Git - clang/commitdiff
PR26048, PR26050: put non-type template parameters and indirect field decls
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 6 Jan 2016 22:49:11 +0000 (22:49 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 6 Jan 2016 22:49:11 +0000 (22:49 +0000)
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++).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256985 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 046ce70a343b2b2f99d793cce469da18d66f8892..029c1182f26e6a36bcfe5c1fb6d82d61b9b91b1e 100644 (file)
@@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDecl,
   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,
index 42bebc543e3e5399a73c7b08bf67380cdc14ecdf..797e07b4b78b1d7dc4688f5ada58eb7102e6309e 100644 (file)
@@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 
 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);
 }
index 16394e865eb190605b0e51962c9a365cd767ed5f..72587e388e4747451539e041fcd67949b0a3be5f 100644 (file)
@@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     case Var:
     case ImplicitParam:
     case ParmVar:
-    case NonTypeTemplateParm:
     case ObjCMethod:
     case ObjCProperty:
     case MSProperty:
@@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     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;
index 7fef4c5d172c8630d9c9467761f53bbedd4b0bd2..31c9313cf53a96c7aa7386140d1605017d04f0fd 100644 (file)
@@ -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}}
 };
index 06eb1bef7fea2e9537f85aae2a55dd3b4c22b3eb..843b45543fcf8158bf3ea06fa342b3f4811958ba 100644 (file)
@@ -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 { // expected-note 16{{declared here}}
     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}}