зеркало из https://github.com/microsoft/clang-1.git
improve error recovery handling broken 'then' or 'else' stmts in
if statements. This implements Sema/if-empty-body.c:f3, silencing a bogus secondary warning. It also improve the location info for the nullstmts created for recovery purposes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43440 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
85f9bceab1
Коммит
b96728d90a
|
@ -512,19 +512,18 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
||||||
bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
|
bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
|
||||||
if (NeedsInnerScope) EnterScope(Scope::DeclScope);
|
if (NeedsInnerScope) EnterScope(Scope::DeclScope);
|
||||||
|
|
||||||
// Read the if condition.
|
// Read the 'then' stmt.
|
||||||
StmtResult CondStmt = ParseStatement();
|
SourceLocation ThenStmtLoc = Tok.getLocation();
|
||||||
|
StmtResult ThenStmt = ParseStatement();
|
||||||
|
|
||||||
// Broken substmt shouldn't prevent the label from being added to the AST.
|
|
||||||
if (CondStmt.isInvalid)
|
|
||||||
CondStmt = Actions.ActOnNullStmt(Tok.getLocation());
|
|
||||||
|
|
||||||
// Pop the 'if' scope if needed.
|
// Pop the 'if' scope if needed.
|
||||||
if (NeedsInnerScope) ExitScope();
|
if (NeedsInnerScope) ExitScope();
|
||||||
|
|
||||||
// If it has an else, parse it.
|
// If it has an else, parse it.
|
||||||
SourceLocation ElseLoc;
|
SourceLocation ElseLoc;
|
||||||
|
SourceLocation ElseStmtLoc;
|
||||||
StmtResult ElseStmt(false);
|
StmtResult ElseStmt(false);
|
||||||
|
|
||||||
if (Tok.is(tok::kw_else)) {
|
if (Tok.is(tok::kw_else)) {
|
||||||
ElseLoc = ConsumeToken();
|
ElseLoc = ConsumeToken();
|
||||||
|
|
||||||
|
@ -535,19 +534,37 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
||||||
NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
|
NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
|
||||||
if (NeedsInnerScope) EnterScope(Scope::DeclScope);
|
if (NeedsInnerScope) EnterScope(Scope::DeclScope);
|
||||||
|
|
||||||
|
ElseStmtLoc = Tok.getLocation();
|
||||||
ElseStmt = ParseStatement();
|
ElseStmt = ParseStatement();
|
||||||
|
|
||||||
// Pop the 'else' scope if needed.
|
// Pop the 'else' scope if needed.
|
||||||
if (NeedsInnerScope) ExitScope();
|
if (NeedsInnerScope) ExitScope();
|
||||||
|
|
||||||
if (ElseStmt.isInvalid)
|
|
||||||
ElseStmt = Actions.ActOnNullStmt(ElseLoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getLang().C99)
|
if (getLang().C99)
|
||||||
ExitScope();
|
ExitScope();
|
||||||
|
|
||||||
return Actions.ActOnIfStmt(IfLoc, CondExp.Val, CondStmt.Val,
|
// 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.
|
||||||
|
if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
|
||||||
|
(ThenStmt.isInvalid && ElseStmt.Val == 0) ||
|
||||||
|
(ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
|
||||||
|
// Both invalid, or one is invalid and other is non-present: delete cond and
|
||||||
|
// return error.
|
||||||
|
Actions.DeleteExpr(CondExp.Val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now if either are invalid, replace with a ';'.
|
||||||
|
if (ThenStmt.isInvalid)
|
||||||
|
ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
|
||||||
|
if (ElseStmt.isInvalid)
|
||||||
|
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
|
||||||
ElseLoc, ElseStmt.Val);
|
ElseLoc, ElseStmt.Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,10 @@ void f1(int a) {
|
||||||
void f2(int a) {
|
void f2(int a) {
|
||||||
if (a) {}
|
if (a) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void f3() {
|
||||||
|
if (1)
|
||||||
|
xx; // expected-error {{use of undeclared identifier}}
|
||||||
|
return; // no empty body warning.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче