mirror of https://github.com/microsoft/clang.git
PR35039: Materialize temporary objects before wrapping them in an
OpaqueValueExpr in a GNU binary conditional expression. It's not meaningful for a non-materialized temporary object to be used as a common subexpression of multiple expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316836 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5d548d284e
commit
abf6311767
|
@ -7242,6 +7242,16 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
|
|||
commonExpr = commonRes.get();
|
||||
}
|
||||
|
||||
// If the common expression is a class or array prvalue, materialize it
|
||||
// so that we can safely refer to it multiple times.
|
||||
if (commonExpr->isRValue() && (commonExpr->getType()->isRecordType() ||
|
||||
commonExpr->getType()->isArrayType())) {
|
||||
ExprResult MatExpr = TemporaryMaterializationConversion(commonExpr);
|
||||
if (MatExpr.isInvalid())
|
||||
return ExprError();
|
||||
commonExpr = MatExpr.get();
|
||||
}
|
||||
|
||||
opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
|
||||
commonExpr->getType(),
|
||||
commonExpr->getValueKind(),
|
||||
|
|
|
@ -834,7 +834,8 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: Preds (1): B4
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B4]
|
||||
// CHECK: 1: [B7.2] ?: [B6.6]
|
||||
// CXX98: 1: [B7.2] ?: [B6.6]
|
||||
// CXX11: 1: [B7.3] ?: [B6.6]
|
||||
// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CHECK: 3: [B4.2]
|
||||
// CHECK: 4: [B4.3] (CXXConstructExpr, class A)
|
||||
|
@ -843,10 +844,13 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: Preds (2): B5 B6
|
||||
// CHECK: Succs (2): B3 B2
|
||||
// CHECK: [B5]
|
||||
// CHECK: 1: [B7.2] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CHECK: 2: [B5.1]
|
||||
// CHECK: 3: [B5.2] (CXXConstructExpr, class A)
|
||||
// CHECK: 4: [B5.3] (BindTemporary)
|
||||
// CXX98: 1: [B7.2] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CXX98: 2: [B5.1]
|
||||
// CXX98: 3: [B5.2] (CXXConstructExpr, class A)
|
||||
// CXX98: 4: [B5.3] (BindTemporary)
|
||||
// CXX11: 1: [B7.3] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CXX11: 2: [B5.1] (CXXConstructExpr, class A)
|
||||
// CXX11: 3: [B5.2] (BindTemporary)
|
||||
// CHECK: Preds (1): B7
|
||||
// CHECK: Succs (1): B4
|
||||
// CHECK: [B6]
|
||||
|
@ -861,10 +865,15 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: [B7]
|
||||
// CHECK: 1: A() (CXXConstructExpr, class A)
|
||||
// CHECK: 2: [B7.1] (BindTemporary)
|
||||
// CHECK: 3: [B7.2].operator bool
|
||||
// CHECK: 4: [B7.2]
|
||||
// CHECK: 5: [B7.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CHECK: T: [B7.5] ? ... : ...
|
||||
// CXX98: 3: [B7.2].operator bool
|
||||
// CXX98: 4: [B7.2]
|
||||
// CXX98: 5: [B7.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CXX98: T: [B7.5] ? ... : ...
|
||||
// CXX11: 3: [B7.2]
|
||||
// CXX11: 4: [B7.3].operator bool
|
||||
// CXX11: 5: [B7.3]
|
||||
// CXX11: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CXX11: T: [B7.6] ? ... : ...
|
||||
// CHECK: Preds (1): B8
|
||||
// CHECK: Succs (2): B5 B6
|
||||
// CHECK: [B0 (EXIT)]
|
||||
|
@ -886,7 +895,8 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: Preds (1): B4
|
||||
// CHECK: Succs (1): B1
|
||||
// CHECK: [B4]
|
||||
// CHECK: 1: [B7.4] ?: [B6.6]
|
||||
// CXX98: 1: [B7.4] ?: [B6.6]
|
||||
// CXX11: 1: [B7.5] ?: [B6.6]
|
||||
// CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CHECK: 3: [B4.2]
|
||||
// CHECK: 4: [B7.2]([B4.3])
|
||||
|
@ -894,10 +904,13 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: Preds (2): B5 B6
|
||||
// CHECK: Succs (2): B3 B2
|
||||
// CHECK: [B5]
|
||||
// CHECK: 1: [B7.4] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CHECK: 2: [B5.1]
|
||||
// CHECK: 3: [B5.2] (CXXConstructExpr, class A)
|
||||
// CHECK: 4: [B5.3] (BindTemporary)
|
||||
// CXX98: 1: [B7.4] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CXX98: 2: [B5.1]
|
||||
// CXX98: 3: [B5.2] (CXXConstructExpr, class A)
|
||||
// CXX98: 4: [B5.3] (BindTemporary)
|
||||
// CXX11: 1: [B7.5] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CXX11: 2: [B5.1] (CXXConstructExpr, class A)
|
||||
// CXX11: 3: [B5.2] (BindTemporary)
|
||||
// CHECK: Preds (1): B7
|
||||
// CHECK: Succs (1): B4
|
||||
// CHECK: [B6]
|
||||
|
@ -914,10 +927,15 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: 2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
|
||||
// CHECK: 3: A() (CXXConstructExpr, class A)
|
||||
// CHECK: 4: [B7.3] (BindTemporary)
|
||||
// CHECK: 5: [B7.4].operator bool
|
||||
// CHECK: 6: [B7.4]
|
||||
// CHECK: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CHECK: T: [B7.7] ? ... : ...
|
||||
// CXX98: 5: [B7.4].operator bool
|
||||
// CXX98: 6: [B7.4]
|
||||
// CXX98: 7: [B7.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CXX98: T: [B7.7] ? ... : ...
|
||||
// CXX11: 5: [B7.4]
|
||||
// CXX11: 6: [B7.5].operator bool
|
||||
// CXX11: 7: [B7.5]
|
||||
// CXX11: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CXX11: T: [B7.8] ? ... : ...
|
||||
// CHECK: Preds (2): B8 B9
|
||||
// CHECK: Succs (2): B5 B6
|
||||
// CHECK: [B8]
|
||||
|
@ -925,7 +943,8 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: Preds (1): B9
|
||||
// CHECK: Succs (1): B7
|
||||
// CHECK: [B9]
|
||||
// CHECK: 1: [B12.2] ?: [B11.6]
|
||||
// CXX98: 1: [B12.2] ?: [B11.6]
|
||||
// CXX11: 1: [B12.3] ?: [B11.6]
|
||||
// CHECK: 2: [B9.1] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CHECK: 3: [B9.2]
|
||||
// CHECK: 4: const A &a = A() ?: A();
|
||||
|
@ -933,10 +952,13 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: Preds (2): B10 B11
|
||||
// CHECK: Succs (2): B8 B7
|
||||
// CHECK: [B10]
|
||||
// CHECK: 1: [B12.2] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CHECK: 2: [B10.1]
|
||||
// CHECK: 3: [B10.2] (CXXConstructExpr, class A)
|
||||
// CHECK: 4: [B10.3] (BindTemporary)
|
||||
// CXX98: 1: [B12.2] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CXX98: 2: [B10.1]
|
||||
// CXX98: 3: [B10.2] (CXXConstructExpr, class A)
|
||||
// CXX98: 4: [B10.3] (BindTemporary)
|
||||
// CXX11: 1: [B12.3] (ImplicitCastExpr, NoOp, const class A)
|
||||
// CXX11: 2: [B10.1] (CXXConstructExpr, class A)
|
||||
// CXX11: 3: [B10.2] (BindTemporary)
|
||||
// CHECK: Preds (1): B12
|
||||
// CHECK: Succs (1): B9
|
||||
// CHECK: [B11]
|
||||
|
@ -951,10 +973,15 @@ int testConsistencyNestedNormalReturn(bool value) {
|
|||
// CHECK: [B12]
|
||||
// CHECK: 1: A() (CXXConstructExpr, class A)
|
||||
// CHECK: 2: [B12.1] (BindTemporary)
|
||||
// CHECK: 3: [B12.2].operator bool
|
||||
// CHECK: 4: [B12.2]
|
||||
// CHECK: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CHECK: T: [B12.5] ? ... : ...
|
||||
// CXX98: 3: [B12.2].operator bool
|
||||
// CXX98: 4: [B12.2]
|
||||
// CXX98: 5: [B12.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CXX98: T: [B12.5] ? ... : ...
|
||||
// CXX11: 3: [B12.2]
|
||||
// CXX11: 4: [B12.3].operator bool
|
||||
// CXX11: 5: [B12.3]
|
||||
// CXX11: 6: [B12.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
|
||||
// CXX11: T: [B12.6] ? ... : ...
|
||||
// CHECK: Preds (1): B13
|
||||
// CHECK: Succs (2): B10 B11
|
||||
// CHECK: [B0 (EXIT)]
|
||||
|
|
|
@ -6,6 +6,8 @@ struct A {
|
|||
A(const A&);
|
||||
~A();
|
||||
|
||||
operator bool();
|
||||
|
||||
int arr[10];
|
||||
};
|
||||
|
||||
|
@ -79,3 +81,27 @@ void i() {
|
|||
|
||||
// CHECK-LABEL: }
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @_Z1jv(
|
||||
void j() {
|
||||
// CHECK: alloca %{{.*}}*
|
||||
// CHECK: %[[OUTERTEMP:.*]] = alloca %{{.*}}
|
||||
// CHECK: %[[INNERTEMP:.*]] = alloca %{{.*}}
|
||||
// CHECK: call void @_ZN1AC1Ei(%{{.*}} %[[INNERTEMP]], i32 1)
|
||||
// CHECK: call zeroext i1 @_ZN1AcvbEv(%{{.*}} %[[INNERTEMP]])
|
||||
// CHECK: br i1
|
||||
//
|
||||
// CHECK: call void @_ZN1AC1EOS_(%{{.*}} %[[OUTERTEMP]], %{{.*}} %[[INNERTEMP]])
|
||||
// CHECK: br label
|
||||
//
|
||||
// CHECK: call void @_ZN1AC1Ei(%{{.*}} %[[OUTERTEMP]], i32 2)
|
||||
// CHECK: br label
|
||||
//
|
||||
// CHECK: call void @_ZN1AD1Ev(%{{.*}} %[[INNERTEMP]])
|
||||
A &&a = A(1) ?: A(2);
|
||||
|
||||
// CHECK: call void @_Z1iv()
|
||||
i();
|
||||
|
||||
// CHECK: call void @_ZN1AD1Ev(%{{.*}} %[[OUTERTEMP]])
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue