]> granicus.if.org Git - clang/commitdiff
Allow paren casted throw statements inside of ternary expressions
authorDavid Majnemer <david.majnemer@gmail.com>
Sun, 2 Jun 2013 08:40:42 +0000 (08:40 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sun, 2 Jun 2013 08:40:42 +0000 (08:40 +0000)
clang would incorrectly not allow the following:

int x = true ? (throw 1) : 2;

The problem exists because we don't see beyond the parens.
This, in turn, causes us to believe that we are choosing between void
and int which we diagnose as an error.

Instead, allow clang to see the 'throw' inside the parens.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183085 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/CodeGenCXX/throw-expressions.cpp
test/SemaCXX/conditional-expr.cpp

index 439fc1636f500d65ee175fd274f974a26409b871..087fea206d7b8c51a649d5e6b50f59401bb13e92 100644 (file)
@@ -4273,8 +4273,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
     //   ... and one of the following shall hold:
     //   -- The second or the third operand (but not both) is a throw-
     //      expression; the result is of the type of the other and is a prvalue.
-    bool LThrow = isa<CXXThrowExpr>(LHS.get());
-    bool RThrow = isa<CXXThrowExpr>(RHS.get());
+    bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenCasts());
+    bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenCasts());
     if (LThrow && !RThrow)
       return RTy;
     if (RThrow && !LThrow)
index ba8a86881a63de3907ec8ee16f0734ef22252c7c..87c481b25fe6e715f416f4cd6d51419f4844ef21 100644 (file)
@@ -43,3 +43,27 @@ int test5(bool x, bool y, int z) {
 //
 // end:
 // CHECK: ret i32
+
+int test6(bool x, bool y, int z) {
+  return (x ? throw 1 : y) ? z : (throw 2);
+}
+// CHECK: define i32 @_Z5test6bbi(
+// CHECK: br i1
+//
+// x.true:
+// CHECK: call void @__cxa_throw(
+// CHECK-NEXT: unreachable
+//
+// x.false:
+// CHECK: br i1
+//
+// y.true:
+// CHECK: load i32*
+// CHECK: br label
+//
+// y.false:
+// CHECK: call void @__cxa_throw(
+// CHECK-NEXT: unreachable
+//
+// end:
+// CHECK: ret i32
index 692aaefc9d54b72ef5d6b9400e2552425eda062a..5abee4a3c4f857c599e7c9e19e18c0f5bfc0d155 100644 (file)
@@ -81,6 +81,8 @@ void test()
   i1 ? test() : test();
   i1 = i1 ? throw 0 : 0;
   i1 = i1 ? 0 : throw 0;
+  i1 = i1 ? (throw 0) : 0;
+  i1 = i1 ? 0 : (throw 0);
   i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}}
   i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}}
   (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}}