]> granicus.if.org Git - clang/commitdiff
Enable inline namespaces in the AST.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 31 Aug 2010 00:36:36 +0000 (00:36 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 31 Aug 2010 00:36:36 +0000 (00:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112564 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/DeclBase.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp [new file with mode: 0644]

index 3a93193211a1dae04e0b3727b93c29b05c9c0cbf..4fdcf681514f479a70c87ad628aecc9db4d45a02 100644 (file)
@@ -219,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
 
 /// NamespaceDecl - Represent a C++ namespace.
 class NamespaceDecl : public NamedDecl, public DeclContext {
+  bool IsInline : 1;
+
   SourceLocation LBracLoc, RBracLoc;
 
   // For extended namespace definitions:
@@ -248,28 +250,33 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
 
   NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
     : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
-      NextNamespace(0), OrigOrAnonNamespace(0, true) { }
+      IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
 
 public:
   static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
                                SourceLocation L, IdentifierInfo *Id);
 
-  // \brief Returns true if this is an anonymous namespace declaration.
-  //
-  // For example:
+  /// \brief Returns true if this is an anonymous namespace declaration.
+  ///
+  /// For example:
   /// \code
-  //   namespace {
-  //     ...
-  //   };
-  // \endcode
-  // q.v. C++ [namespace.unnamed]
+  ///   namespace {
+  ///     ...
+  ///   };
+  /// \endcode
+  /// q.v. C++ [namespace.unnamed]
   bool isAnonymousNamespace() const {
     return !getIdentifier();
   }
 
-  /// \brief Returns true if this is a C++0x inline namespace.
+  /// \brief Returns true if this is an inline namespace declaration.
   bool isInline() const {
-    return false;
+    return IsInline;
+  }
+
+  /// \brief Set whether this is an inline namespace declaration.
+  void setInline(bool Inline) {
+    IsInline = Inline;
   }
 
   /// \brief Return the next extended namespace declaration or null if there
index 32550dc6166b438b38ce03938297cad9fdec3a34..d3fdb8050ba5b152ffc5afeb140f9ac5178beb58 100644 (file)
@@ -421,6 +421,10 @@ def err_static_assert_expression_is_not_constant : Error<
   "static_assert expression is not an integral constant expression">;
 def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
 
+def err_inline_namespace_mismatch : Error<
+  "%select{|non-}0inline namespace "
+  "cannot be reopened as %select{non-|}0inline">;
+
 def err_unexpected_friend : Error<
   "friends can only be classes or functions">;
 def ext_enum_friend : ExtWarn<
index 0316124fbe3c2ad3bb25a15435a02ccc76e4c013..ca8837703429655e05c8034a50329a920ef3c877 100644 (file)
@@ -510,7 +510,7 @@ bool DeclContext::isTransparentContext() const {
   else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord)
     return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
   else if (DeclKind == Decl::Namespace)
-    return false; // FIXME: Check for C++0x inline namespaces
+    return cast<NamespaceDecl>(this)->isInline();
 
   return false;
 }
index 0ffc6398168eda9876ce2c14a050af91d7a95f74..008e384c580b87a35a561fe60d783fa91b045d95 100644 (file)
@@ -3289,6 +3289,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
   NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext,
     (II ? IdentLoc : LBrace) , II);
   Namespc->setLBracLoc(LBrace);
+  Namespc->setInline(InlineLoc.isValid());
 
   Scope *DeclRegionScope = NamespcScope->getParent();
 
@@ -3311,6 +3312,16 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
 
     if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
       // This is an extended namespace definition.
+      if (Namespc->isInline() != OrigNS->isInline()) {
+        // inline-ness must match
+        Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
+          << Namespc->isInline();
+        Diag(OrigNS->getLocation(), diag::note_previous_definition);
+        Namespc->setInvalidDecl();
+        // Recover by ignoring the new namespace's inline status.
+        Namespc->setInline(OrigNS->isInline());
+      }
+
       // Attach this namespace decl to the chain of extended namespace
       // definitions.
       OrigNS->setNextNamespace(Namespc);
@@ -3368,6 +3379,16 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
       assert(!PrevDecl->getNextNamespace());
       Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
       PrevDecl->setNextNamespace(Namespc);
+
+      if (Namespc->isInline() != PrevDecl->isInline()) {
+        // inline-ness must match
+        Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
+          << Namespc->isInline();
+        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+        Namespc->setInvalidDecl();
+        // Recover by ignoring the new namespace's inline status.
+        Namespc->setInline(PrevDecl->isInline());
+      }
     }
 
     CurContext->addDecl(Namespc);
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp
new file mode 100644 (file)
index 0000000..198b013
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+namespace NIL {} // expected-note {{previous definition}}
+inline namespace NIL {} // expected-error {{cannot be reopened as inline}}
+inline namespace IL {} // expected-note {{previous definition}}
+namespace IL {} // expected-error {{cannot be reopened as non-inline}}
+
+namespace {} // expected-note {{previous definition}}
+inline namespace {} // expected-error {{cannot be reopened as inline}}
+namespace X {
+  inline namespace {} // expected-note {{previous definition}}
+  namespace {} // expected-error {{cannot be reopened as non-inline}}
+}