From f798f65ccc1ba56a1d34c9228af6e01c09c7a7e8 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 24 May 2012 22:04:19 +0000 Subject: Implement the C++11 discarded value expression rules for volatile lvalues. . llvm-svn: 157420 --- clang/lib/Sema/SemaExprCXX.cpp | 72 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) (limited to 'clang/lib/Sema/SemaExprCXX.cpp') diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index efc13a92843..d98cb87dfb5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5267,6 +5267,61 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen); } +static bool IsSpecialDiscardedValue(Expr *E) { + // In C++11, discarded-value expressions of a certain form are special, + // according to [expr]p10: + // The lvalue-to-rvalue conversion (4.1) is applied only if the + // expression is an lvalue of volatile-qualified type and it has + // one of the following forms: + E = E->IgnoreParens(); + + // — id-expression (5.1.1), + if (isa(E)) + return true; + + // — subscripting (5.2.1), + if (isa(E)) + return true; + + // — class member access (5.2.5), + if (isa(E)) + return true; + + // — indirection (5.3.1), + if (UnaryOperator *UO = dyn_cast(E)) + if (UO->getOpcode() == UO_Deref) + return true; + + if (BinaryOperator *BO = dyn_cast(E)) { + // — pointer-to-member operation (5.5), + if (BO->isPtrMemOp()) + return true; + + // — comma expression (5.18) where the right operand is one of the above. + if (BO->getOpcode() == BO_Comma) + return IsSpecialDiscardedValue(BO->getRHS()); + } + + // — conditional expression (5.16) where both the second and the third + // operands are one of the above, or + if (ConditionalOperator *CO = dyn_cast(E)) + return IsSpecialDiscardedValue(CO->getTrueExpr()) && + IsSpecialDiscardedValue(CO->getFalseExpr()); + // The related edge case of "*x ?: *x". + if (BinaryConditionalOperator *BCO = + dyn_cast(E)) { + if (OpaqueValueExpr *OVE = dyn_cast(BCO->getTrueExpr())) + return IsSpecialDiscardedValue(OVE->getSourceExpr()) && + IsSpecialDiscardedValue(BCO->getFalseExpr()); + } + + // Objective-C++ extensions to the rule. + if (isa(E) || isa(E)) + return true; + + return false; +} + /// Perform the conversions required for an expression used in a /// context that ignores the result. ExprResult Sema::IgnoredValueConversions(Expr *E) { @@ -5291,8 +5346,21 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { return Owned(E); } - // Otherwise, this rule does not apply in C++, at least not for the moment. - if (getLangOpts().CPlusPlus) return Owned(E); + if (getLangOpts().CPlusPlus) { + // The C++11 standard defines the notion of a discarded-value expression; + // normally, we don't need to do anything to handle it, but if it is a + // volatile lvalue with a special form, we perform an lvalue-to-rvalue + // conversion. + if (getLangOpts().CPlusPlus0x && E->isGLValue() && + E->getType().isVolatileQualified() && + IsSpecialDiscardedValue(E)) { + ExprResult Res = DefaultLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + } + return Owned(E); + } // GCC seems to also exclude expressions of incomplete enum type. if (const EnumType *T = E->getType()->getAs()) { -- cgit v1.2.3