[cfe-commits] r91493 - in /cfe/trunk: include/clang/AST/Decl.h lib/Sema/SemaDeclCXX.cpp test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp

John McCall rjmccall at apple.com
Tue Dec 15 18:06:49 PST 2009


Author: rjmccall
Date: Tue Dec 15 20:06:49 2009
New Revision: 91493

URL: http://llvm.org/viewvc/llvm-project?rev=91493&view=rev
Log:
Successive anonymous namespaces name the same scope.  I misinterpreted the
standard the last time.  Fixes PR5766.


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=91493&r1=91492&r2=91493&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Dec 15 20:06:49 2009
@@ -85,13 +85,20 @@
 class TranslationUnitDecl : public Decl, public DeclContext {
   ASTContext &Ctx;
 
+  /// The (most recently entered) anonymous namespace for this
+  /// translation unit, if one has been created.
+  NamespaceDecl *AnonymousNamespace;
+
   explicit TranslationUnitDecl(ASTContext &ctx)
     : Decl(TranslationUnit, 0, SourceLocation()),
       DeclContext(TranslationUnit),
-      Ctx(ctx) {}
+      Ctx(ctx), AnonymousNamespace(0) {}
 public:
   ASTContext &getASTContext() const { return Ctx; }
 
+  NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
+  void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
+
   static TranslationUnitDecl *Create(ASTContext &C);
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
@@ -247,10 +254,15 @@
   // OrigNamespace of the first namespace decl points to itself.
   NamespaceDecl *OrigNamespace, *NextNamespace;
 
+  // The (most recently entered) anonymous namespace inside this
+  // namespace.
+  NamespaceDecl *AnonymousNamespace;
+
   NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
     : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) {
     OrigNamespace = this;
     NextNamespace = 0;
+    AnonymousNamespace = 0;
   }
 public:
   static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
@@ -278,6 +290,16 @@
   }
   void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
 
+  NamespaceDecl *getAnonymousNamespace() const {
+    return AnonymousNamespace;
+  }
+
+  void setAnonymousNamespace(NamespaceDecl *D) {
+    assert(D->isAnonymousNamespace());
+    assert(D->getParent() == this);
+    AnonymousNamespace = D;
+  }
+
   virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
   const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=91493&r1=91492&r2=91493&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Dec 15 20:06:49 2009
@@ -2748,6 +2748,28 @@
     PushOnScopeChains(Namespc, DeclRegionScope);
   } else {
     // Anonymous namespaces.
+    assert(Namespc->isAnonymousNamespace());
+    CurContext->addDecl(Namespc);
+
+    // Link the anonymous namespace into its parent.
+    NamespaceDecl *PrevDecl;
+    DeclContext *Parent = CurContext->getLookupContext();
+    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
+      PrevDecl = TU->getAnonymousNamespace();
+      TU->setAnonymousNamespace(Namespc);
+    } else {
+      NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
+      PrevDecl = ND->getAnonymousNamespace();
+      ND->setAnonymousNamespace(Namespc);
+    }
+
+    // Link the anonymous namespace with its previous declaration.
+    if (PrevDecl) {
+      assert(PrevDecl->isAnonymousNamespace());
+      assert(!PrevDecl->getNextNamespace());
+      Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
+      PrevDecl->setNextNamespace(Namespc);
+    }
 
     // C++ [namespace.unnamed]p1.  An unnamed-namespace-definition
     //   behaves as if it were replaced by
@@ -2765,20 +2787,19 @@
     // declarations semantically contained within an anonymous
     // namespace internal linkage.
 
-    assert(Namespc->isAnonymousNamespace());
-    CurContext->addDecl(Namespc);
-
-    UsingDirectiveDecl* UD
-      = UsingDirectiveDecl::Create(Context, CurContext,
-                                   /* 'using' */ LBrace,
-                                   /* 'namespace' */ SourceLocation(),
-                                   /* qualifier */ SourceRange(),
-                                   /* NNS */ NULL,
-                                   /* identifier */ SourceLocation(),
-                                   Namespc,
-                                   /* Ancestor */ CurContext);
-    UD->setImplicit();
-    CurContext->addDecl(UD);
+    if (!PrevDecl) {
+      UsingDirectiveDecl* UD
+        = UsingDirectiveDecl::Create(Context, CurContext,
+                                     /* 'using' */ LBrace,
+                                     /* 'namespace' */ SourceLocation(),
+                                     /* qualifier */ SourceRange(),
+                                     /* NNS */ NULL,
+                                     /* identifier */ SourceLocation(),
+                                     Namespc,
+                                     /* Ancestor */ CurContext);
+      UD->setImplicit();
+      CurContext->addDecl(UD);
+    }
   }
 
   // Although we could have an invalid decl (i.e. the namespace name is a

Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp?rev=91493&r1=91492&r2=91493&view=diff

==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp Tue Dec 15 20:06:49 2009
@@ -1,7 +1,6 @@
 // RUN: %clang_cc1 -emit-llvm-only -verify %s
 
 // This lame little test was ripped straight from the standard.
-
 namespace {
   int i; // expected-note {{candidate}}
 }
@@ -22,3 +21,22 @@
   A::i++;
   j++;
 }
+
+
+// Test that all anonymous namespaces in a translation unit are
+// considered the same context.
+namespace {
+  class Test3 {}; // expected-note {{previous definition}}
+}
+namespace {
+  class Test3 {}; // expected-error {{redefinition of 'Test3'}}
+}
+
+namespace test4 {
+  namespace {
+    class Test4 {}; // expected-note {{previous definition}}
+  }
+  namespace {
+    class Test4 {}; // expected-error {{redefinition of 'Test4'}}
+  }
+}





More information about the cfe-commits mailing list