diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-07 04:16:51 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-07 04:16:51 +0000 |
commit | 8ae4ec28451a16a57718286da3e476fc2f495c3f (patch) | |
tree | 27a7eeb26c7d5f432b76bedd2c9cf7dbb57db5b4 /lib/AST/ExprConstant.cpp | |
parent | daa88985ed6d174aeb8c6ddca394f734a73268b7 (diff) |
Teach Expr::HasSideEffects about all the Expr types, and fix a bug where it
was mistakenly classifying dynamic_casts which might throw as having no side
effects.
Switch it from a visitor to a switch, so it is kept up-to-date as future Expr
nodes are added. Move it from ExprConstant.cpp to Expr.cpp, since it's not
really related to constant expression evaluation.
Since we use HasSideEffect to determine whether to emit an unused global with
internal linkage, this has the effect of suppressing emission of globals in
some cases.
I've left many of the Objective-C cases conservatively assuming that the
expression has side-effects. I'll leave it to someone with better knowledge
of Objective-C than mine to improve them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161388 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 95 |
1 files changed, 3 insertions, 92 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 48131f940a..567002cf82 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2277,91 +2277,6 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, return Success; } -namespace { -class HasSideEffect - : public ConstStmtVisitor<HasSideEffect, bool> { - const ASTContext &Ctx; -public: - - HasSideEffect(const ASTContext &C) : Ctx(C) {} - - // Unhandled nodes conservatively default to having side effects. - bool VisitStmt(const Stmt *S) { - return true; - } - - bool VisitParenExpr(const ParenExpr *E) { return Visit(E->getSubExpr()); } - bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) { - return Visit(E->getResultExpr()); - } - bool VisitDeclRefExpr(const DeclRefExpr *E) { - if (Ctx.getCanonicalType(E->getType()).isVolatileQualified()) - return true; - return false; - } - bool VisitObjCIvarRefExpr(const ObjCIvarRefExpr *E) { - if (Ctx.getCanonicalType(E->getType()).isVolatileQualified()) - return true; - return false; - } - - // We don't want to evaluate BlockExprs multiple times, as they generate - // a ton of code. - bool VisitBlockExpr(const BlockExpr *E) { return true; } - bool VisitPredefinedExpr(const PredefinedExpr *E) { return false; } - bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) - { return Visit(E->getInitializer()); } - bool VisitMemberExpr(const MemberExpr *E) { return Visit(E->getBase()); } - bool VisitIntegerLiteral(const IntegerLiteral *E) { return false; } - bool VisitFloatingLiteral(const FloatingLiteral *E) { return false; } - bool VisitStringLiteral(const StringLiteral *E) { return false; } - bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return false; } - bool VisitCharacterLiteral(const CharacterLiteral *E) { return false; } - bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E) - { return false; } - bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E) - { return Visit(E->getLHS()) || Visit(E->getRHS()); } - bool VisitChooseExpr(const ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Ctx)); } - bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) - { return Visit(E->getCond()) || Visit(E->getTrueExpr()) - || Visit(E->getFalseExpr()); } - bool VisitCastExpr(const CastExpr *E) { return Visit(E->getSubExpr()); } - bool VisitBinAssign(const BinaryOperator *E) { return true; } - bool VisitCompoundAssignOperator(const BinaryOperator *E) { return true; } - bool VisitBinaryOperator(const BinaryOperator *E) - { return Visit(E->getLHS()) || Visit(E->getRHS()); } - bool VisitUnaryPreInc(const UnaryOperator *E) { return true; } - bool VisitUnaryPostInc(const UnaryOperator *E) { return true; } - bool VisitUnaryPreDec(const UnaryOperator *E) { return true; } - bool VisitUnaryPostDec(const UnaryOperator *E) { return true; } - bool VisitUnaryDeref(const UnaryOperator *E) { - if (Ctx.getCanonicalType(E->getType()).isVolatileQualified()) - return true; - return Visit(E->getSubExpr()); - } - bool VisitUnaryOperator(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - bool VisitGNUNullExpr(const GNUNullExpr *E) { return false; } - bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return false; } - bool VisitCXXThisExpr(const CXXThisExpr *E) { return false; } - bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { - return false; - } - - // Has side effects if any element does. - bool VisitInitListExpr(const InitListExpr *E) { - for (unsigned i = 0, e = E->getNumInits(); i != e; ++i) - if (Visit(E->getInit(i))) return true; - if (const Expr *filler = E->getArrayFiller()) - return Visit(filler); - return false; - } - - bool VisitSizeOfPackExpr(const SizeOfPackExpr *) { return false; } -}; - -} // end anonymous namespace - //===----------------------------------------------------------------------===// // Generic Evaluation //===----------------------------------------------------------------------===// @@ -4356,9 +4271,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { if (TryEvaluateBuiltinObjectSize(E)) return true; - // If evaluating the argument has side-effects we can't determine - // the size of the object and lower it to unknown now. CodeGen relies on - // us to handle all cases where the expression has side-effects. + // If evaluating the argument has side-effects, we can't determine the size + // of the object, and so we lower it to unknown now. CodeGen relies on us to + // handle all cases where the expression has side-effects. if (E->getArg(0)->HasSideEffects(Info.Ctx)) { if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1) return Success(-1ULL, E); @@ -6423,10 +6338,6 @@ bool Expr::isEvaluatable(const ASTContext &Ctx) const { return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects; } -bool Expr::HasSideEffects(const ASTContext &Ctx) const { - return HasSideEffect(Ctx).Visit(this); -} - APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { EvalResult EvalResult; bool Result = EvaluateAsRValue(EvalResult, Ctx); |