Improve error recovery in C/ObjC when the first argument of a function

declarator is incorrect.  Not being a typename causes the parser to 
dive down into the K&R identifier list handling stuff, which is almost
never the right thing to do.

Before:

r.c:3:17: error: expected ')'
void bar(intptr y);
                ^
r.c:3:9: note: to match this '('
void bar(intptr y);
        ^
r.c:3:10: error: a parameter list without types is only allowed in a function definition
void bar(intptr y);
         ^

After:

r.c:3:10: error: unknown type name 'intptr'; did you mean 'intptr_t'?
void bar(intptr y);
         ^~~~~~
         intptr_t
r.c:1:13: note: 'intptr_t' declared here
typedef int intptr_t;
            ^

This fixes rdar://7980651 - poor recovery for bad type in the first arg of a C function

llvm-svn: 103783
This commit is contained in:
Chris Lattner 2010-05-14 17:44:56 +00:00
parent d3e4ba18ac
commit ff895c140c
2 changed files with 27 additions and 5 deletions

View File

@ -2941,12 +2941,29 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// Identifier list. Note that '(' identifier-list ')' is only allowed for
// normal declarators, not for abstract-declarators. Get the first
// identifier.
IdentifierInfo *FirstIdent = Tok.getIdentifierInfo();
SourceLocation FirstIdentLoc = Tok.getLocation();
Token FirstTok = Tok;
ConsumeToken(); // eat the first identifier.
return ParseFunctionDeclaratorIdentifierList(LParenLoc, FirstIdent,
FirstIdentLoc, D);
// Identifier lists follow a really simple grammar: the identifiers can
// be followed *only* by a ", moreidentifiers" or ")". However, K&R
// identifier lists are really rare in the brave new modern world, and it
// is very common for someone to typo a type in a non-k&r style list. If
// we are presented with something like: "void foo(intptr x, float y)",
// we don't want to start parsing the function declarator as though it is
// a K&R style declarator just because intptr is an invalid type.
//
// To handle this, we check to see if the token after the first identifier
// is a "," or ")". Only if so, do we parse it as an identifier list.
if (Tok.is(tok::comma) || Tok.is(tok::r_paren))
return ParseFunctionDeclaratorIdentifierList(LParenLoc,
FirstTok.getIdentifierInfo(),
FirstTok.getLocation(), D);
// If we get here, the code is invalid. Push the first identifier back
// into the token stream and parse the first argument as an (invalid)
// normal argument declarator.
PP.EnterToken(Tok);
Tok = FirstTok;
}
}

View File

@ -73,3 +73,8 @@ void foo() {
int X;
X = 4 // expected-error{{expected ';' after expression}}
}
// rdar://7980651
typedef int intptr_t; // expected-note {{'intptr_t' declared here}}
void bar(intptr y); // expected-error {{unknown type name 'intptr'; did you mean 'intptr_t'?}}