Simplify and fill out parsing of function bodies.
llvm-svn: 38841
This commit is contained in:
parent
2534b877b4
commit
fff824fe14
|
@ -455,12 +455,14 @@ void Parser::ParseParenDeclarator(Declarator &D) {
|
|||
// NOTE: better to only create a scope if not '()'
|
||||
bool IsVariadic;
|
||||
bool HasPrototype;
|
||||
bool IsEmpty = false;
|
||||
bool ErrorEmitted = false;
|
||||
|
||||
if (Tok.getKind() == tok::r_paren) {
|
||||
// int() -> no prototype, no '...'.
|
||||
IsVariadic = false;
|
||||
HasPrototype = false;
|
||||
IsEmpty = true;
|
||||
} else if (Tok.getKind() == tok::identifier &&
|
||||
0/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
|
||||
// Identifier list. Note that '(' identifier-list ')' is only allowed for
|
||||
|
@ -545,7 +547,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
|
|||
|
||||
// Remember that we parsed a function type, and remember the attributes.
|
||||
D.AddTypeInfo(DeclaratorTypeInfo::getFunction(HasPrototype, IsVariadic,
|
||||
StartLoc));
|
||||
IsEmpty, StartLoc));
|
||||
|
||||
|
||||
// If we have the closing ')', eat it and we're done.
|
||||
|
|
|
@ -187,7 +187,6 @@ void Parser::ParseExternalDeclaration() {
|
|||
///
|
||||
void Parser::ParseDeclarationOrFunctionDefinition() {
|
||||
// Parse the common declaration-specifiers piece.
|
||||
// NOTE: this can not be missing for C99 'declaration's.
|
||||
DeclSpec DS;
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
|
@ -196,41 +195,63 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
|
|||
assert(0 && "Unimp!");
|
||||
|
||||
|
||||
// Parse the declarator.
|
||||
{
|
||||
Declarator DeclaratorInfo(DS, Declarator::FileContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
// Parse the first declarator.
|
||||
Declarator DeclaratorInfo(DS, Declarator::FileContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
// Error parsing the declarator?
|
||||
if (DeclaratorInfo.getIdentifier() == 0) {
|
||||
// If so, skip until the semi-colon or a }.
|
||||
SkipUntil(tok::r_brace, true);
|
||||
if (Tok.getKind() == tok::semi)
|
||||
ConsumeToken();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the declarator was 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
|
||||
DS.StorageClassSpec != DeclSpec::SCS_typedef && // typedef int X()
|
||||
DeclaratorInfo.isInnermostFunctionType()) { // int *X -> not a fn def.
|
||||
assert(0 && "unimp");
|
||||
|
||||
|
||||
}
|
||||
// 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::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.isInnermostFunctionType() &&
|
||||
(Tok.getKind() == tok::l_brace || // int X() {}
|
||||
isDeclarationSpecifier())) { // int X(f) int f; {}
|
||||
ParseFunctionDefinition(DeclaratorInfo);
|
||||
return;
|
||||
} else {
|
||||
if (DeclaratorInfo.isInnermostFunctionType())
|
||||
Diag(Tok, diag::err_expected_fn_body);
|
||||
else
|
||||
Diag(Tok, diag::err_expected_after_declarator);
|
||||
SkipUntil(tok::r_brace, true);
|
||||
if (Tok.getKind() == tok::semi)
|
||||
ConsumeToken();
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, we know that it is not a function definition. Parse the
|
||||
// rest of the init-declarator-list.
|
||||
while (1) {
|
||||
// must be: decl-spec[opt] declarator init-declarator-list
|
||||
// Parse declarator '=' initializer.
|
||||
if (Tok.getKind() == tok::equal)
|
||||
assert(0 && "cannot handle initializer yet!");
|
||||
}
|
||||
|
||||
while (Tok.getKind() == tok::comma) {
|
||||
|
||||
// TODO: install declarator.
|
||||
|
||||
// If we don't have a comma, it is either the end of the list (a ';') or an
|
||||
// error, bail out.
|
||||
if (Tok.getKind() != tok::comma)
|
||||
break;
|
||||
|
||||
// Consume the comma.
|
||||
ConsumeToken();
|
||||
|
||||
// Parse the declarator.
|
||||
Declarator DeclaratorInfo(DS, Declarator::FileContext);
|
||||
// Parse the next declarator.
|
||||
DeclaratorInfo.clear();
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
// declarator '=' initializer
|
||||
if (Tok.getKind() == tok::equal)
|
||||
assert(0 && "cannot handle initializer yet!");
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (Tok.getKind() == tok::semi) {
|
||||
|
@ -244,3 +265,60 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
|
|||
}
|
||||
}
|
||||
|
||||
/// ParseFunctionDefinition - We parsed and verified that the specified
|
||||
/// Declarator is well formed. If this is a K&R-style function, read the
|
||||
/// parameters declaration-list, then start the compound-statement.
|
||||
///
|
||||
/// declaration-specifiers[opt] declarator declaration-list[opt]
|
||||
/// compound-statement [TODO]
|
||||
///
|
||||
void Parser::ParseFunctionDefinition(Declarator &D) {
|
||||
const DeclaratorTypeInfo &FnTypeInfo = D.getTypeObject(0);
|
||||
assert(FnTypeInfo.Kind == DeclaratorTypeInfo::Function &&
|
||||
"This isn't a function declarator!");
|
||||
|
||||
// If this declaration was formed with a K&R-style identifier list for the
|
||||
// arguments, parse declarations for all of the args next.
|
||||
// int foo(a,b) int a; float b; {}
|
||||
if (!FnTypeInfo.Fun.hasPrototype && !FnTypeInfo.Fun.isEmpty) {
|
||||
// Read all the argument declarations.
|
||||
while (isDeclarationSpecifier()) {
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS;
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
Declarator DeclaratorInfo(DS, Declarator::FileContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
while (Tok.getKind() == tok::comma) {
|
||||
// Consume the comma.
|
||||
ConsumeToken();
|
||||
|
||||
// Parse the next declarator.
|
||||
DeclaratorInfo.clear();
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
}
|
||||
|
||||
if (Tok.getKind() == tok::semi) {
|
||||
ConsumeToken();
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_semi_knr_fn_body);
|
||||
// Skip to end of block or statement
|
||||
SkipUntil(tok::l_brace, true);
|
||||
if (Tok.getKind() == tok::semi)
|
||||
ConsumeToken();
|
||||
}
|
||||
}
|
||||
|
||||
// Note, check that we got them all.
|
||||
} else {
|
||||
//if (isDeclarationSpecifier())
|
||||
// Diag('k&r declspecs with prototype?');
|
||||
|
||||
// FIXME: Install the arguments into the current scope.
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -264,6 +264,12 @@ DIAG(err_expected_ident_lparen, ERROR,
|
|||
"expected identifier or '('")
|
||||
DIAG(err_expected_rparen, ERROR,
|
||||
"expected ')'")
|
||||
DIAG(err_expected_semi_knr_fn_body, ERROR,
|
||||
"expected ';' at end of K&R-style function argument declaration list")
|
||||
DIAG(err_expected_fn_body, ERROR,
|
||||
"expected function body after function declarator")
|
||||
DIAG(err_expected_after_declarator, ERROR,
|
||||
"expected '=', ',', ';', 'asm', or '__attribute__' after declarator")
|
||||
|
||||
/// err_matching - this is used as a continuation of a previous error, e.g. to
|
||||
/// specify the '(' when we expected a ')'. This should probably be some
|
||||
|
|
|
@ -172,6 +172,7 @@ struct DeclaratorTypeInfo {
|
|||
/// with ',...)', this is true.
|
||||
bool isVariadic : 1;
|
||||
// TODO: capture argument info.
|
||||
bool isEmpty : 1;
|
||||
};
|
||||
|
||||
union {
|
||||
|
@ -209,12 +210,14 @@ struct DeclaratorTypeInfo {
|
|||
/// getFunction - Return a DeclaratorTypeInfo for a function.
|
||||
///
|
||||
static DeclaratorTypeInfo getFunction(bool hasProto, bool isVariadic,
|
||||
bool isEmpty /*fixme arg info*/,
|
||||
SourceLocation Loc) {
|
||||
DeclaratorTypeInfo I;
|
||||
I.Kind = Function;
|
||||
I.Loc = Loc;
|
||||
I.Fun.hasPrototype = hasProto;
|
||||
I.Fun.isVariadic = isVariadic;
|
||||
I.Fun.isEmpty = isEmpty;
|
||||
return I;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue