Parser support for C++ using directives, from Piotr Rak

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61486 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 23c0c61..a410dfe 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -216,6 +216,8 @@
 ///           others                   [FIXME]
 /// [C++]   template-declaration
 /// [C++]   namespace-definition
+/// [C++]   using-directive
+/// [C++]   using-declaration [TODO]
 ///         others... [FIXME]
 ///
 Parser::DeclTy *Parser::ParseDeclaration(unsigned Context) {
@@ -225,6 +227,8 @@
     return ParseTemplateDeclaration(Context);
   case tok::kw_namespace:
     return ParseNamespace(Context);
+  case tok::kw_using:
+    return ParseUsingDirectiveOrDeclaration(Context);
   default:
     return ParseSimpleDeclaration(Context);
   }
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 1d3de90..3236763 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -131,6 +131,91 @@
                                   &InnerDecls.front(), InnerDecls.size());
 }
 
+/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
+/// using-directive. Assumes that current token is 'using'.
+Parser::DeclTy *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context)
+{
+  assert(Tok.is(tok::kw_using) && "Not using token");
+
+  // Eat 'using'.
+  SourceLocation UsingLoc = ConsumeToken();
+
+  if (Tok.is(tok::kw_namespace)) {
+    // Next token after 'using' is 'namespace' so it must be using-directive
+    return ParseUsingDirective(Context, UsingLoc);
+  } else {
+    // Otherwise, it must be using-declaration.
+    return ParseUsingDeclaration(Context, UsingLoc); //FIXME: It is just stub.
+  }
+}
+
+/// ParseUsingDirective - Parse C++ using-directive, assumes
+/// that current token is 'namespace' and 'using' was already parsed.
+///
+///       using-directive: [C++ 7.3.p4: namespace.udir]
+///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
+///                 namespace-name ;
+/// [GNU] using-directive:
+///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
+///                 namespace-name attributes[opt] ;
+///
+Parser::DeclTy *Parser::ParseUsingDirective(unsigned Context,
+                                            SourceLocation UsingLoc) {
+  assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
+
+  // Eat 'namespace'.
+  SourceLocation NamespcLoc = ConsumeToken();
+
+  CXXScopeSpec SS;
+  // Parse (optional) nested-name-specifier.
+  MaybeParseCXXScopeSpecifier(SS);
+
+  AttributeList *AttrList = 0;
+  IdentifierInfo *NamespcName = 0;
+  SourceLocation IdentLoc = SourceLocation();
+
+  // Parse namespace-name.
+  if (!SS.isInvalid() && Tok.is(tok::identifier)) {
+    // Parse identifier.
+    NamespcName = Tok.getIdentifierInfo();
+    IdentLoc = ConsumeToken();
+    // Parse (optional) attributes (most likely GNU strong-using extension)
+    if (Tok.is(tok::kw___attribute)) {
+      AttrList = ParseAttributes();
+    }
+    // Eat ';'.
+    if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                     AttrList? "attributes list" : "namespace name")) {
+        SkipUntil(tok::semi);
+        return 0;
+    }
+  } else {
+    Diag(Tok, diag::err_expected_namespace_name);
+    // If there was invalid namespace name, skip to end of decl, and eat ';'.
+    SkipUntil(tok::semi);
+    // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
+    return 0;
+  }
+
+  return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
+                                      IdentLoc ,NamespcName, AttrList);
+}
+
+/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
+/// 'using' was already seen.
+///
+///     using-declaration: [C++ 7.3.p3: namespace.udecl]
+///       'using' 'typename'[opt] ::[opt] nested-name-specifier
+///               unqualified-id [TODO]
+///       'using' :: unqualified-id [TODO]
+///
+Parser::DeclTy *Parser::ParseUsingDeclaration(unsigned Context,
+                                              SourceLocation UsingLoc) {
+  assert(false && "Not implemented");
+  // FIXME: Implement parsing.
+  return 0;
+}
+
 /// ParseClassName - Parse a C++ class-name, which names a class. Note
 /// that we only check that the result names a type; semantic analysis
 /// will need to verify that the type names a class. The result is
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index e5b40d9..3c79d64 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -43,6 +43,21 @@
 ///  Out-of-line virtual destructor to provide home for Action class.
 Action::~Action() {}
 
+// Defined out-of-line here because of dependecy on AttributeList
+Action::DeclTy *Action::ActOnUsingDirective(Scope *CurScope,
+                                            SourceLocation UsingLoc,
+                                            SourceLocation NamespcLoc,
+                                            const CXXScopeSpec &SS,
+                                            SourceLocation IdentLoc,
+                                            IdentifierInfo *NamespcName,
+                                            AttributeList *AttrList) {
+
+  // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+  // passed AttributeList, however other actions don't free it, is it
+  // temporary state or bug?
+  delete AttrList;
+  return 0;
+}
 
 DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
   return Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID);
@@ -358,6 +373,7 @@
       ConsumeToken();
     }
     return 0;
+  case tok::kw_using:
   case tok::kw_namespace:
   case tok::kw_typedef:
   case tok::kw_template: