llvm-project/clang/lib/Parse/ParseDeclCXX.cpp

120 lines
3.8 KiB
C++

//===--- 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<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();
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);
}