forked from OSchip/llvm-project
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
This commit is contained in:
parent
7cbfa4462f
commit
fa6010b6e4
|
@ -2265,9 +2265,32 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
||||||
|
|
||||||
// After those conversions, one of the following shall hold:
|
// After those conversions, one of the following shall hold:
|
||||||
// -- The second and third operands have the same type; the result
|
// -- The second and third operands have the same type; the result
|
||||||
// is of that type.
|
// is of that type. If the operands have class type, the result
|
||||||
if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy))
|
// 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;
|
return LTy;
|
||||||
|
}
|
||||||
|
|
||||||
// Extension: conditional operator involving vector types.
|
// Extension: conditional operator involving vector types.
|
||||||
if (LTy->isVectorType() || RTy->isVectorType())
|
if (LTy->isVectorType() || RTy->isVectorType())
|
||||||
|
|
|
@ -255,3 +255,23 @@ namespace test1 {
|
||||||
foo(a ? a->x() : 0);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue