[clang] d29f7f1 - [clang] Fix ternary operator in the second for loop statement

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sun May 16 10:43:02 PDT 2021


Author: Danila Kutenin
Date: 2021-05-16T10:42:52-07:00
New Revision: d29f7f1a7b47345289d63318e7b2a28cc56e169d

URL: https://github.com/llvm/llvm-project/commit/d29f7f1a7b47345289d63318e7b2a28cc56e169d
DIFF: https://github.com/llvm/llvm-project/commit/d29f7f1a7b47345289d63318e7b2a28cc56e169d.diff

LOG: [clang] Fix ternary operator in the second for loop statement

Fix ternary operator in for loop argument, it was by mistake not set as CanBeForRangeDecl and led to incorrect codegen. It fixes https://bugs.llvm.org/show_bug.cgi?id=50038. I don't have commit rights. Danila Kutenin. kutdanila at yandex.ru

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D102502

Added: 
    clang/test/CodeGenCXX/for-loop-init-ternary-operator-statement.cpp
    clang/test/PCH/for-loop-init-ternary-operator-statement.cpp

Modified: 
    clang/lib/Parse/ParseExprCXX.cpp
    clang/lib/Parse/ParseTentative.cpp
    clang/test/Parser/cxx2a-init-statement.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 644df55bf46e8..93f578edc09e6 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2033,6 +2033,8 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
     DeclGroupPtrTy DG = ParseSimpleDeclaration(DeclaratorContext::ForInit,
                                                DeclEnd, attrs, false, FRI);
     FRI->LoopVar = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
+    assert((FRI->ColonLoc.isValid() || !DG) &&
+           "cannot find for range declaration");
     return Sema::ConditionResult();
   }
 

diff  --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 3bf2bc455bfe8..c0bfbbde40ac8 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -353,8 +353,8 @@ struct Parser::ConditionDeclarationOrInitStatementState {
       if (CanBeForRangeDecl) {
         // Skip until we hit a ')', ';', or a ':' with no matching '?'.
         // The final case is a for range declaration, the rest are not.
+        unsigned QuestionColonDepth = 0;
         while (true) {
-          unsigned QuestionColonDepth = 0;
           P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon},
                       StopBeforeMatch);
           if (P.Tok.is(tok::question))

diff  --git a/clang/test/CodeGenCXX/for-loop-init-ternary-operator-statement.cpp b/clang/test/CodeGenCXX/for-loop-init-ternary-operator-statement.cpp
new file mode 100644
index 0000000000000..a40898b0e84d1
--- /dev/null
+++ b/clang/test/CodeGenCXX/for-loop-init-ternary-operator-statement.cpp
@@ -0,0 +1,42 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @_Z1fv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 0, i32* [[I]], align 4
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP0]], 2
+// CHECK-NEXT:    [[TMP1:%.*]] = zext i1 [[CMP]] to i64
+// CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 1, i32 0
+// CHECK-NEXT:    store i32 [[COND]], i32* [[X]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[X]], align 4
+// CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP2]], 0
+// CHECK-NEXT:    br i1 [[TOBOOL]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[X]], align 4
+// CHECK-NEXT:    store i32 [[TMP3]], i32* [[RETVAL]], align 4
+// CHECK-NEXT:    br label [[RETURN:%.*]]
+// CHECK:       for.inc:
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* [[I]], align 4
+// CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP4]], 1
+// CHECK-NEXT:    store i32 [[INC]], i32* [[I]], align 4
+// CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP2:![0-9]+]]
+// CHECK:       for.end:
+// CHECK-NEXT:    store i32 0, i32* [[RETVAL]], align 4
+// CHECK-NEXT:    br label [[RETURN]]
+// CHECK:       return:
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[RETVAL]], align 4
+// CHECK-NEXT:    ret i32 [[TMP5]]
+//
+int f() {
+  for (int i = 0; int x = i < 2 ? 1 : 0; i++) {
+    return x;
+  }
+  return 0;
+}
+

diff  --git a/clang/test/PCH/for-loop-init-ternary-operator-statement.cpp b/clang/test/PCH/for-loop-init-ternary-operator-statement.cpp
new file mode 100644
index 0000000000000..50819e79e6f6f
--- /dev/null
+++ b/clang/test/PCH/for-loop-init-ternary-operator-statement.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-pch -o %t %s
+// RUN: %clang_cc1 -x ast -ast-print %t | FileCheck %s
+
+int f() {
+  // CHECK: for (int i = 0; x; i++) {
+  for (int i = 0; int x = i < 2 ? 1 : 0; i++) {
+    return x;
+  }
+  return 0;
+}
+

diff  --git a/clang/test/Parser/cxx2a-init-statement.cpp b/clang/test/Parser/cxx2a-init-statement.cpp
index 727ee63d1b927..116e38506d9d2 100644
--- a/clang/test/Parser/cxx2a-init-statement.cpp
+++ b/clang/test/Parser/cxx2a-init-statement.cpp
@@ -15,6 +15,8 @@ void f() {
   int A<0>::*arr2[3];
   for (int n = 5; int A<true ? 0 : 1>::*x : arr2) {}
 
+  for (int i = 0; int x = i < 2 ? 1 : 0; i++) {}
+
   F (*arr3[3])(int);
   for (int n = 5; F (*p)(int n) : arr3) {}
   for (int n = 5; F (*p)(int (n)) : arr3) {}


        


More information about the cfe-commits mailing list