//===--- 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/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "AstGuard.h"
#include "ExtensionRAIIObject.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();
// Enter a scope for the namespace.
ParseScope NamespaceScope(this, Scope::DeclScope);
DeclTy *NamespcDecl =
Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace);
PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
PP.getSourceManager(),
"parsing namespace");
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
ParseExternalDeclaration();
// Leave the namespace scope.
NamespaceScope.Exit();
SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace);
return NamespcDecl;
} else {
Diag(Tok, Ident ? diag::err_expected_lbrace :
diag::err_expected_ident_lbrace);
}
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 string literal!");
llvm::SmallVector<char, 8> 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();
ParseScope LinkageScope(this, Scope::DeclScope);
DeclTy *LinkageSpec
= Actions.ActOnStartLinkageSpecification(CurScope,
/*FIXME: */SourceLocation(),
Loc, LangBufPtr, StrSize,
Tok.is(tok::l_brace)? Tok.getLocation()
: SourceLocation());
if (Tok.isNot(tok::l_brace)) {
ParseDeclarationOrFunctionDefinition();
return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
SourceLocation());
}
SourceLocation LBrace = ConsumeBrace();
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
ParseExternalDeclaration();
}
SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace);
}
/// 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