diff options
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 1427814c93..44f231a667 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -253,15 +253,62 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context, /// /// 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 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { 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. |