//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the C++ Declaration portions of the Parser interfaces. // //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" #include "clang/Parse/Scope.h" #include "clang/Basic/Diagnostic.h" using namespace clang; /// ParseNamespace - We know that the current token is a namespace keyword. This /// may either be a top level namespace or a block-level namespace alias. /// /// namespace-definition: [C++ 7.3: basic.namespace] /// named-namespace-definition /// unnamed-namespace-definition /// /// unnamed-namespace-definition: /// 'namespace' attributes[opt] '{' namespace-body '}' /// /// named-namespace-definition: /// original-namespace-definition /// extension-namespace-definition /// /// original-namespace-definition: /// 'namespace' identifier attributes[opt] '{' namespace-body '}' /// /// extension-namespace-definition: /// 'namespace' original-namespace-name '{' namespace-body '}' /// /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] /// 'namespace' identifier '=' qualified-namespace-specifier ';' /// Parser::DeclTy *Parser::ParseNamespace(unsigned Context) { assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. SourceLocation IdentLoc; IdentifierInfo *Ident = 0; if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); IdentLoc = ConsumeToken(); // eat the identifier. } // Read label attributes, if present. DeclTy *AttrList = 0; if (Tok.is(tok::kw___attribute)) // FIXME: save these somewhere. AttrList = ParseAttributes(); if (Tok.is(tok::equal)) { // FIXME: Verify no attributes were present. // FIXME: parse this. } else if (Tok.is(tok::l_brace)) { SourceLocation LBrace = ConsumeBrace(); // FIXME: push a scope, push a namespace decl. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // FIXME capture the decls. ParseExternalDeclaration(); } SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); // FIXME: act on this. } else { unsigned D = Ident ? diag::err_expected_lbrace : diag::err_expected_ident_lbrace; Diag(Tok.getLocation(), D); } return 0; } /// ParseLinkage - We know that the current token is a string_literal /// and just before that, that extern was seen. /// /// linkage-specification: [C++ 7.5p2: dcl.link] /// 'extern' string-literal '{' declaration-seq[opt] '}' /// 'extern' string-literal declaration /// Parser::DeclTy *Parser::ParseLinkage(unsigned Context) { assert(Tok.is(tok::string_literal) && "Not a stringliteral!"); llvm::SmallVector LangBuffer; // LangBuffer is guaranteed to be big enough. LangBuffer.resize(Tok.getLength()); const char *LangBufPtr = &LangBuffer[0]; unsigned StrSize = PP.getSpelling(Tok, LangBufPtr); SourceLocation Loc = ConsumeStringToken(); DeclTy *D = 0; SourceLocation LBrace, RBrace; if (Tok.isNot(tok::l_brace)) { D = ParseDeclaration(Context); } else { LBrace = ConsumeBrace(); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // FIXME capture the decls. D = ParseExternalDeclaration(); } RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); } if (!D) return 0; return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D); }