Parsing and AST support for using declarations, from John Thompson!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73812 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 1427814..44f231a 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -253,15 +253,62 @@
 ///
 ///     using-declaration: [C++ 7.3.p3: namespace.udecl]
 ///       'using' 'typename'[opt] ::[opt] nested-name-specifier
-///               unqualified-id [TODO]
-///       'using' :: unqualified-id [TODO]
+///               unqualified-id
+///       'using' :: unqualified-id
 ///
 Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
                                                 SourceLocation UsingLoc,
                                                 SourceLocation &DeclEnd) {
-  assert(false && "Not implemented");
-  // FIXME: Implement parsing.
-  return DeclPtrTy();
+  CXXScopeSpec SS;
+  bool IsTypeName;
+
+  // Ignore optional 'typename'.
+  if (Tok.is(tok::kw_typename)) {
+    ConsumeToken();
+    IsTypeName = true;
+  }
+  else
+    IsTypeName = false;
+
+  // Parse nested-name-specifier.
+  ParseOptionalCXXScopeSpecifier(SS);
+
+  AttributeList *AttrList = 0;
+  IdentifierInfo *TargetName = 0;
+  SourceLocation IdentLoc = SourceLocation();
+
+  // Check nested-name specifier.
+  if (SS.isInvalid()) {
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+  if (Tok.is(tok::annot_template_id)) {
+    Diag(Tok, diag::err_unexpected_template_spec_in_using);
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_expected_ident_in_using);
+    // If there was invalid identifier, skip to end of decl, and eat ';'.
+    SkipUntil(tok::semi);
+    return DeclPtrTy();
+  }
+  
+  // Parse identifier.
+  TargetName = Tok.getIdentifierInfo();
+  IdentLoc = ConsumeToken();
+  
+  // Parse (optional) attributes (most likely GNU strong-using extension).
+  if (Tok.is(tok::kw___attribute))
+    AttrList = ParseAttributes();
+  
+  // Eat ';'.
+  DeclEnd = Tok.getLocation();
+  ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+                   AttrList ? "attributes list" : "namespace name", tok::semi);
+
+  return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS,
+                                      IdentLoc, TargetName, AttrList, IsTypeName);
 }
 
 /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
@@ -790,7 +837,23 @@
     ConsumeToken();
     return ParseCXXClassMemberDeclaration(AS);
   }
-  
+
+  if (Tok.is(tok::kw_using)) {
+    // Eat 'using'.
+    SourceLocation UsingLoc = ConsumeToken();
+
+    if (Tok.is(tok::kw_namespace)) {
+      Diag(UsingLoc, diag::err_using_namespace_in_class);
+      SkipUntil(tok::semi, true, true);
+    }
+    else {
+      SourceLocation DeclEnd;
+      // Otherwise, it must be using-declaration.
+      ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd);
+    }
+    return;
+  }
+
   SourceLocation DSStart = Tok.getLocation();
   // decl-specifier-seq:
   // Parse the common declaration-specifiers piece.