diff options
author | John McCall <rjmccall@apple.com> | 2010-12-04 03:47:34 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-12-04 03:47:34 +0000 |
commit | f6a1648197562e0b133440d612d9af297d0a86cc (patch) | |
tree | 10c1ff179182b53e5f8eb356b7fe1ace0c7dab41 /lib/Sema/SemaExprCXX.cpp | |
parent | e68b9842d2d6adc2c72c81c845a2c68e58d9d3a4 (diff) |
Although we currently have explicit lvalue-to-rvalue conversions, they're
not actually frequently used, because ImpCastExprToType only creates a node
if the types differ. So explicitly create an ICE in the lvalue-to-rvalue
conversion code in DefaultFunctionArrayLvalueConversion() as well as several
other new places, and consistently deal with the consequences throughout the
compiler.
In addition, introduce a new cast kind for loading an ObjCProperty l-value,
and make sure we emit those nodes whenever an ObjCProperty l-value appears
that's not on the LHS of an assignment operator.
This breaks a couple of rewriter tests, which I've x-failed until future
development occurs on the rewriter.
Ted Kremenek kindly contributed the analyzer workarounds in this patch.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120890 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fceb542c79..965328615d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1845,10 +1845,21 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, // Perform the first implicit conversion. switch (SCS.First) { case ICK_Identity: - case ICK_Lvalue_To_Rvalue: // Nothing to do. break; + case ICK_Lvalue_To_Rvalue: + // Should this get its own ICK? + if (From->getObjectKind() == OK_ObjCProperty) { + ConvertPropertyForRValue(From); + if (!From->isRValue()) break; + } + + FromType = FromType.getUnqualifiedType(); + From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue, + From, 0, VK_RValue); + break; + case ICK_Array_To_Pointer: FromType = Context.getArrayDecayedType(FromType); ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay); @@ -2746,14 +2757,14 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // The operands have class type. Make a temporary copy. InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); ExprResult LHSCopy = PerformCopyInitialization(Entity, - SourceLocation(), - Owned(LHS)); + SourceLocation(), + Owned(LHS)); if (LHSCopy.isInvalid()) return QualType(); ExprResult RHSCopy = PerformCopyInitialization(Entity, - SourceLocation(), - Owned(RHS)); + SourceLocation(), + Owned(RHS)); if (RHSCopy.isInvalid()) return QualType(); @@ -3512,21 +3523,42 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen); } -ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) { - if (!FullExpr) return ExprError(); - +/// Perform the conversions required for an expression used in a +/// context that ignores the result. +void Sema::IgnoredValueConversions(Expr *&E) { // C99 6.3.2.1: // [Except in specific positions,] an lvalue that does not have // array type is converted to the value stored in the // designated object (and is no longer an lvalue). - // This rule does not apply in C++; however, in ObjC++, we do want - // to do lvalue-to-rvalue conversion on top-level ObjCProperty - // l-values. - if (!FullExpr->isRValue() && - (!getLangOptions().CPlusPlus || - FullExpr->getObjectKind() == OK_ObjCProperty)) - DefaultFunctionArrayLvalueConversion(FullExpr); + if (E->isRValue()) return; + + // We always want to do this on ObjC property references. + if (E->getObjectKind() == OK_ObjCProperty) { + ConvertPropertyForRValue(E); + if (E->isRValue()) return; + } + + // Otherwise, this rule does not apply in C++, at least not for the moment. + if (getLangOptions().CPlusPlus) return; + + // GCC seems to also exclude expressions of incomplete enum type. + if (const EnumType *T = E->getType()->getAs<EnumType>()) { + if (!T->getDecl()->isComplete()) { + // FIXME: stupid workaround for a codegen bug! + ImpCastExprToType(E, Context.VoidTy, CK_ToVoid); + return; + } + } + + DefaultFunctionArrayLvalueConversion(E); + RequireCompleteType(E->getExprLoc(), E->getType(), + diag::err_incomplete_type); +} + +ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) { + if (!FullExpr) return ExprError(); + IgnoredValueConversions(FullExpr); CheckImplicitConversions(FullExpr); return MaybeCreateCXXExprWithTemporaries(FullExpr); } |