diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/Expr.cpp | 46 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 11 |
2 files changed, 51 insertions, 6 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 265788a081..fbc5a67af1 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -824,6 +824,8 @@ const char *CastExpr::getCastKindName() const { return "LValueBitCast"; case CK_LValueToRValue: return "LValueToRValue"; + case CK_GetObjCProperty: + return "GetObjCProperty"; case CK_NoOp: return "NoOp"; case CK_BaseToDerived: @@ -1722,6 +1724,24 @@ Expr *Expr::IgnoreParenCasts() { } } +Expr *Expr::IgnoreParenLValueCasts() { + Expr *E = this; + while (E) { + if (ParenExpr *P = dyn_cast<ParenExpr>(E)) { + E = P->getSubExpr(); + continue; + } + if (CastExpr *P = dyn_cast<CastExpr>(E)) { + if (P->getCastKind() == CK_LValueToRValue) { + E = P->getSubExpr(); + continue; + } + } + break; + } + return E; +} + Expr *Expr::IgnoreParenImpCasts() { Expr *E = this; while (true) { @@ -2043,12 +2063,34 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, return isIntegerConstantExpr(Result, Ctx) && Result == 0; } +/// \brief If this expression is an l-value for an Objective C +/// property, find the underlying property reference expression. +const ObjCPropertyRefExpr *Expr::getObjCProperty() const { + const Expr *E = this; + while (true) { + assert((E->getValueKind() == VK_LValue && + E->getObjectKind() == OK_ObjCProperty) && + "expression is not a property reference"); + E = E->IgnoreParenCasts(); + if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) { + E = BO->getRHS(); + continue; + } + } + + break; + } + + return cast<ObjCPropertyRefExpr>(E); +} + FieldDecl *Expr::getBitField() { Expr *E = this->IgnoreParens(); while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - if (ICE->getValueKind() != VK_RValue && - ICE->getCastKind() == CK_NoOp) + if (ICE->getCastKind() == CK_LValueToRValue || + (ICE->getValueKind() != VK_RValue && ICE->getCastKind() == CK_NoOp)) E = ICE->getSubExpr()->IgnoreParens(); else break; diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index e55545e693..1afc7602fb 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -413,8 +413,10 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { assert(Ctx.getLangOptions().CPlusPlus && "This is only relevant for C++."); // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand. + // Except we override this for writes to ObjC properties. if (E->isAssignmentOp()) - return Cl::CL_LValue; + return (E->getLHS()->getObjectKind() == OK_ObjCProperty + ? Cl::CL_PRValue : Cl::CL_LValue); // C++ [expr.comma]p1: the result is of the same value category as its right // operand, [...]. @@ -468,9 +470,10 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, if (Kind == Cl::CL_PRValue) { // For the sake of better diagnostics, we want to specifically recognize // use of the GCC cast-as-lvalue extension. - if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E->IgnoreParens())){ - if (CE->getSubExpr()->Classify(Ctx).isLValue()) { - Loc = CE->getLParenLoc(); + if (const ExplicitCastExpr *CE = + dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) { + if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) { + Loc = CE->getExprLoc(); return Cl::CM_LValueCast; } } |