From bef3a5b7e535a42e509705739582930a79621f20 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sun, 11 Oct 2015 17:27:29 +0000 Subject: [PATCH] Keep the IfStmt node even if the condition is invalid This is important to keep the information in IDE or other tools even if the code contains a few errors git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249982 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaStmt.cpp | 28 +++++++++++----------------- test/Misc/ast-dump-invalid.cpp | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index e876fa921e..0afff06f15 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -483,13 +483,6 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - // 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 (!CondVal.get() && !CondVar) { - getCurFunction()->setHasDroppedStmt(); - return StmtError(); - } - ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = nullptr; @@ -497,22 +490,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, ConditionVar = cast(CondVar); CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc); - if (CondResult.isInvalid()) - return StmtError(); } Expr *ConditionExpr = CondResult.getAs(); - if (!ConditionExpr) - return StmtError(); + if (ConditionExpr) { + DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(thenStmt); + if (!elseStmt) { + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, + diag::warn_empty_if_body); + } - if (!elseStmt) { - DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); + DiagnoseUnusedExprResult(elseStmt); + } else { + // Create a dummy Expr for the condition for error recovery + ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(), + Context.BoolTy, VK_RValue); } - DiagnoseUnusedExprResult(elseStmt); - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt); } diff --git a/test/Misc/ast-dump-invalid.cpp b/test/Misc/ast-dump-invalid.cpp index 3b97cc6540..7b02ba1113 100644 --- a/test/Misc/ast-dump-invalid.cpp +++ b/test/Misc/ast-dump-invalid.cpp @@ -18,3 +18,26 @@ void f(T i, T j) { // CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'T' // CHECK-NEXT: |-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'i' 'T' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 'j' 'T' + + +namespace TestInvalidIf { +int g(int i) { + if (invalid_condition) + return 4; + else + return i; +} +} +// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf +// CHECK-NEXT: `-FunctionDecl +// CHECK-NEXT: |-ParmVarDecl +// CHECK-NEXT: `-CompoundStmt +// CHECK-NEXT: `-IfStmt {{.*}} +// CHECK-NEXT: |-<<>> +// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <> '_Bool' +// CHECK-NEXT: |-ReturnStmt {{.*}} +// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 4 +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'i' 'int' + -- 2.40.0