diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp | 94 | 
1 files changed, 57 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 6a6baf96ad37..2c0fce91844c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -604,10 +604,12 @@ namespace {        /// gets a chance to look at it.        EM_PotentialConstantExpressionUnevaluated, -      /// Evaluate as a constant expression. Continue evaluating if either: -      /// - We find a MemberExpr with a base that can't be evaluated. -      /// - We find a variable initialized with a call to a function that has -      ///   the alloc_size attribute on it. +      /// Evaluate as a constant expression. In certain scenarios, if: +      /// - we find a MemberExpr with a base that can't be evaluated, or +      /// - we find a variable initialized with a call to a function that has +      ///   the alloc_size attribute on it +      /// then we may consider evaluation to have succeeded. +      ///        /// In either case, the LValue returned shall have an invalid base; in the        /// former, the base will be the invalid MemberExpr, in the latter, the        /// base will be either the alloc_size CallExpr or a CastExpr wrapping @@ -890,10 +892,6 @@ namespace {        return KeepGoing;      } -    bool allowInvalidBaseExpr() const { -      return EvalMode == EM_OffsetFold; -    } -      class ArrayInitLoopIndex {        EvalInfo &Info;        uint64_t OuterIndex; @@ -1394,8 +1392,10 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E);  static bool EvaluateInPlace(APValue &Result, EvalInfo &Info,                              const LValue &This, const Expr *E,                              bool AllowNonLiteralTypes = false); -static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); -static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, +                           bool InvalidBaseOK = false); +static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info, +                            bool InvalidBaseOK = false);  static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result,                                    EvalInfo &Info);  static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); @@ -4803,6 +4803,7 @@ class LValueExprEvaluatorBase    : public ExprEvaluatorBase<Derived> {  protected:    LValue &Result; +  bool InvalidBaseOK;    typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy;    typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy; @@ -4811,9 +4812,14 @@ protected:      return true;    } +  bool evaluatePointer(const Expr *E, LValue &Result) { +    return EvaluatePointer(E, Result, this->Info, InvalidBaseOK); +  } +  public: -  LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result) : -    ExprEvaluatorBaseTy(Info), Result(Result) {} +  LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) +      : ExprEvaluatorBaseTy(Info), Result(Result), +        InvalidBaseOK(InvalidBaseOK) {}    bool Success(const APValue &V, const Expr *E) {      Result.setFrom(this->Info.Ctx, V); @@ -4825,7 +4831,7 @@ public:      QualType BaseTy;      bool EvalOK;      if (E->isArrow()) { -      EvalOK = EvaluatePointer(E->getBase(), Result, this->Info); +      EvalOK = evaluatePointer(E->getBase(), Result);        BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType();      } else if (E->getBase()->isRValue()) {        assert(E->getBase()->getType()->isRecordType()); @@ -4836,7 +4842,7 @@ public:        BaseTy = E->getBase()->getType();      }      if (!EvalOK) { -      if (!this->Info.allowInvalidBaseExpr()) +      if (!InvalidBaseOK)          return false;        Result.setInvalid(E);        return true; @@ -4930,8 +4936,8 @@ namespace {  class LValueExprEvaluator    : public LValueExprEvaluatorBase<LValueExprEvaluator> {  public: -  LValueExprEvaluator(EvalInfo &Info, LValue &Result) : -    LValueExprEvaluatorBaseTy(Info, Result) {} +  LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : +    LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {}    bool VisitVarDecl(const Expr *E, const VarDecl *VD);    bool VisitUnaryPreIncDec(const UnaryOperator *UO); @@ -4984,10 +4990,11 @@ public:  ///  * function designators in C, and  ///  * "extern void" objects  ///  * @selector() expressions in Objective-C -static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info) { +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, +                           bool InvalidBaseOK) {    assert(E->isGLValue() || E->getType()->isFunctionType() ||           E->getType()->isVoidType() || isa<ObjCSelectorExpr>(E)); -  return LValueExprEvaluator(Info, Result).Visit(E); +  return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E);  }  bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { @@ -5148,7 +5155,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {    if (E->getBase()->getType()->isVectorType())      return Error(E); -  if (!EvaluatePointer(E->getBase(), Result, Info)) +  if (!evaluatePointer(E->getBase(), Result))      return false;    APSInt Index; @@ -5160,7 +5167,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {  }  bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { -  return EvaluatePointer(E->getSubExpr(), Result, Info); +  return evaluatePointer(E->getSubExpr(), Result);  }  bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { @@ -5308,7 +5315,7 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,  /// and mark Result's Base as invalid.  static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base,                                        LValue &Result) { -  if (!Info.allowInvalidBaseExpr() || Base.isNull()) +  if (Base.isNull())      return false;    // Because we do no form of static analysis, we only support const variables. @@ -5342,17 +5349,27 @@ namespace {  class PointerExprEvaluator    : public ExprEvaluatorBase<PointerExprEvaluator> {    LValue &Result; +  bool InvalidBaseOK;    bool Success(const Expr *E) {      Result.set(E);      return true;    } +  bool evaluateLValue(const Expr *E, LValue &Result) { +    return EvaluateLValue(E, Result, Info, InvalidBaseOK); +  } + +  bool evaluatePointer(const Expr *E, LValue &Result) { +    return EvaluatePointer(E, Result, Info, InvalidBaseOK); +  } +    bool visitNonBuiltinCallExpr(const CallExpr *E);  public: -  PointerExprEvaluator(EvalInfo &info, LValue &Result) -    : ExprEvaluatorBaseTy(info), Result(Result) {} +  PointerExprEvaluator(EvalInfo &info, LValue &Result, bool InvalidBaseOK) +      : ExprEvaluatorBaseTy(info), Result(Result), +        InvalidBaseOK(InvalidBaseOK) {}    bool Success(const APValue &V, const Expr *E) {      Result.setFrom(Info.Ctx, V); @@ -5399,9 +5416,10 @@ public:  };  } // end anonymous namespace -static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) { +static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info, +                            bool InvalidBaseOK) {    assert(E->isRValue() && E->getType()->hasPointerRepresentation()); -  return PointerExprEvaluator(Info, Result).Visit(E); +  return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E);  }  bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { @@ -5414,7 +5432,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {    if (IExp->getType()->isPointerType())      std::swap(PExp, IExp); -  bool EvalPtrOK = EvaluatePointer(PExp, Result, Info); +  bool EvalPtrOK = evaluatePointer(PExp, Result);    if (!EvalPtrOK && !Info.noteFailure())      return false; @@ -5432,7 +5450,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {  }  bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { -  return EvaluateLValue(E->getSubExpr(), Result, Info); +  return evaluateLValue(E->getSubExpr(), Result);  }  bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { @@ -5466,7 +5484,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {    case CK_DerivedToBase:    case CK_UncheckedDerivedToBase: -    if (!EvaluatePointer(E->getSubExpr(), Result, Info)) +    if (!evaluatePointer(E->getSubExpr(), Result))        return false;      if (!Result.Base && Result.Offset.isZero())        return true; @@ -5513,7 +5531,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {    }    case CK_ArrayToPointerDecay:      if (SubExpr->isGLValue()) { -      if (!EvaluateLValue(SubExpr, Result, Info)) +      if (!evaluateLValue(SubExpr, Result))          return false;      } else {        Result.set(SubExpr, Info.CurrentCall->Index); @@ -5530,18 +5548,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {      return true;    case CK_FunctionToPointerDecay: -    return EvaluateLValue(SubExpr, Result, Info); +    return evaluateLValue(SubExpr, Result);    case CK_LValueToRValue: {      LValue LVal; -    if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) +    if (!evaluateLValue(E->getSubExpr(), LVal))        return false;      APValue RVal;      // Note, we use the subexpression's type in order to retain cv-qualifiers.      if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(),                                          LVal, RVal)) -      return evaluateLValueAsAllocSize(Info, LVal.Base, Result); +      return InvalidBaseOK && +             evaluateLValueAsAllocSize(Info, LVal.Base, Result);      return Success(RVal, E);    }    } @@ -5586,7 +5605,7 @@ bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) {    if (ExprEvaluatorBaseTy::VisitCallExpr(E))      return true; -  if (!(Info.allowInvalidBaseExpr() && getAllocSizeAttr(E))) +  if (!(InvalidBaseOK && getAllocSizeAttr(E)))      return false;    Result.setInvalid(E); @@ -5609,12 +5628,12 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,                                                  unsigned BuiltinOp) {    switch (BuiltinOp) {    case Builtin::BI__builtin_addressof: -    return EvaluateLValue(E->getArg(0), Result, Info); +    return evaluateLValue(E->getArg(0), Result);    case Builtin::BI__builtin_assume_aligned: {      // We need to be very careful here because: if the pointer does not have the      // asserted alignment, then the behavior is undefined, and undefined      // behavior is non-constant. -    if (!EvaluatePointer(E->getArg(0), Result, Info)) +    if (!evaluatePointer(E->getArg(0), Result))        return false;      LValue OffsetResult(Result); @@ -6255,7 +6274,7 @@ class TemporaryExprEvaluator    : public LValueExprEvaluatorBase<TemporaryExprEvaluator> {  public:    TemporaryExprEvaluator(EvalInfo &Info, LValue &Result) : -    LValueExprEvaluatorBaseTy(Info, Result) {} +    LValueExprEvaluatorBaseTy(Info, Result, false) {}    /// Visit an expression which constructs the value of this temporary.    bool VisitConstructExpr(const Expr *E) { @@ -7358,7 +7377,8 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,        if (!EvaluateAsRValue(Info, E, RVal))          return false;        LVal.setFrom(Info.Ctx, RVal); -    } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info)) +    } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info, +                                /*InvalidBaseOK=*/true))        return false;    }  | 
