static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc) { // As a general rule, we only care about lvalues. But there are some rvalues // for which we want to generate special results. 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 ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) { if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) { Loc = CE->getExprLoc(); return Cl::CM_LValueCast; } } } if (Kind != Cl::CL_LValue) return Cl::CM_RValue; // This is the lvalue case. // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6) if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType()) return Cl::CM_Function; // Assignment to a property in ObjC is an implicit setter access. But a // setter might not exist. if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) { if (Expr->isImplicitProperty() && Expr->getImplicitPropertySetter() == 0) return Cl::CM_NoSetterProperty; } CanQualType CT = Ctx.getCanonicalType(E->getType()); // Const stuff is obviously not modifiable. if (CT.isConstQualified()) return Cl::CM_ConstQualified; if (CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) return Cl::CM_ConstQualified; // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) return Cl::CM_ArrayType; // Incomplete types are not modifiable. if (CT->isIncompleteType()) return Cl::CM_IncompleteType; // Records with any const fields (recursively) are not modifiable. if (const RecordType *R = CT->getAs<RecordType>()) { assert((E->getObjectKind() == OK_ObjCProperty || !Ctx.getLangOpts().CPlusPlus) && "C++ struct assignment should be resolved by the " "copy assignment operator."); if (R->hasConstFields()) return Cl::CM_ConstQualified; } return Cl::CM_Modifiable; }
static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc) { // As a general rule, we only care about lvalues. But there are some rvalues // for which we want to generate special results. 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(); return Cl::CM_LValueCast; } } } if (Kind != Cl::CL_LValue) return Cl::CM_RValue; // This is the lvalue case. // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6) if (Ctx.getLangOptions().CPlusPlus && E->getType()->isFunctionType()) return Cl::CM_Function; // You cannot assign to a variable outside a block from within the block if // it is not marked __block, e.g. // void takeclosure(void (^C)(void)); // void func() { int x = 1; takeclosure(^{ x = 7; }); } if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E)) { if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl())) return Cl::CM_NotBlockQualified; } // Assignment to a property in ObjC is an implicit setter access. But a // setter might not exist. if (const ObjCImplicitSetterGetterRefExpr *Expr = dyn_cast<ObjCImplicitSetterGetterRefExpr>(E)) { if (Expr->getSetterMethod() == 0) return Cl::CM_NoSetterProperty; } CanQualType CT = Ctx.getCanonicalType(E->getType()); // Const stuff is obviously not modifiable. if (CT.isConstQualified()) return Cl::CM_ConstQualified; // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) return Cl::CM_ArrayType; // Incomplete types are not modifiable. if (CT->isIncompleteType()) return Cl::CM_IncompleteType; // Records with any const fields (recursively) are not modifiable. if (const RecordType *R = CT->getAs<RecordType>()) { assert(!Ctx.getLangOptions().CPlusPlus && "C++ struct assignment should be resolved by the " "copy assignment operator."); if (R->hasConstFields()) return Cl::CM_ConstQualified; } return Cl::CM_Modifiable; }