Implement access declarations.  Most of the work here is parsing them, which
is difficult because they're so terribly, terribly ambiguous.


We implement access declarations in terms of using declarations, which is
quite reasonable.  However, we should really persist the access/using
distinction in the AST and use the appropriate name in diagnostics.  This
isn't a priority, so I'll just file a PR and hope someone else does it. :)

llvm-svn: 91095
diff --git a/clang/lib/Parse/MinimalAction.cpp b/clang/lib/Parse/MinimalAction.cpp
index aa0b89b..8b207fa 100644
--- a/clang/lib/Parse/MinimalAction.cpp
+++ b/clang/lib/Parse/MinimalAction.cpp
@@ -45,6 +45,7 @@
 // Defined out-of-line here because of dependency on AttributeList
 Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
                                                 AccessSpecifier AS,
+                                                bool HasUsingKeyword,
                                                 SourceLocation UsingLoc,
                                                 const CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 34ea9c7..78336bb 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -357,7 +357,7 @@
                    AttrList ? "attributes list" : "using declaration", 
                    tok::semi);
 
-  return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
+  return Actions.ActOnUsingDeclaration(CurScope, AS, true, UsingLoc, SS, Name,
                                        AttrList, IsTypeName, TypenameLoc);
 }
 
@@ -1065,6 +1065,46 @@
 ///
 void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
                                        const ParsedTemplateInfo &TemplateInfo) {
+  // Access declarations.
+  if (!TemplateInfo.Kind &&
+      (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+      TryAnnotateCXXScopeToken() &&
+      Tok.is(tok::annot_cxxscope)) {
+    bool isAccessDecl = false;
+    if (NextToken().is(tok::identifier))
+      isAccessDecl = GetLookAheadToken(2).is(tok::semi);
+    else
+      isAccessDecl = NextToken().is(tok::kw_operator);
+
+    if (isAccessDecl) {
+      // Collect the scope specifier token we annotated earlier.
+      CXXScopeSpec SS;
+      ParseOptionalCXXScopeSpecifier(SS, /*ObjectType*/ 0, false);
+
+      // Try to parse an unqualified-id.
+      UnqualifiedId Name;
+      if (ParseUnqualifiedId(SS, false, true, true, /*ObjectType*/ 0, Name)) {
+        SkipUntil(tok::semi);
+        return;
+      }
+
+      // TODO: recover from mistakenly-qualified operator declarations.
+      if (ExpectAndConsume(tok::semi,
+                           diag::err_expected_semi_after,
+                           "access declaration",
+                           tok::semi))
+        return;
+
+      Actions.ActOnUsingDeclaration(CurScope, AS,
+                                    false, SourceLocation(),
+                                    SS, Name,
+                                    /* AttrList */ 0,
+                                    /* IsTypeName */ false,
+                                    SourceLocation());
+      return;
+    }
+  }
+
   // static_assert-declaration
   if (Tok.is(tok::kw_static_assert)) {
     // FIXME: Check for templates