summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-05-19 23:40:50 +0000
committerDouglas Gregor <dgregor@apple.com>2010-05-19 23:40:50 +0000
commitfa6010b6e4c6f296c5dd99f9933223f16c3c1008 (patch)
tree3f72cc98c36337827d5dab28536d5dcc40897774 /clang
parent7cbfa4462fdf4f042cbc3928f3275490fe644e0d (diff)
downloadbcm5719-llvm-fa6010b6e4c6f296c5dd99f9933223f16c3c1008.tar.gz
bcm5719-llvm-fa6010b6e4c6f296c5dd99f9933223f16c3c1008.zip
When a conditional operator is an rvalue of class type, we need to
create a temporary copy of both the "true" and "false" results. Fixes the Boost.Interprocess failures. Daniel did all the hard work of tracking down the issue, I get to type up the trivial fix for this horrible miscompile. llvm-svn: 104184
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp27
-rw-r--r--clang/test/SemaCXX/conditional-expr.cpp20
2 files changed, 45 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 0737e9f151a..62b7b4abbc0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2265,9 +2265,32 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// After those conversions, one of the following shall hold:
// -- The second and third operands have the same type; the result
- // is of that type.
- if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy))
+ // is of that type. If the operands have class type, the result
+ // is a prvalue temporary of the result type, which is
+ // copy-initialized from either the second operand or the third
+ // operand depending on the value of the first operand.
+ if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
+ if (LTy->isRecordType()) {
+ // The operands have class type. Make a temporary copy.
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
+ OwningExprResult LHSCopy = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(LHS));
+ if (LHSCopy.isInvalid())
+ return QualType();
+
+ OwningExprResult RHSCopy = PerformCopyInitialization(Entity,
+ SourceLocation(),
+ Owned(RHS));
+ if (RHSCopy.isInvalid())
+ return QualType();
+
+ LHS = LHSCopy.takeAs<Expr>();
+ RHS = RHSCopy.takeAs<Expr>();
+ }
+
return LTy;
+ }
// Extension: conditional operator involving vector types.
if (LTy->isVectorType() || RTy->isVectorType())
diff --git a/clang/test/SemaCXX/conditional-expr.cpp b/clang/test/SemaCXX/conditional-expr.cpp
index f1fe8ba79bb..a09ff2bd417 100644
--- a/clang/test/SemaCXX/conditional-expr.cpp
+++ b/clang/test/SemaCXX/conditional-expr.cpp
@@ -255,3 +255,23 @@ namespace test1 {
foo(a ? a->x() : 0);
}
}
+
+namespace rdar7998817 {
+ class X {
+ X(X&); // expected-note{{declared private here}}
+
+ struct ref { };
+
+ public:
+ X();
+ X(ref);
+
+ operator ref();
+ };
+
+ void f(bool B) {
+ X x;
+ (void)(B? x // expected-error{{calling a private constructor of class 'rdar7998817::X'}}
+ : X());
+ }
+}
OpenPOWER on IntegriCloud