]> granicus.if.org Git - clang/commitdiff
Parser support for inline namespaces
authorSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 27 Aug 2010 23:12:46 +0000 (23:12 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 27 Aug 2010 23:12:46 +0000 (23:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112320 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp [new file with mode: 0644]

index ed0f9b0fefc96467d4b551ba0b1a9076d7002609..d9d5014476ad13f3f652f41537dcacf4592a6043 100644 (file)
@@ -128,6 +128,7 @@ def err_expected_semi_after_namespace_name : Error<
   "expected ';' after namespace name">;
 def err_unexpected_namespace_attributes_alias : Error<
   "attributes can not be specified on namespace alias">;
+def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
 def err_namespace_nonnamespace_scope : Error<
   "namespaces can only be defined in global or namespace scope">;
 def err_expected_semi_after_attribute_list : Error<
index 1116c956a44921c53d6ffca3472fc6403e8a56ae..f1c1a5b763fd35e8db8b3bfeadb9761ccbc20009 100644 (file)
@@ -1428,21 +1428,21 @@ private:
   bool isCXX0XAttributeSpecifier(bool FullLookahead = false, 
                                  tok::TokenKind *After = 0);
   
-  Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
+  Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+                       SourceLocation InlineLoc = SourceLocation());
   Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
   Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
-                                             SourceLocation &DeclEnd,
-                                             CXX0XAttributeList Attrs);
+                                         SourceLocation &DeclEnd,
+                                         CXX0XAttributeList Attrs);
   Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
-                                SourceLocation &DeclEnd,
-                                AttributeList *Attr);
+                            SourceLocation &DeclEnd, AttributeList *Attr);
   Decl *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
-                                  SourceLocation &DeclEnd,
-                                  AccessSpecifier AS = AS_none);
+                              SourceLocation &DeclEnd,
+                              AccessSpecifier AS = AS_none);
   Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
   Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
-                                SourceLocation AliasLoc, IdentifierInfo *Alias,
-                                SourceLocation &DeclEnd);
+                            SourceLocation AliasLoc, IdentifierInfo *Alias,
+                            SourceLocation &DeclEnd);
 
   //===--------------------------------------------------------------------===//
   // C++ 9: classes [class] and C structs/unions.
index 974381668b72e8591c766dccea2090148c9bf6ec..907472955e15a2334c96e14dd5eac7ca7c3cd402 100644 (file)
@@ -1988,10 +1988,11 @@ public:
   //===---------------------------- C++ Features --------------------------===//
 
   // Act on C++ namespaces
-  virtual Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
-                                           IdentifierInfo *Ident,
-                                           SourceLocation LBrace,
-                                           AttributeList *AttrList);
+  virtual Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
+                                       SourceLocation IdentLoc,
+                                       IdentifierInfo *Ident,
+                                       SourceLocation LBrace,
+                                       AttributeList *AttrList);
   virtual void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
 
   NamespaceDecl *getStdNamespace() const;
index c73b6085ead8f82366e31bb544ac967820fb22d3..1f81202f014a3bd40923a7dd995f4fbaf764584c 100644 (file)
@@ -323,6 +323,17 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
         << Attr.Range;
     SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
     break;
+  case tok::kw_inline:
+    // Could be the start of an inline namespace.
+    if (getLang().CPlusPlus0x && NextToken().is(tok::kw_namespace)) {
+      if (Attr.HasAttr)
+        Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+          << Attr.Range;
+      SourceLocation InlineLoc = ConsumeToken();
+      SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
+      break;
+    }
+    return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true);
   case tok::kw_namespace:
     if (Attr.HasAttr)
       Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
index df707b22e1a8f93e199aa3933cf372f261c3359d..a62e37bc4339b8cad176f77b22308435e0740977 100644 (file)
 using namespace clang;
 
 /// ParseNamespace - We know that the current token is a namespace keyword. This
-/// may either be a top level namespace or a block-level namespace alias.
+/// may either be a top level namespace or a block-level namespace alias. If
+/// there was an inline keyword, it has already been parsed.
 ///
 ///       namespace-definition: [C++ 7.3: basic.namespace]
 ///         named-namespace-definition
 ///         unnamed-namespace-definition
 ///
 ///       unnamed-namespace-definition:
-///         'namespace' attributes[opt] '{' namespace-body '}'
+///         'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
 ///
 ///       named-namespace-definition:
 ///         original-namespace-definition
 ///         extension-namespace-definition
 ///
 ///       original-namespace-definition:
-///         'namespace' identifier attributes[opt] '{' namespace-body '}'
+///         'inline'[opt] 'namespace' identifier attributes[opt]
+///             '{' namespace-body '}'
 ///
 ///       extension-namespace-definition:
-///         'namespace' original-namespace-name '{' namespace-body '}'
+///         'inline'[opt] 'namespace' original-namespace-name
+///             '{' namespace-body '}'
 ///
 ///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
 ///         'namespace' identifier '=' qualified-namespace-specifier ';'
 ///
 Decl *Parser::ParseNamespace(unsigned Context,
-                             SourceLocation &DeclEnd) {
+                             SourceLocation &DeclEnd,
+                             SourceLocation InlineLoc) {
   assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
   SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.
 
@@ -76,6 +80,9 @@ Decl *Parser::ParseNamespace(unsigned Context,
   if (Tok.is(tok::equal)) {
     if (AttrList)
       Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+    if (InlineLoc.isValid())
+      Diag(InlineLoc, diag::err_inline_namespace_alias)
+          << FixItHint::CreateRemoval(InlineLoc);
 
     return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
   }
@@ -100,8 +107,8 @@ Decl *Parser::ParseNamespace(unsigned Context,
   ParseScope NamespaceScope(this, Scope::DeclScope);
 
   Decl *NamespcDecl =
-    Actions.ActOnStartNamespaceDef(getCurScope(), IdentLoc, Ident, LBrace,
-                                   AttrList.get());
+    Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, IdentLoc, Ident,
+                                   LBrace, AttrList.get());
 
   PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
                                       "parsing namespace");
index a5002b011921da97168ed70268d4b62ba74c2957..54053435322abbb024d7613f8e7058b18f4edcd0 100644 (file)
@@ -482,6 +482,15 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
       SourceLocation DeclEnd;
       return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
     }
+
+  case tok::kw_inline:
+    if (getLang().CPlusPlus0x && NextToken().is(tok::kw_namespace)) {
+      // Inline namespaces
+      SourceLocation DeclEnd;
+      return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+    }
+    goto dont_know;
+
   case tok::kw_extern:
     if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
       // Extern templates
@@ -491,12 +500,11 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
       return Actions.ConvertDeclToDeclGroup(
                   ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd));
     }
-
     // FIXME: Detect C++ linkage specifications here?
-
-    // Fall through to handle other declarations or function definitions.
+    goto dont_know;
 
   default:
+  dont_know:
     // We can't tell whether this is a function-definition or declaration yet.
     if (DS)
       return ParseDeclarationOrFunctionDefinition(*DS, Attr.AttrList);
index 513836a002c723ec4a8e74a7c288d02765b85477..676af80c730af342e3bfcd74fa2592203ffcd612 100644 (file)
@@ -3280,6 +3280,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
 /// ActOnStartNamespaceDef - This is called at the start of a namespace
 /// definition.
 Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+                                   SourceLocation InlineLoc,
                                    SourceLocation IdentLoc,
                                    IdentifierInfo *II,
                                    SourceLocation LBrace,
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp
new file mode 100644 (file)
index 0000000..04584da
--- /dev/null
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+namespace a {} // original
+namespace a {} // ext
+inline namespace b {} // inline original
+inline namespace b {} // inline ext
+inline namespace {} // inline unnamed