Changes through out the parser and actions/ast interface to return top-level

declarations through the asm streamer.  For a testcase like:

int G;
int H, I, *J;
int func() {}

'clang -parse-print-ast' prints:

Read top-level decl: G
Read top-level decl: H
Read top-level decl: I
Read top-level decl: J
Read top-level decl: func

llvm-svn: 38992
This commit is contained in:
Chris Lattner 2006-10-16 00:33:54 +00:00
parent a11999d83a
commit 2dacc3ff2e
12 changed files with 213 additions and 89 deletions

View File

@ -19,15 +19,17 @@ using namespace clang;
/// Interface to the Builder.cpp file.
///
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo);
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo,
std::vector<Decl*> &LastInGroupList);
namespace {
class ASTStreamer {
Parser P;
std::vector<Decl*> LastInGroupList;
public:
ASTStreamer(Preprocessor &PP, unsigned MainFileID, bool FullLocInfo)
: P(PP, *CreateASTBuilderActions(PP, FullLocInfo)) {
: P(PP, *CreateASTBuilderActions(PP, FullLocInfo, LastInGroupList)) {
PP.EnterSourceFile(MainFileID, 0, true);
// Initialize the parser.
@ -37,9 +39,33 @@ namespace {
/// ReadTopLevelDecl - Parse and return the next top-level declaration.
Decl *ReadTopLevelDecl() {
Parser::DeclTy *Result;
if (P.ParseTopLevelDecl(Result))
return 0;
Result = (Decl*)1; // FIXME!
/// If the previous time through we read something like 'int X, Y', return
/// the next declarator.
if (!LastInGroupList.empty()) {
Result = LastInGroupList.back();
LastInGroupList.pop_back();
return (Decl*)Result;
}
do {
if (P.ParseTopLevelDecl(Result))
return 0; // End of file.
// If we got a null return and something *was* parsed, try again. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
} while (Result == 0);
// If we parsed a declspec with multiple declarators, reverse the list and
// return the first one.
if (!LastInGroupList.empty()) {
LastInGroupList.push_back((Decl*)Result);
std::reverse(LastInGroupList.begin(), LastInGroupList.end());
Result = LastInGroupList.back();
LastInGroupList.pop_back();
}
return (Decl*)Result;
}

View File

@ -31,16 +31,25 @@ class VISIBILITY_HIDDEN ASTBuilder : public Action {
/// FullLocInfo - If this is true, the ASTBuilder constructs AST Nodes that
/// capture maximal location information for each source-language construct.
bool FullLocInfo;
/// LastInGroupList - This vector is populated when there are multiple
/// declarators in a single decl group (e.g. "int A, B, C"). In this case,
/// all but the last decl will be entered into this. This is used by the
/// ASTStreamer.
std::vector<Decl*> &LastInGroupList;
public:
ASTBuilder(Preprocessor &pp, bool fullLocInfo)
: PP(pp), FullLocInfo(fullLocInfo) {}
ASTBuilder(Preprocessor &pp, bool fullLocInfo,
std::vector<Decl*> &prevInGroup)
: PP(pp), FullLocInfo(fullLocInfo), LastInGroupList(prevInGroup) {}
//===--------------------------------------------------------------------===//
// Symbol table tracking callbacks.
//
virtual bool isTypedefName(const IdentifierInfo &II, Scope *S) const;
virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init);
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup);
virtual DeclTy *ParseFunctionDefinition(Scope *S, Declarator &D,
StmtTy *Body);
virtual void PopScope(SourceLocation Loc, Scope *S);
//===--------------------------------------------------------------------===//
@ -103,16 +112,17 @@ bool ASTBuilder::isTypedefName(const IdentifierInfo &II, Scope *S) const {
return D != 0 && D->getDeclSpec().StorageClassSpec == DeclSpec::SCS_typedef;
}
void ASTBuilder::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init) {
Action::DeclTy *
ASTBuilder::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup) {
IdentifierInfo *II = D.getIdentifier();
Decl *PrevDecl = II ? II->getFETokenInfo<Decl>() : 0;
Decl *New;
if (D.isFunctionDeclarator())
New = new FunctionDecl(II, D, Loc, PrevDecl);
New = new FunctionDecl(II, D, PrevDecl);
else
New = new VarDecl(II, D, Loc, PrevDecl);
New = new VarDecl(II, D, PrevDecl);
// If this has an identifier, add it to the scope stack.
if (II) {
@ -120,6 +130,17 @@ void ASTBuilder::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
II->setFETokenInfo(New);
S->AddDecl(II);
}
if (LastInGroup) LastInGroupList.push_back((Decl*)LastInGroup);
return New;
}
Action::DeclTy *
ASTBuilder::ParseFunctionDefinition(Scope *S, Declarator &D, StmtTy *Body) {
FunctionDecl *FD = (FunctionDecl *)ParseDeclarator(S, D, 0, 0);
// TODO: more stuff.
return FD;
}
void ASTBuilder::PopScope(SourceLocation Loc, Scope *S) {
@ -359,9 +380,8 @@ Action::ExprResult ASTBuilder::ParseConditionalOp(SourceLocation QuestionLoc,
/// Interface to the Builder.cpp file.
///
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo) {
return new ASTBuilder(PP, FullLocInfo);
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo,
std::vector<Decl*> &LastInGroupList) {
return new ASTBuilder(PP, FullLocInfo, LastInGroupList);
}

View File

@ -24,11 +24,11 @@ using namespace clang;
namespace {
class ParserPrintActions : public EmptyAction {
/// ParseDeclarator - This callback is invoked when a declarator is parsed and
/// 'Init' specifies the initializer if any. This is for things like:
/// ParseDeclarator - This callback is invoked when a declarator is parsed
/// and 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init) {
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup) {
std::cout << "ParseDeclarator ";
if (IdentifierInfo *II = D.getIdentifier()) {
std::cout << "'" << II->getName() << "'";
@ -38,7 +38,7 @@ namespace {
std::cout << "\n";
// Pass up to EmptyActions so that the symbol table is maintained right.
EmptyAction::ParseDeclarator(Loc, S, D, Init);
return EmptyAction::ParseDeclarator(S, D, Init, LastInGroup);
}
/// PopScope - This callback is called immediately before the specified scope

View File

@ -577,12 +577,11 @@ static void PrintASTs(Preprocessor &PP, unsigned MainFileID) {
ASTStreamerTy *Streamer = ASTStreamer_Init(PP, MainFileID, true);
while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
std::cerr << "Read top-level decl!\n";
//if (const IdentifierInfo *II = D->getIdentifier())
// std::cerr << II->getName() << "\n";
//else
// std::cerr << "\n";
std::cerr << "Read top-level decl: ";
if (const IdentifierInfo *II = D->getIdentifier())
std::cerr << II->getName() << "\n";
else
std::cerr << "\n";
}
ASTStreamer_Terminate(Streamer);

View File

@ -34,10 +34,11 @@ bool EmptyAction::isTypedefName(const IdentifierInfo &II, Scope *S) const {
/// ParseDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
void EmptyAction::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init) {
Action::DeclTy *
EmptyAction::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup) {
// If there is no identifier associated with this declarator, bail out.
if (D.getIdentifier() == 0) return;
if (D.getIdentifier() == 0) return 0;
// Remember whether or not this declarator is a typedef.
TypedefInfo *TI = new TypedefInfo();
@ -50,6 +51,7 @@ void EmptyAction::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
// Remember that this needs to be removed when the scope is popped.
S->AddDecl(&II);
return 0;
}
/// PopScope - When a scope is popped, if any typedefs are now out-of-scope,

View File

@ -112,7 +112,13 @@ void Parser::ParseDeclaration(unsigned Context) {
/// [GNU] declarator simple-asm-expr[opt] attributes[opt]
/// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer
///
void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
Parser::DeclTy *Parser::
ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
// Declarators may be grouped together ("int X, *Y, Z();"). Provide info so
// that they can be chained properly if the actions want this.
Parser::DeclTy *LastDeclInGroup = 0;
// At this point, we know that it is not a function definition. Parse the
// rest of the init-declarator-list.
while (1) {
@ -129,15 +135,16 @@ void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
if (Tok.getKind() == tok::equal) {
ConsumeToken();
Init = ParseInitializer();
if (!Init.isInvalid) {
if (Init.isInvalid) {
SkipUntil(tok::semi);
return;
return 0;
}
}
// Inform the current actions module that we just parsed a declarator.
// TODO: pass asm & attributes.
Actions.ParseDeclarator(Tok.getLocation(), CurScope, D, Init.Val);
LastDeclInGroup = Actions.ParseDeclarator(CurScope, D, Init.Val,
LastDeclInGroup);
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
@ -154,12 +161,14 @@ void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
if (Tok.getKind() == tok::semi) {
ConsumeToken();
return LastDeclInGroup;
} else {
Diag(Tok, diag::err_parse_error);
// Skip to end of block or statement
SkipUntil(tok::r_brace, true);
if (Tok.getKind() == tok::semi)
ConsumeToken();
return 0;
}
}

View File

@ -219,7 +219,7 @@ void Parser::Initialize() {
Declarator D(DS, Declarator::FileContext);
D.SetIdentifier(PP.getIdentifierInfo("__builtin_va_list"),SourceLocation());
Actions.ParseDeclarator(SourceLocation(), CurScope, D, 0);
Actions.ParseDeclarator(CurScope, D, 0, 0);
}
if (Tok.getKind() == tok::eof) // Empty source file is an extension.
@ -232,7 +232,7 @@ bool Parser::ParseTopLevelDecl(DeclTy*& Result) {
Result = 0;
if (Tok.getKind() == tok::eof) return true;
ParseExternalDeclaration();
Result = ParseExternalDeclaration();
return false;
}
@ -274,21 +274,22 @@ void Parser::ParseTranslationUnit() {
/// [GNU] asm-definition:
/// simple-asm-expr ';'
///
void Parser::ParseExternalDeclaration() {
Parser::DeclTy *Parser::ParseExternalDeclaration() {
switch (Tok.getKind()) {
case tok::semi:
Diag(diag::ext_top_level_semi);
ConsumeToken();
break;
// TODO: Invoke action for top-level semicolon.
return 0;
case tok::kw_asm:
ParseSimpleAsm();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
"top-level asm block");
break;
// TODO: Invoke action for top-level asm.
return 0;
default:
// We can't tell whether this is a function-definition or declaration yet.
ParseDeclarationOrFunctionDefinition();
break;
return ParseDeclarationOrFunctionDefinition();
}
}
@ -304,7 +305,7 @@ void Parser::ParseExternalDeclaration() {
/// [!C99] init-declarator-list ';' [TODO]
/// [OMP] threadprivate-directive [TODO]
///
void Parser::ParseDeclarationOrFunctionDefinition() {
Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
@ -316,7 +317,8 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
// if (!DS.isMissingDeclaratorOk()) Diag(...);
ConsumeToken();
return;
// TODO: Return type definition.
return 0;
}
// Parse the first declarator.
@ -328,32 +330,31 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
SkipUntil(tok::r_brace, true);
if (Tok.getKind() == tok::semi)
ConsumeToken();
return;
return 0;
}
// If the declarator is the start of a function definition, handle it.
if (Tok.getKind() == tok::equal || // int X()= -> not a function def
Tok.getKind() == tok::comma || // int X(), -> not a function def
Tok.getKind() == tok::semi || // int X(); -> not a function def
Tok.getKind() == tok::semi || // int X(); -> not a function def
Tok.getKind() == tok::kw_asm || // int X() __asm__ -> not a fn def
Tok.getKind() == tok::kw___attribute) {// int X() __attr__ -> not a fn def
// FALL THROUGH.
} else if (DeclaratorInfo.isFunctionDeclarator() &&
(Tok.getKind() == tok::l_brace || // int X() {}
isDeclarationSpecifier())) { // int X(f) int f; {}
ParseFunctionDefinition(DeclaratorInfo);
return;
return ParseFunctionDefinition(DeclaratorInfo);
} else {
if (DeclaratorInfo.isFunctionDeclarator())
Diag(Tok, diag::err_expected_fn_body);
else
Diag(Tok, diag::err_expected_after_declarator);
SkipUntil(tok::semi);
return;
return 0;
}
// Parse the init-declarator-list for a normal declaration.
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
@ -363,7 +364,7 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
/// declaration-specifiers[opt] declarator declaration-list[opt]
/// compound-statement [TODO]
///
void Parser::ParseFunctionDefinition(Declarator &D) {
Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) {
const DeclaratorTypeInfo &FnTypeInfo = D.getTypeObject(0);
assert(FnTypeInfo.Kind == DeclaratorTypeInfo::Function &&
"This isn't a function declarator!");
@ -393,10 +394,15 @@ void Parser::ParseFunctionDefinition(Declarator &D) {
// If we didn't find the '{', bail out.
if (Tok.getKind() != tok::l_brace)
return;
return 0;
}
// TODO: Get stmt info.
StmtTy *FnBody = 0;
ParseCompoundStatement();
// TODO: Pass argument information.
return Actions.ParseFunctionDefinition(CurScope, D, FnBody);
}
/// ParseAsmStringLiteral - This is just a normal string-literal, but is not

View File

@ -19,15 +19,17 @@ using namespace clang;
/// Interface to the Builder.cpp file.
///
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo);
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo,
std::vector<Decl*> &LastInGroupList);
namespace {
class ASTStreamer {
Parser P;
std::vector<Decl*> LastInGroupList;
public:
ASTStreamer(Preprocessor &PP, unsigned MainFileID, bool FullLocInfo)
: P(PP, *CreateASTBuilderActions(PP, FullLocInfo)) {
: P(PP, *CreateASTBuilderActions(PP, FullLocInfo, LastInGroupList)) {
PP.EnterSourceFile(MainFileID, 0, true);
// Initialize the parser.
@ -37,9 +39,33 @@ namespace {
/// ReadTopLevelDecl - Parse and return the next top-level declaration.
Decl *ReadTopLevelDecl() {
Parser::DeclTy *Result;
if (P.ParseTopLevelDecl(Result))
return 0;
Result = (Decl*)1; // FIXME!
/// If the previous time through we read something like 'int X, Y', return
/// the next declarator.
if (!LastInGroupList.empty()) {
Result = LastInGroupList.back();
LastInGroupList.pop_back();
return (Decl*)Result;
}
do {
if (P.ParseTopLevelDecl(Result))
return 0; // End of file.
// If we got a null return and something *was* parsed, try again. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
} while (Result == 0);
// If we parsed a declspec with multiple declarators, reverse the list and
// return the first one.
if (!LastInGroupList.empty()) {
LastInGroupList.push_back((Decl*)Result);
std::reverse(LastInGroupList.begin(), LastInGroupList.end());
Result = LastInGroupList.back();
LastInGroupList.pop_back();
}
return (Decl*)Result;
}

View File

@ -31,16 +31,25 @@ class VISIBILITY_HIDDEN ASTBuilder : public Action {
/// FullLocInfo - If this is true, the ASTBuilder constructs AST Nodes that
/// capture maximal location information for each source-language construct.
bool FullLocInfo;
/// LastInGroupList - This vector is populated when there are multiple
/// declarators in a single decl group (e.g. "int A, B, C"). In this case,
/// all but the last decl will be entered into this. This is used by the
/// ASTStreamer.
std::vector<Decl*> &LastInGroupList;
public:
ASTBuilder(Preprocessor &pp, bool fullLocInfo)
: PP(pp), FullLocInfo(fullLocInfo) {}
ASTBuilder(Preprocessor &pp, bool fullLocInfo,
std::vector<Decl*> &prevInGroup)
: PP(pp), FullLocInfo(fullLocInfo), LastInGroupList(prevInGroup) {}
//===--------------------------------------------------------------------===//
// Symbol table tracking callbacks.
//
virtual bool isTypedefName(const IdentifierInfo &II, Scope *S) const;
virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init);
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup);
virtual DeclTy *ParseFunctionDefinition(Scope *S, Declarator &D,
StmtTy *Body);
virtual void PopScope(SourceLocation Loc, Scope *S);
//===--------------------------------------------------------------------===//
@ -103,16 +112,17 @@ bool ASTBuilder::isTypedefName(const IdentifierInfo &II, Scope *S) const {
return D != 0 && D->getDeclSpec().StorageClassSpec == DeclSpec::SCS_typedef;
}
void ASTBuilder::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init) {
Action::DeclTy *
ASTBuilder::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup) {
IdentifierInfo *II = D.getIdentifier();
Decl *PrevDecl = II ? II->getFETokenInfo<Decl>() : 0;
Decl *New;
if (D.isFunctionDeclarator())
New = new FunctionDecl(II, D, Loc, PrevDecl);
New = new FunctionDecl(II, D, PrevDecl);
else
New = new VarDecl(II, D, Loc, PrevDecl);
New = new VarDecl(II, D, PrevDecl);
// If this has an identifier, add it to the scope stack.
if (II) {
@ -120,6 +130,17 @@ void ASTBuilder::ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
II->setFETokenInfo(New);
S->AddDecl(II);
}
if (LastInGroup) LastInGroupList.push_back((Decl*)LastInGroup);
return New;
}
Action::DeclTy *
ASTBuilder::ParseFunctionDefinition(Scope *S, Declarator &D, StmtTy *Body) {
FunctionDecl *FD = (FunctionDecl *)ParseDeclarator(S, D, 0, 0);
// TODO: more stuff.
return FD;
}
void ASTBuilder::PopScope(SourceLocation Loc, Scope *S) {
@ -359,9 +380,8 @@ Action::ExprResult ASTBuilder::ParseConditionalOp(SourceLocation QuestionLoc,
/// Interface to the Builder.cpp file.
///
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo) {
return new ASTBuilder(PP, FullLocInfo);
Action *CreateASTBuilderActions(Preprocessor &PP, bool FullLocInfo,
std::vector<Decl*> &LastInGroupList) {
return new ASTBuilder(PP, FullLocInfo, LastInGroupList);
}

View File

@ -36,17 +36,12 @@ class Decl {
/// Type.
/// Kind.
/// Loc - The location of the declaration in the source code.
///
SourceLocation Loc;
/// Scope stack info when parsing, otherwise decl list when scope is popped.
///
Decl *Next;
public:
Decl(IdentifierInfo *Id, const Declarator &D, SourceLocation loc, Decl *next)
: Identifier(Id), DeclarationSpecifier(D.getDeclSpec()), Loc(loc),
Next(next) {}
Decl(IdentifierInfo *Id, const Declarator &D, Decl *next)
: Identifier(Id), DeclarationSpecifier(D.getDeclSpec()), Next(next) {}
const IdentifierInfo *getIdentifier() const { return Identifier; }
@ -60,8 +55,8 @@ public:
class FunctionDecl : public Decl {
// Args etc.
public:
FunctionDecl(IdentifierInfo *Id, const Declarator &D,
SourceLocation Loc, Decl *Next) : Decl(Id, D, Loc, Next) {}
FunctionDecl(IdentifierInfo *Id, const Declarator &D, Decl *Next)
: Decl(Id, D, Next) {}
};
@ -70,8 +65,8 @@ public:
class VarDecl : public Decl {
// Initializer.
public:
VarDecl(IdentifierInfo *Id, const Declarator &D,
SourceLocation Loc, Decl *Next) : Decl(Id, D, Loc, Next) {}
VarDecl(IdentifierInfo *Id, const Declarator &D, Decl *Next)
: Decl(Id, D, Next) {}
};

View File

@ -47,6 +47,7 @@ public:
// Types - Though these don't actually enforce strong typing, they document
// what types are required to be identical for the actions.
typedef void ExprTy;
typedef void StmtTy;
typedef void DeclTy;
typedef void TypeTy;
@ -79,13 +80,32 @@ public:
/// ParseDeclarator - This callback is invoked when a declarator is parsed and
/// 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init) {}
///
/// LastInGroup is non-null for cases where one declspec has multiple
/// declarators on it. For example in 'int A, B', ParseDeclarator will be
/// called with LastInGroup=A when invoked for B.
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D,
ExprTy *Init, DeclTy *LastInGroup) {
return 0;
}
/// ParseFunctionDefinition - This is called when a function definition is
/// parsed. The declarator that is part of this is not passed to
/// ParseDeclarator.
virtual DeclTy *ParseFunctionDefinition(Scope *S, Declarator &D,
// TODO: FORMAL ARG INFO.
StmtTy *Body) {
return 0;
}
/// PopScope - This callback is called immediately before the specified scope
/// is popped and deleted.
virtual void PopScope(SourceLocation Loc, Scope *S) {}
//===--------------------------------------------------------------------===//
// 'External Declaration' (Top Level) Parsing Callbacks.
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
@ -178,8 +198,8 @@ public:
/// ParseDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
/// popped.
virtual void ParseDeclarator(SourceLocation Loc, Scope *S, Declarator &D,
ExprTy *Init);
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup);
/// PopScope - When a scope is popped, if any typedefs are now out-of-scope,
/// they are removed from the IdentifierInfo::FETokenInfo field.

View File

@ -48,6 +48,7 @@ public:
// Type forwarding. All of these are statically 'void*', but they may all be
// different actual classes based on the actions in place.
typedef Action::ExprTy ExprTy;
typedef Action::StmtTy StmtTy;
typedef Action::DeclTy DeclTy;
typedef Action::TypeTy TypeTy;
@ -214,9 +215,9 @@ private:
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
void ParseExternalDeclaration();
void ParseDeclarationOrFunctionDefinition();
void ParseFunctionDefinition(Declarator &D);
DeclTy *ParseExternalDeclaration();
DeclTy *ParseDeclarationOrFunctionDefinition();
DeclTy *ParseFunctionDefinition(Declarator &D);
void ParseSimpleAsm();
void ParseAsmStringLiteral();
@ -285,7 +286,7 @@ private:
// C99 6.7: Declarations.
void ParseDeclaration(unsigned Context);
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclTy *ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
void ParseDeclarationSpecifiers(DeclSpec &DS);
void ParseSpecifierQualifierList(DeclSpec &DS);