From: Chris Lattner Date: Fri, 12 Dec 2008 06:19:11 +0000 (+0000) Subject: merge recovery-2.c into recovery-3.c. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18914bcb22774137ba720e5fcb377150bf2f6de3;p=clang 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60929 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index bde4a50217..263079f138 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -448,20 +448,28 @@ Parser::OwningStmtResult Parser::ParseIfStatement() { ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. + SourceLocation LParenLoc = ConsumeParen(); + OwningExprResult CondExp(Actions); - if (getLang().CPlusPlus) { - SourceLocation LParenLoc = ConsumeParen(); + if (getLang().CPlusPlus) CondExp = ParseCXXCondition(); - MatchRHSPunctuation(tok::r_paren, LParenLoc); - } else { - CondExp = ParseSimpleParenExpression(); - } - - if (CondExp.isInvalid()) { + 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); - return StmtError(); + // 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. @@ -521,6 +529,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 diff --git a/test/Parser/recovery-2.c b/test/Parser/recovery-2.c deleted file mode 100644 index 4451232dca..0000000000 --- a/test/Parser/recovery-2.c +++ /dev/null @@ -1,8 +0,0 @@ -// RUN: clang -fsyntax-only -verify -pedantic %s - - -// PR2241 -float f[] = { - 1e, // expected-error {{exponent}} - 1ee0 // expected-error {{exponent}} -}; diff --git a/test/Parser/recovery-3.c b/test/Parser/recovery-3.c index 955d728827..0c8206fe28 100644 --- a/test/Parser/recovery-3.c +++ b/test/Parser/recovery-3.c @@ -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 + ; +} +