merge recovery-2.c into recovery-3.c.

Substantially improve error recovery after broken if conditions by
parsing the full if when we have a semantic error instead of using
parser recovery techniques to recover from a semantic error.

This fixes rdar://6094870 - spurious error after invalid 'if' condition

llvm-svn: 60929
This commit is contained in:
Chris Lattner 2008-12-12 06:19:11 +00:00
parent d8980509b3
commit bc2d77cdf2
3 changed files with 54 additions and 17 deletions

View File

@ -448,20 +448,28 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
// Parse the condition.
OwningExprResult CondExp(Actions);
if (getLang().CPlusPlus) {
SourceLocation LParenLoc = ConsumeParen();
CondExp = ParseCXXCondition();
MatchRHSPunctuation(tok::r_paren, LParenLoc);
} else {
CondExp = ParseSimpleParenExpression();
}
if (CondExp.isInvalid()) {
OwningExprResult CondExp(Actions);
if (getLang().CPlusPlus)
CondExp = ParseCXXCondition();
else
CondExp = ParseExpression();
// If the parser was confused by the condition and we don't have a ')', try to
// recover by skipping ahead to a semi and bailing out. If condexp is
// semantically invalid but we have well formed code, keep going.
if (CondExp.isInvalid() && Tok.isNot(tok::r_paren)) {
SkipUntil(tok::semi);
// Skipping may have stopped if it found the containing ')'. If so, we can
// continue parsing the if statement.
if (Tok.isNot(tok::r_paren))
return StmtError();
}
// Otherwise the condition is valid or the rparen is present.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
// C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
@ -522,6 +530,11 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
IfScope.Exit();
// If the condition was invalid, discard the if statement. We could recover
// better by replacing it with a valid expr, but don't do that yet.
if (CondExp.isInvalid())
return StmtError();
// If the then or else stmt is invalid and the other is valid (and present),
// make turn the invalid one into a null stmt to avoid dropping the other
// part. If both are invalid, return error.

View File

@ -1,8 +0,0 @@
// RUN: clang -fsyntax-only -verify -pedantic %s
// PR2241
float f[] = {
1e, // expected-error {{exponent}}
1ee0 // expected-error {{exponent}}
};

View File

@ -1,5 +1,12 @@
// RUN: clang -fsyntax-only -verify -pedantic %s
// PR2241
float test2241[] = {
1e, // expected-error {{exponent}}
1ee0 // expected-error {{exponent}}
};
// Testcase derived from PR2692
static char *f (char * (*g) (char **, int), char **p, ...) {
char *s;
@ -12,3 +19,28 @@ static char *f (char * (*g) (char **, int), char **p, ...) {
} // expected-error {{expected external declaration}}
// rdar://6094870
int test(int) {
struct { int i; } x;
if (x.hello) // expected-error {{no member named 'hello'}}
test(0);
else
;
if (x.hello == 0) // expected-error {{no member named 'hello'}}
test(0);
else
;
if ((x.hello == 0)) // expected-error {{no member named 'hello'}}
test(0);
else
;
if (x.i == 0)) // expected-error {{expected expression}}
test(0);
else
;
}