diff options
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
| -rw-r--r-- | lib/AST/ExprConstant.cpp | 56 | 
1 files changed, 44 insertions, 12 deletions
| diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 01c9fe7cd846a..66a88b065ce1b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -934,6 +934,7 @@ static bool IsGlobalLValue(APValue::LValueBase B) {    case Expr::ObjCStringLiteralClass:    case Expr::ObjCEncodeExprClass:    case Expr::CXXTypeidExprClass: +  case Expr::CXXUuidofExprClass:      return true;    case Expr::CallExprClass:      return IsStringLiteralCall(cast<CallExpr>(E)); @@ -1491,15 +1492,19 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,    llvm_unreachable("base class missing from derived class's bases list");  } -/// Extract the value of a character from a string literal. +/// Extract the value of a character from a string literal. CharType is used to +/// determine the expected signedness of the result -- a string literal used to +/// initialize an array of 'signed char' or 'unsigned char' might contain chars +/// of the wrong signedness.  static APSInt ExtractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, -                                            uint64_t Index) { +                                            uint64_t Index, QualType CharType) {    // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant    const StringLiteral *S = dyn_cast<StringLiteral>(Lit);    assert(S && "unexpected string literal expression kind"); +  assert(CharType->isIntegerType() && "unexpected character type");    APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), -    Lit->getType()->getArrayElementTypeNoTypeQual()->isUnsignedIntegerType()); +               CharType->isUnsignedIntegerType());    if (Index < S->getLength())      Value = S->getCodeUnit(Index);    return Value; @@ -1546,7 +1551,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,          assert(I == N - 1 && "extracting subobject of character?");          assert(!O->hasLValuePath() || O->getLValuePath().empty());          Obj = APValue(ExtractStringLiteralCharacter( -          Info, O->getLValueBase().get<const Expr*>(), Index)); +          Info, O->getLValueBase().get<const Expr*>(), Index, SubType));          return true;        } else if (O->getArrayInitializedElts() > Index)          O = &O->getArrayInitializedElt(Index); @@ -2868,6 +2873,7 @@ public:    bool VisitStringLiteral(const StringLiteral *E) { return Success(E); }    bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); }    bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); +  bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);    bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);    bool VisitUnaryDeref(const UnaryOperator *E);    bool VisitUnaryReal(const UnaryOperator *E); @@ -2973,6 +2979,10 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {    return Success(E);  } +bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { +  return Success(E); +}  +  bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {    // Handle static data members.    if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) { @@ -3849,8 +3859,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {    // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...]    // an appropriately-typed string literal enclosed in braces. -  if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() && -      Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) { +  if (E->isStringLiteralInit()) {      LValue LV;      if (!EvaluateLValue(E->getInit(0), LV, Info))        return false; @@ -5079,14 +5088,37 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {          }        } +      // The comparison here must be unsigned, and performed with the same +      // width as the pointer. +      unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy); +      uint64_t CompareLHS = LHSOffset.getQuantity(); +      uint64_t CompareRHS = RHSOffset.getQuantity(); +      assert(PtrSize <= 64 && "Unexpected pointer width"); +      uint64_t Mask = ~0ULL >> (64 - PtrSize); +      CompareLHS &= Mask; +      CompareRHS &= Mask; + +      // If there is a base and this is a relational operator, we can only +      // compare pointers within the object in question; otherwise, the result +      // depends on where the object is located in memory. +      if (!LHSValue.Base.isNull() && E->isRelationalOp()) { +        QualType BaseTy = getType(LHSValue.Base); +        if (BaseTy->isIncompleteType()) +          return Error(E); +        CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); +        uint64_t OffsetLimit = Size.getQuantity(); +        if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit) +          return Error(E); +      } +        switch (E->getOpcode()) {        default: llvm_unreachable("missing comparison operator"); -      case BO_LT: return Success(LHSOffset < RHSOffset, E); -      case BO_GT: return Success(LHSOffset > RHSOffset, E); -      case BO_LE: return Success(LHSOffset <= RHSOffset, E); -      case BO_GE: return Success(LHSOffset >= RHSOffset, E); -      case BO_EQ: return Success(LHSOffset == RHSOffset, E); -      case BO_NE: return Success(LHSOffset != RHSOffset, E); +      case BO_LT: return Success(CompareLHS < CompareRHS, E); +      case BO_GT: return Success(CompareLHS > CompareRHS, E); +      case BO_LE: return Success(CompareLHS <= CompareRHS, E); +      case BO_GE: return Success(CompareLHS >= CompareRHS, E); +      case BO_EQ: return Success(CompareLHS == CompareRHS, E); +      case BO_NE: return Success(CompareLHS != CompareRHS, E);        }      }    } | 
