]> granicus.if.org Git - clang/commitdiff
When a conditional operator is an rvalue of class type, we need to
authorDouglas Gregor <dgregor@apple.com>
Wed, 19 May 2010 23:40:50 +0000 (23:40 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 19 May 2010 23:40:50 +0000 (23:40 +0000)
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.

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

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/conditional-expr.cpp

index 0737e9f151a6566c014d350b6c69077f64a2c6c9..62b7b4abbc010d82f097195adeeec2e6dd146ceb 100644 (file)
@@ -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()) 
index f1fe8ba79bbb6c2fd7591e1f07c819a57017f591..a09ff2bd417d53f9b1e68403e2615271c57d430f 100644 (file)
@@ -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());
+  }
+}