diff options
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 180 |
1 files changed, 119 insertions, 61 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 786155af281d6..df75bc8a735f0 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -59,6 +59,8 @@ namespace { EvalInfo(const ASTContext &ctx, Expr::EvalResult &evalresult) : Ctx(ctx), EvalResult(evalresult) {} + + const LangOptions &getLangOpts() { return Ctx.getLangOptions(); } }; struct ComplexValue { @@ -378,18 +380,22 @@ private: RetTy DerivedError(const Expr *E) { return static_cast<Derived*>(this)->Error(E); } + RetTy DerivedValueInitialization(const Expr *E) { + return static_cast<Derived*>(this)->ValueInitialization(E); + } protected: EvalInfo &Info; typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; + RetTy ValueInitialization(const Expr *E) { return DerivedError(E); } + public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} RetTy VisitStmt(const Stmt *) { - assert(0 && "Expression evaluator should not be called on stmts"); - return DerivedError(0); + llvm_unreachable("Expression evaluator should not be called on stmts"); } RetTy VisitExpr(const Expr *E) { return DerivedError(E); @@ -436,6 +442,23 @@ public: : DerivedError(E)); return DerivedSuccess(*value, E); } + + RetTy VisitInitListExpr(const InitListExpr *E) { + if (Info.getLangOpts().CPlusPlus0x) { + if (E->getNumInits() == 0) + return DerivedValueInitialization(E); + if (E->getNumInits() == 1) + return StmtVisitorTy::Visit(E->getInit(0)); + } + return DerivedError(E); + } + RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { + return DerivedValueInitialization(E); + } + RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { + return DerivedValueInitialization(E); + } + }; } @@ -447,6 +470,7 @@ namespace { class LValueExprEvaluator : public ExprEvaluatorBase<LValueExprEvaluator, bool> { LValue &Result; + const Decl *PrevDecl; bool Success(const Expr *E) { Result.Base = E; @@ -456,7 +480,7 @@ class LValueExprEvaluator public: LValueExprEvaluator(EvalInfo &info, LValue &Result) : - ExprEvaluatorBaseTy(info), Result(Result) {} + ExprEvaluatorBaseTy(info), Result(Result), PrevDecl(0) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(V); @@ -481,9 +505,13 @@ public: return false; case CK_NoOp: + case CK_LValueBitCast: return Visit(E->getSubExpr()); + + // FIXME: Support CK_DerivedToBase and friends. } } + // FIXME: Missing: __real__, __imag__ }; @@ -501,10 +529,16 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { return Success(E); // Reference parameters can refer to anything even if they have an // "initializer" in the form of a default argument. - if (!isa<ParmVarDecl>(VD)) + if (!isa<ParmVarDecl>(VD)) { // FIXME: Check whether VD might be overridden! + + // Check for recursive initializers of references. + if (PrevDecl == VD) + return Error(E); + PrevDecl = VD; if (const Expr *Init = VD->getAnyInitializer()) return Visit(Init); + } } return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); @@ -585,6 +619,9 @@ public: bool Error(const Stmt *S) { return false; } + bool ValueInitialization(const Expr *E) { + return Success((Expr*)0); + } bool VisitBinaryOperator(const BinaryOperator *E); bool VisitCastExpr(const CastExpr* E); @@ -599,10 +636,8 @@ public: return Success(E); return false; } - bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) - { return Success((Expr*)0); } bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) - { return Success((Expr*)0); } + { return ValueInitialization(E); } // FIXME: Missing: @protocol, @selector }; @@ -667,7 +702,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { case CK_NoOp: case CK_BitCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); @@ -761,11 +797,11 @@ namespace { APValue Success(const APValue &V, const Expr *E) { return V; } APValue Error(const Expr *E) { return APValue(); } + APValue ValueInitialization(const Expr *E) + { return GetZeroVector(E->getType()); } APValue VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - APValue VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) - { return GetZeroVector(E->getType()); } APValue VisitCastExpr(const CastExpr* E); APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); APValue VisitInitListExpr(const InitListExpr *E); @@ -812,7 +848,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { } // Splat and create vector APValue. - llvm::SmallVector<APValue, 4> Elts(NElts, Result); + SmallVector<APValue, 4> Elts(NElts, Result); return APValue(&Elts[0], Elts.size()); } case CK_BitCast: { @@ -829,7 +865,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) && "Vectors must be composed of ints or floats"); - llvm::SmallVector<APValue, 4> Elts; + SmallVector<APValue, 4> Elts; for (unsigned i = 0; i != NElts; ++i) { APSInt Tmp = Init.extOrTrunc(EltWidth); @@ -862,7 +898,7 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { unsigned NumElements = VT->getNumElements(); QualType EltTy = VT->getElementType(); - llvm::SmallVector<APValue, 4> Elements; + SmallVector<APValue, 4> Elements; // If a vector is initialized with a single element, that value // becomes every element of the vector, not just the first. @@ -926,7 +962,7 @@ VectorExprEvaluator::GetZeroVector(QualType T) { ZeroElement = APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy))); - llvm::SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement); + SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement); return APValue(&Elements[0], Elements.size()); } @@ -999,6 +1035,8 @@ public: return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); } + bool ValueInitialization(const Expr *E) { return Success(0, E); } + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// @@ -1039,16 +1077,9 @@ public: return Success(E->getValue(), E); } + // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { - return Success(0, E); - } - - bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { - return Success(0, E); - } - - bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { - return Success(0, E); + return ValueInitialization(E); } bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { @@ -1072,7 +1103,7 @@ public: bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); - + private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); @@ -1210,7 +1241,7 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) { else if (ArgTy->isUnionType()) return union_type_class; else // FIXME: offset_type_class, method_type_class, & lang_type_class? - assert(0 && "CallExpr::isBuiltinClassifyType(): unimplemented type"); + llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); return -1; } @@ -1267,7 +1298,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // If evaluating the argument has side-effects we can't determine // the size of the object and lower it to unknown now. if (E->getArg(0)->HasSideEffects(Info.Ctx)) { - if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1) + if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1) return Success(-1ULL, E); return Success(0, E); } @@ -1284,8 +1315,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E); case Builtin::BI__builtin_eh_return_data_regno: { - int Operand = E->getArg(0)->EvaluateAsInt(Info.Ctx).getZExtValue(); - Operand = Info.Ctx.Target.getEHDataRegisterNumber(Operand); + int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); + Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); return Success(Operand, E); } @@ -1300,9 +1331,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { = dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts())) { // The string literal may have embedded null characters. Find the first // one and truncate there. - llvm::StringRef Str = S->getString(); - llvm::StringRef::size_type Pos = Str.find(0); - if (Pos != llvm::StringRef::npos) + StringRef Str = S->getString(); + StringRef::size_type Pos = Str.find(0); + if (Pos != StringRef::npos) Str = Str.substr(0, Pos); return Success(Str.size(), E); @@ -1419,7 +1450,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: - assert(0 && "Invalid binary operator!"); + llvm_unreachable("Invalid binary operator!"); case BO_LT: return Success(CR == APFloat::cmpLessThan, E); case BO_GT: @@ -1801,7 +1832,8 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_VectorSplat: case CK_IntegralToFloating: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingRealToComplex: @@ -1818,9 +1850,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_GetObjCProperty: case CK_LValueBitCast: case CK_UserDefinedConversion: - case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: - case CK_ObjCReclaimReturnedObject: + case CK_ARCProduceObject: + case CK_ARCConsumeObject: + case CK_ARCReclaimReturnedObject: + case CK_ARCExtendBlockObject: return false; case CK_LValueToRValue: @@ -1943,13 +1976,17 @@ public: return false; } + bool ValueInitialization(const Expr *E) { + Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); + return true; + } + bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitCastExpr(const CastExpr *E); - bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); @@ -2219,11 +2256,6 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { return false; } -bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { - Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); - return true; -} - //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// @@ -2255,7 +2287,7 @@ public: bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); - // FIXME Missing: ImplicitValueInitExpr + // FIXME Missing: ImplicitValueInitExpr, InitListExpr }; } // end anonymous namespace @@ -2318,16 +2350,18 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: - case CK_AnyPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingComplexToReal: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToReal: case CK_IntegralComplexToBoolean: - case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: - case CK_ObjCReclaimReturnedObject: + case CK_ARCProduceObject: + case CK_ARCConsumeObject: + case CK_ARCReclaimReturnedObject: + case CK_ARCExtendBlockObject: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -2633,6 +2667,13 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, return HandleConversionToBool(this, Result, Info); } +bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const { + EvalResult Scratch; + EvalInfo Info(Ctx, Scratch); + + return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects; +} + bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); @@ -2671,7 +2712,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { return HasSideEffect(Info).Visit(this); } -APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const { +APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { EvalResult EvalResult; bool Result = Evaluate(EvalResult, Ctx); (void)Result; @@ -2755,7 +2796,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: - case Expr::InitListExprClass: case Expr::DesignatedInitExprClass: case Expr::ImplicitValueInitExprClass: case Expr::ParenListExprClass: @@ -2800,6 +2840,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: + case Expr::AtomicExprClass: + return ICEDiag(2, E->getLocStart()); + + case Expr::InitListExprClass: + if (Ctx.getLangOptions().CPlusPlus0x) { + const InitListExpr *ILE = cast<InitListExpr>(E); + if (ILE->getNumInits() == 0) + return NoDiag(); + if (ILE->getNumInits() == 1) + return CheckICE(ILE->getInit(0), Ctx); + // Fall through for more than 1 expression. + } return ICEDiag(2, E->getLocStart()); case Expr::SizeOfPackExprClass: @@ -2963,11 +3015,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // Evaluate gives an error for undefined Div/Rem, so make sure // we don't evaluate one. if (LHSResult.Val == 0 && RHSResult.Val == 0) { - llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx); + llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) return ICEDiag(1, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { - llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx); + llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) return ICEDiag(1, E->getLocStart()); } @@ -2998,11 +3050,11 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // evaluated are not considered. if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) { if (Exp->getOpcode() == BO_LAnd && - Exp->getLHS()->EvaluateAsInt(Ctx) == 0) + Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0) return LHSResult; if (Exp->getOpcode() == BO_LOr && - Exp->getLHS()->EvaluateAsInt(Ctx) != 0) + Exp->getLHS()->EvaluateKnownConstInt(Ctx) != 0) return LHSResult; } @@ -3012,7 +3064,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // to actually check the condition to see whether the side // with the comma is evaluated. if ((Exp->getOpcode() == BO_LAnd) != - (Exp->getLHS()->EvaluateAsInt(Ctx) == 0)) + (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) return RHSResult; return NoDiag(); } @@ -3031,11 +3083,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXConstCastExprClass: case Expr::ObjCBridgedCastExprClass: { const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); - if (SubExpr->getType()->isIntegralOrEnumerationType()) + switch (cast<CastExpr>(E)->getCastKind()) { + case CK_LValueToRValue: + case CK_NoOp: + case CK_IntegralToBoolean: + case CK_IntegralCast: return CheckICE(SubExpr, Ctx); - if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) - return NoDiag(); - return ICEDiag(2, E->getLocStart()); + default: + if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) + return NoDiag(); + return ICEDiag(2, E->getLocStart()); + } } case Expr::BinaryConditionalOperatorClass: { const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E); @@ -3045,7 +3103,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (FalseResult.Val == 2) return FalseResult; if (CommonResult.Val == 1) return CommonResult; if (FalseResult.Val == 1 && - Exp->getCommon()->EvaluateAsInt(Ctx) == 0) return NoDiag(); + Exp->getCommon()->EvaluateKnownConstInt(Ctx) == 0) return NoDiag(); return FalseResult; } case Expr::ConditionalOperatorClass: { @@ -3072,7 +3130,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // subexpressions of [...] conditional (5.16) operations that // are not evaluated are not considered bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x - ? Exp->getCond()->EvaluateAsInt(Ctx) != 0 + ? Exp->getCond()->EvaluateKnownConstInt(Ctx) != 0 : false; ICEDiag TrueResult = NoDiag(); if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch) @@ -3092,7 +3150,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // Rare case where the diagnostics depend on which side is evaluated // Note that if we get here, CondResult is 0, and at least one of // TrueResult and FalseResult is non-zero. - if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) { + if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) { return FalseResult; } return TrueResult; |