diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-12-30 03:27:21 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-12-30 03:27:21 +0000 |
commit | f780abc21c39cd4731b9e38f2d2d9f7d1510bd7b (patch) | |
tree | 9b2482dd8a7c43a95ae186d56d8d334dcfa5130a /lib/Parse | |
parent | fc820a4394a33e4fccfd8283909d425708311d41 (diff) |
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
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 85 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 16 |
3 files changed, 105 insertions, 0 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 23c0c61517..a410dfeda3 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -216,6 +216,8 @@ void Parser::FuzzyParseMicrosoftDeclSpec() { /// 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 @@ Parser::DeclTy *Parser::ParseDeclaration(unsigned Context) { 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 1d3de90060..3236763021 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -131,6 +131,91 @@ Parser::DeclTy *Parser::ParseLinkage(unsigned Context) { &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 e5b40d9a44..3c79d6405c 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -43,6 +43,21 @@ ActionBase::~ActionBase() {} /// 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 @@ Parser::DeclTy *Parser::ParseExternalDeclaration() { ConsumeToken(); } return 0; + case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: case tok::kw_template: |