forked from OSchip/llvm-project
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:
parent
d3e4ba18ac
commit
ff895c140c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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'?}}
|
||||
|
|
Loading…
Reference in New Issue