diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-07 22:06:48 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-07 22:06:48 +0000 |
commit | 45edb704d39ccb2681026f475c10b5d4f06ac9a4 (patch) | |
tree | 61a98b57221f9685403617529992ad72fa628fc5 /clang/lib/Sema/SemaExprCXX.cpp | |
parent | 0a8cfc79b7f43720476ef6e45b416dfb5d9cd823 (diff) | |
download | bcm5719-llvm-45edb704d39ccb2681026f475c10b5d4f06ac9a4.tar.gz bcm5719-llvm-45edb704d39ccb2681026f475c10b5d4f06ac9a4.zip |
When building a conditional operator where one operand is a throw-expression
and the other is a glvalue of class type, don't forget to copy-initialize a
temporary when performing the lvalue-to-rvalue conversion on the glvalue.
Strangely, DefaultLvalueConversions misses this part of the lvalue-to-rvalue
conversions.
llvm-svn: 161450
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b47bd970d05..64a12a20395 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4106,7 +4106,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++ // interface pointers. - // C++0x 5.16p1 + // C++11 [expr.cond]p1 // The first expression is contextually converted to bool. if (!Cond.get()->isTypeDependent()) { ExprResult CondRes = CheckCXXBooleanCondition(Cond.take()); @@ -4123,7 +4123,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent()) return Context.DependentTy; - // C++0x 5.16p2 + // C++11 [expr.cond]p2 // If either the second or the third operand has type (cv) void, ... QualType LTy = LHS.get()->getType(); QualType RTy = RHS.get()->getType(); @@ -4136,12 +4136,26 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + + // Finish off the lvalue-to-rvalue conversion by copy-initializing a + // temporary if necessary. DefaultFunctionArrayLvalueConversion doesn't + // do this part for us. + ExprResult &NonVoid = LVoid ? RHS : LHS; + if (NonVoid.get()->getType()->isRecordType() && + NonVoid.get()->isGLValue()) { + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(NonVoid.get()->getType()); + NonVoid = PerformCopyInitialization(Entity, SourceLocation(), NonVoid); + if (NonVoid.isInvalid()) + return QualType(); + } + LTy = LHS.get()->getType(); RTy = RHS.get()->getType(); // ... 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 an rvalue. + // 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()); if (LThrow && !RThrow) @@ -4150,7 +4164,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex return LTy; // -- Both the second and third operands have type void; the result is of - // type void and is an rvalue. + // type void and is a prvalue. if (LVoid && RVoid) return Context.VoidTy; @@ -4167,6 +4181,10 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex // Otherwise, if the second and third operand have different types, and // either has (cv) class type, and attempt is made to convert each of those // operands to the other. + // + // FIXME: In C++11, if both operands have the same value category and the same + // type except for cv-qualification, the types are unified. This is valid: + // volatile int a; int b; volatile int &c = x ? a : b; if (!Context.hasSameType(LTy, RTy) && (LTy->isRecordType() || RTy->isRecordType())) { ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft; |