diff options
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
| -rw-r--r-- | lib/AST/ExprConstant.cpp | 579 | 
1 files changed, 460 insertions, 119 deletions
| diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7d7ca9924c85..3d7f2dca7a2f 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -201,6 +201,7 @@ namespace {      /// Determine whether this is a one-past-the-end pointer.      bool isOnePastTheEnd() const { +      assert(!Invalid);        if (IsOnePastTheEnd)          return true;        if (MostDerivedArraySize && @@ -1308,7 +1309,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,    }    // Does this refer one past the end of some object? -  if (Designator.isOnePastTheEnd()) { +  if (!Designator.Invalid && Designator.isOnePastTheEnd()) {      const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>();      Info.Diag(Loc, diag::note_constexpr_past_end, 1)        << !Designator.Entries.empty() << !!VD << VD; @@ -1328,7 +1329,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E,    // C++1y: A constant initializer for an object o [...] may also invoke    // constexpr constructors for o and its subobjects even if those objects    // are of non-literal class types. -  if (Info.getLangOpts().CPlusPlus1y && This && +  if (Info.getLangOpts().CPlusPlus14 && This &&        Info.EvaluatingDecl == This->getLValueBase())      return true; @@ -1421,6 +1422,17 @@ static bool IsWeakLValue(const LValue &Value) {    return Decl && Decl->isWeak();  } +static bool isZeroSized(const LValue &Value) { +  const ValueDecl *Decl = GetLValueBaseDecl(Value); +  if (Decl && isa<VarDecl>(Decl)) { +    QualType Ty = Decl->getType(); +    if (Ty->isArrayType()) +      return Ty->isIncompleteType() || +             Decl->getASTContext().getTypeSize(Ty) == 0; +  } +  return false; +} +  static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) {    // A null base expression indicates a null pointer.  These are always    // evaluatable, and they are false unless the offset is zero. @@ -2020,7 +2032,9 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,  /// Extract the value of a character from a string literal.  static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,                                              uint64_t Index) { -  // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant +  // FIXME: Support ObjCEncodeExpr, MakeStringConstant +  if (auto PE = dyn_cast<PredefinedExpr>(Lit)) +    Lit = PE->getFunctionName();    const StringLiteral *S = cast<StringLiteral>(Lit);    const ConstantArrayType *CAT =        Info.Ctx.getAsConstantArrayType(S->getType()); @@ -2079,6 +2093,64 @@ static void expandArray(APValue &Array, unsigned Index) {    Array.swap(NewValue);  } +/// Determine whether a type would actually be read by an lvalue-to-rvalue +/// conversion. If it's of class type, we may assume that the copy operation +/// is trivial. Note that this is never true for a union type with fields +/// (because the copy always "reads" the active member) and always true for +/// a non-class type. +static bool isReadByLvalueToRvalueConversion(QualType T) { +  CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); +  if (!RD || (RD->isUnion() && !RD->field_empty())) +    return true; +  if (RD->isEmpty()) +    return false; + +  for (auto *Field : RD->fields()) +    if (isReadByLvalueToRvalueConversion(Field->getType())) +      return true; + +  for (auto &BaseSpec : RD->bases()) +    if (isReadByLvalueToRvalueConversion(BaseSpec.getType())) +      return true; + +  return false; +} + +/// Diagnose an attempt to read from any unreadable field within the specified +/// type, which might be a class type. +static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, +                                     QualType T) { +  CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); +  if (!RD) +    return false; + +  if (!RD->hasMutableFields()) +    return false; + +  for (auto *Field : RD->fields()) { +    // If we're actually going to read this field in some way, then it can't +    // be mutable. If we're in a union, then assigning to a mutable field +    // (even an empty one) can change the active member, so that's not OK. +    // FIXME: Add core issue number for the union case. +    if (Field->isMutable() && +        (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) { +      Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) << Field; +      Info.Note(Field->getLocation(), diag::note_declared_at); +      return true; +    } + +    if (diagnoseUnreadableFields(Info, E, Field->getType())) +      return true; +  } + +  for (auto &BaseSpec : RD->bases()) +    if (diagnoseUnreadableFields(Info, E, BaseSpec.getType())) +      return true; + +  // All mutable fields were empty, and thus not actually read. +  return false; +} +  /// Kinds of access we can perform on an object, for diagnostics.  enum AccessKinds {    AK_Read, @@ -2134,6 +2206,14 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,      }      if (I == N) { +      // If we are reading an object of class type, there may still be more +      // things we need to check: if there are any mutable subobjects, we +      // cannot perform this read. (This only happens when performing a trivial +      // copy or assignment.) +      if (ObjType->isRecordType() && handler.AccessKind == AK_Read && +          diagnoseUnreadableFields(Info, E, ObjType)) +        return handler.failed(); +        if (!handler.found(*O, ObjType))          return false; @@ -2490,7 +2570,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,      // Unless we're looking at a local variable or argument in a constexpr call,      // the variable we're reading must be const.      if (!Frame) { -      if (Info.getLangOpts().CPlusPlus1y && +      if (Info.getLangOpts().CPlusPlus14 &&            VD == Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()) {          // OK, we can read and modify an object if we're in the process of          // evaluating its initializer, because its lifetime began in this @@ -2606,7 +2686,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,    //    // FIXME: Not all local state is mutable. Allow local constant subobjects    // to be read here (but take care with 'mutable' fields). -  if (Frame && Info.getLangOpts().CPlusPlus1y && +  if (Frame && Info.getLangOpts().CPlusPlus14 &&        (Info.EvalStatus.HasSideEffects || Info.keepEvaluatingAfterFailure()))      return CompleteObject(); @@ -2648,10 +2728,10 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,          return false;        CompleteObject LitObj(&Lit, Base->getType());        return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); -    } else if (isa<StringLiteral>(Base)) { +    } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) {        // We represent a string literal array as an lvalue pointing at the        // corresponding expression, rather than building an array of chars. -      // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant +      // FIXME: Support ObjCEncodeExpr, MakeStringConstant        APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);        CompleteObject StrObj(&Str, Base->getType());        return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal); @@ -2668,7 +2748,7 @@ static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal,    if (LVal.Designator.Invalid)      return false; -  if (!Info.getLangOpts().CPlusPlus1y) { +  if (!Info.getLangOpts().CPlusPlus14) {      Info.Diag(E);      return false;    } @@ -2789,7 +2869,7 @@ static bool handleCompoundAssignment(    if (LVal.Designator.Invalid)      return false; -  if (!Info.getLangOpts().CPlusPlus1y) { +  if (!Info.getLangOpts().CPlusPlus14) {      Info.Diag(E);      return false;    } @@ -2938,7 +3018,7 @@ static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal,    if (LVal.Designator.Invalid)      return false; -  if (!Info.getLangOpts().CPlusPlus1y) { +  if (!Info.getLangOpts().CPlusPlus14) {      Info.Diag(E);      return false;    } @@ -3588,6 +3668,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,    return false;  } +/// Determine if a class has any fields that might need to be copied by a +/// trivial copy or move operation. +static bool hasFields(const CXXRecordDecl *RD) { +  if (!RD || RD->isEmpty()) +    return false; +  for (auto *FD : RD->fields()) { +    if (FD->isUnnamedBitfield()) +      continue; +    return true; +  } +  for (auto &Base : RD->bases()) +    if (hasFields(Base.getType()->getAsCXXRecordDecl())) +      return true; +  return false; +} +  namespace {  typedef SmallVector<APValue, 8> ArgVector;  } @@ -3626,8 +3722,12 @@ static bool HandleFunctionCall(SourceLocation CallLoc,    // For a trivial copy or move assignment, perform an APValue copy. This is    // essential for unions, where the operations performed by the assignment    // operator cannot be represented as statements. +  // +  // Skip this for non-union classes with no fields; in that case, the defaulted +  // copy/move does not actually read the object.    const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); -  if (MD && MD->isDefaulted() && MD->isTrivial()) { +  if (MD && MD->isDefaulted() && MD->isTrivial() && +      (MD->getParent()->isUnion() || hasFields(MD->getParent()))) {      assert(This &&             (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));      LValue RHS; @@ -3684,11 +3784,18 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,    }    // For a trivial copy or move constructor, perform an APValue copy. This is -  // essential for unions, where the operations performed by the constructor -  // cannot be represented by ctor-initializers. +  // essential for unions (or classes with anonymous union members), where the +  // operations performed by the constructor cannot be represented by +  // ctor-initializers. +  // +  // Skip this for empty non-union classes; we should not perform an +  // lvalue-to-rvalue conversion on them because their copy constructor does not +  // actually read them.    if (Definition->isDefaulted() &&        ((Definition->isCopyConstructor() && Definition->isTrivial()) || -       (Definition->isMoveConstructor() && Definition->isTrivial()))) { +       (Definition->isMoveConstructor() && Definition->isTrivial())) && +      (Definition->getParent()->isUnion() || +       hasFields(Definition->getParent()))) {      LValue RHS;      RHS.setFrom(Info.Ctx, ArgValues[0]);      return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), @@ -3985,7 +4092,7 @@ public:      const FunctionDecl *FD = nullptr;      LValue *This = nullptr, ThisVal; -    ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); +    auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());      bool HasQualifier = false;      // Extract function decl and 'this' pointer from the callee. @@ -4148,7 +4255,7 @@ public:      return VisitUnaryPostIncDec(UO);    }    bool VisitUnaryPostIncDec(const UnaryOperator *UO) { -    if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) +    if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())        return Error(UO);      LValue LVal; @@ -4573,7 +4680,7 @@ bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {  }  bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { -  if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) +  if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())      return Error(UO);    if (!this->Visit(UO->getSubExpr())) @@ -4586,7 +4693,7 @@ bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) {  bool LValueExprEvaluator::VisitCompoundAssignOperator(      const CompoundAssignOperator *CAO) { -  if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) +  if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())      return Error(CAO);    APValue RHS; @@ -4608,7 +4715,7 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator(  }  bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { -  if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) +  if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())      return Error(E);    APValue NewVal; @@ -4733,6 +4840,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {    case CK_CPointerToObjCPointerCast:    case CK_BlockPointerToObjCPointerCast:    case CK_AnyPointerToBlockPointerCast: +  case CK_AddressSpaceConversion:      if (!Visit(SubExpr))        return false;      // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are @@ -4818,6 +4926,38 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {    return ExprEvaluatorBaseTy::VisitCastExpr(E);  } +static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { +  // C++ [expr.alignof]p3: +  //     When alignof is applied to a reference type, the result is the +  //     alignment of the referenced type. +  if (const ReferenceType *Ref = T->getAs<ReferenceType>()) +    T = Ref->getPointeeType(); + +  // __alignof is defined to return the preferred alignment. +  return Info.Ctx.toCharUnitsFromBits( +    Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); +} + +static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { +  E = E->IgnoreParens(); + +  // The kinds of expressions that we have special-case logic here for +  // should be kept up to date with the special checks for those +  // expressions in Sema. + +  // alignof decl is always accepted, even if it doesn't make sense: we default +  // to 1 in those cases. +  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) +    return Info.Ctx.getDeclAlign(DRE->getDecl(), +                                 /*RefAsPointee*/true); + +  if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) +    return Info.Ctx.getDeclAlign(ME->getMemberDecl(), +                                 /*RefAsPointee*/true); + +  return GetAlignOfType(Info, E->getType()); +} +  bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {    if (IsStringLiteralCall(E))      return Success(E); @@ -4825,7 +4965,71 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {    switch (E->getBuiltinCallee()) {    case Builtin::BI__builtin_addressof:      return EvaluateLValue(E->getArg(0), Result, Info); +  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)) +      return false; + +    LValue OffsetResult(Result); +    APSInt Alignment; +    if (!EvaluateInteger(E->getArg(1), Alignment, Info)) +      return false; +    CharUnits Align = CharUnits::fromQuantity(getExtValue(Alignment)); + +    if (E->getNumArgs() > 2) { +      APSInt Offset; +      if (!EvaluateInteger(E->getArg(2), Offset, Info)) +        return false; + +      int64_t AdditionalOffset = -getExtValue(Offset); +      OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset); +    } + +    // If there is a base object, then it must have the correct alignment. +    if (OffsetResult.Base) { +      CharUnits BaseAlignment; +      if (const ValueDecl *VD = +          OffsetResult.Base.dyn_cast<const ValueDecl*>()) { +        BaseAlignment = Info.Ctx.getDeclAlign(VD); +      } else { +        BaseAlignment = +          GetAlignOfExpr(Info, OffsetResult.Base.get<const Expr*>()); +      } + +      if (BaseAlignment < Align) { +        Result.Designator.setInvalid(); +	// FIXME: Quantities here cast to integers because the plural modifier +	// does not work on APSInts yet. +        CCEDiag(E->getArg(0), +                diag::note_constexpr_baa_insufficient_alignment) << 0 +          << (int) BaseAlignment.getQuantity() +          << (unsigned) getExtValue(Alignment); +        return false; +      } +    } + +    // The offset must also have the correct alignment. +    if (OffsetResult.Offset.RoundUpToAlignment(Align) != OffsetResult.Offset) { +      Result.Designator.setInvalid(); +      APSInt Offset(64, false); +      Offset = OffsetResult.Offset.getQuantity(); +      if (OffsetResult.Base) +        CCEDiag(E->getArg(0), +                diag::note_constexpr_baa_insufficient_alignment) << 1 +          << (int) getExtValue(Offset) << (unsigned) getExtValue(Alignment); +      else +        CCEDiag(E->getArg(0), +                diag::note_constexpr_baa_value_insufficient_alignment) +          << Offset << (unsigned) getExtValue(Alignment); + +      return false; +    } + +    return true; +  }    default:      return ExprEvaluatorBaseTy::VisitCallExpr(E);    } @@ -5166,7 +5370,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {    if (ZeroInit && !ZeroInitialization(E))      return false; -  ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); +  auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());    return HandleConstructorCall(E->getExprLoc(), This, Args,                                 cast<CXXConstructorDecl>(Definition), Info,                                 Result); @@ -5270,6 +5474,9 @@ public:    bool VisitCallExpr(const CallExpr *E) {      return VisitConstructExpr(E);    } +  bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { +    return VisitConstructExpr(E); +  }  };  } // end anonymous namespace @@ -5645,7 +5852,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,        return false;    } -  ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); +  auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());    return HandleConstructorCall(E->getExprLoc(), Subobject, Args,                                 cast<CXXConstructorDecl>(Definition),                                 Info, *Value); @@ -5786,8 +5993,6 @@ public:    bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);  private: -  CharUnits GetAlignOfExpr(const Expr *E); -  CharUnits GetAlignOfType(QualType T);    static QualType GetObjectType(APValue::LValueBase B);    bool TryEvaluateBuiltinObjectSize(const CallExpr *E);    // FIXME: Missing: array subscript of vector, member of vector @@ -5985,8 +6190,20 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) {        return false;    } -  // If we can prove the base is null, lower to zero now. -  if (!Base.getLValueBase()) return Success(0, E); +  if (!Base.getLValueBase()) { +    // It is not possible to determine which objects ptr points to at compile time, +    // __builtin_object_size should return (size_t) -1 for type 0 or 1 +    // and (size_t) 0 for type 2 or 3. +    llvm::APSInt TypeIntVaue; +    const Expr *ExprType = E->getArg(1); +    if (!ExprType->EvaluateAsInt(TypeIntVaue, Info.Ctx)) +      return false; +    if (TypeIntVaue == 0 || TypeIntVaue == 1) +      return Success(-1, E); +    if (TypeIntVaue == 2 || TypeIntVaue == 3) +      return Success(0, E); +    return Error(E); +  }    QualType T = GetObjectType(Base.getLValueBase());    if (T.isNull() || @@ -6286,6 +6503,27 @@ static bool HasSameBase(const LValue &A, const LValue &B) {           A.getLValueCallIndex() == B.getLValueCallIndex();  } +/// \brief Determine whether this is a pointer past the end of the complete +/// object referred to by the lvalue. +static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, +                                            const LValue &LV) { +  // A null pointer can be viewed as being "past the end" but we don't +  // choose to look at it that way here. +  if (!LV.getLValueBase()) +    return false; + +  // If the designator is valid and refers to a subobject, we're not pointing +  // past the end. +  if (!LV.getLValueDesignator().Invalid && +      !LV.getLValueDesignator().isOnePastTheEnd()) +    return false; + +  // We're a past-the-end pointer if we point to the byte after the object, +  // no matter what our type or path is. +  auto Size = Ctx.getTypeSizeInChars(getType(LV.getLValueBase())); +  return LV.getLValueOffset() == Size; +} +  namespace {  /// \brief Data recursive integer evaluator of certain binary operators. @@ -6605,15 +6843,27 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {    QualType LHSTy = E->getLHS()->getType();    QualType RHSTy = E->getRHS()->getType(); -  if (LHSTy->isAnyComplexType()) { -    assert(RHSTy->isAnyComplexType() && "Invalid comparison"); +  if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) {      ComplexValue LHS, RHS; - -    bool LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); +    bool LHSOK; +    if (E->getLHS()->getType()->isRealFloatingType()) { +      LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); +      if (LHSOK) { +        LHS.makeComplexFloat(); +        LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics()); +      } +    } else { +      LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); +    }      if (!LHSOK && !Info.keepEvaluatingAfterFailure())        return false; -    if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) +    if (E->getRHS()->getType()->isRealFloatingType()) { +      if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK) +        return false; +      RHS.makeComplexFloat(); +      RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics()); +    } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)        return false;      if (LHS.isComplexFloat()) { @@ -6736,6 +6986,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {          // object.          if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue))            return Error(E); +        // We can't compare the address of the start of one object with the +        // past-the-end address of another object, per C++ DR1652. +        if ((LHSValue.Base && LHSValue.Offset.isZero() && +             isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) || +            (RHSValue.Base && RHSValue.Offset.isZero() && +             isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) +          return Error(E); +        // We can't tell whether an object is at the same address as another +        // zero sized object. +        if ((RHSValue.Base && isZeroSized(LHSValue)) || +            (LHSValue.Base && isZeroSized(RHSValue))) +          return Error(E);          // Pointers with different bases cannot represent the same object.          // (Note that clang defaults to -fmerge-all-constants, which can          // lead to inconsistent results for comparisons involving the address @@ -6940,39 +7202,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {    return ExprEvaluatorBaseTy::VisitBinaryOperator(E);  } -CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { -  // C++ [expr.alignof]p3: -  //     When alignof is applied to a reference type, the result is the -  //     alignment of the referenced type. -  if (const ReferenceType *Ref = T->getAs<ReferenceType>()) -    T = Ref->getPointeeType(); - -  // __alignof is defined to return the preferred alignment. -  return Info.Ctx.toCharUnitsFromBits( -    Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); -} - -CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) { -  E = E->IgnoreParens(); - -  // The kinds of expressions that we have special-case logic here for -  // should be kept up to date with the special checks for those -  // expressions in Sema. - -  // alignof decl is always accepted, even if it doesn't make sense: we default -  // to 1 in those cases. -  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) -    return Info.Ctx.getDeclAlign(DRE->getDecl(), -                                 /*RefAsPointee*/true); - -  if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) -    return Info.Ctx.getDeclAlign(ME->getMemberDecl(), -                                 /*RefAsPointee*/true); - -  return GetAlignOfType(E->getType()); -} - -  /// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with  /// a result as the expression's type.  bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( @@ -6980,9 +7209,9 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(    switch(E->getKind()) {    case UETT_AlignOf: {      if (E->isArgumentType()) -      return Success(GetAlignOfType(E->getArgumentType()), E); +      return Success(GetAlignOfType(Info, E->getArgumentType()), E);      else -      return Success(GetAlignOfExpr(E->getArgumentExpr()), E); +      return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E);    }    case UETT_VecStep: { @@ -7732,24 +7961,49 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {    if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma)      return ExprEvaluatorBaseTy::VisitBinaryOperator(E); -  bool LHSOK = Visit(E->getLHS()); +  // Track whether the LHS or RHS is real at the type system level. When this is +  // the case we can simplify our evaluation strategy. +  bool LHSReal = false, RHSReal = false; + +  bool LHSOK; +  if (E->getLHS()->getType()->isRealFloatingType()) { +    LHSReal = true; +    APFloat &Real = Result.FloatReal; +    LHSOK = EvaluateFloat(E->getLHS(), Real, Info); +    if (LHSOK) { +      Result.makeComplexFloat(); +      Result.FloatImag = APFloat(Real.getSemantics()); +    } +  } else { +    LHSOK = Visit(E->getLHS()); +  }    if (!LHSOK && !Info.keepEvaluatingAfterFailure())      return false;    ComplexValue RHS; -  if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) +  if (E->getRHS()->getType()->isRealFloatingType()) { +    RHSReal = true; +    APFloat &Real = RHS.FloatReal; +    if (!EvaluateFloat(E->getRHS(), Real, Info) || !LHSOK) +      return false; +    RHS.makeComplexFloat(); +    RHS.FloatImag = APFloat(Real.getSemantics()); +  } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK)      return false; -  assert(Result.isComplexFloat() == RHS.isComplexFloat() && -         "Invalid operands to binary operator."); +  assert(!(LHSReal && RHSReal) && +         "Cannot have both operands of a complex operation be real.");    switch (E->getOpcode()) {    default: return Error(E);    case BO_Add:      if (Result.isComplexFloat()) {        Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),                                         APFloat::rmNearestTiesToEven); -      Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), -                                       APFloat::rmNearestTiesToEven); +      if (LHSReal) +        Result.getComplexFloatImag() = RHS.getComplexFloatImag(); +      else if (!RHSReal) +        Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), +                                         APFloat::rmNearestTiesToEven);      } else {        Result.getComplexIntReal() += RHS.getComplexIntReal();        Result.getComplexIntImag() += RHS.getComplexIntImag(); @@ -7759,8 +8013,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {      if (Result.isComplexFloat()) {        Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),                                              APFloat::rmNearestTiesToEven); -      Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), -                                            APFloat::rmNearestTiesToEven); +      if (LHSReal) { +        Result.getComplexFloatImag() = RHS.getComplexFloatImag(); +        Result.getComplexFloatImag().changeSign(); +      } else if (!RHSReal) { +        Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), +                                              APFloat::rmNearestTiesToEven); +      }      } else {        Result.getComplexIntReal() -= RHS.getComplexIntReal();        Result.getComplexIntImag() -= RHS.getComplexIntImag(); @@ -7768,25 +8027,75 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {      break;    case BO_Mul:      if (Result.isComplexFloat()) { +      // This is an implementation of complex multiplication according to the +      // constraints laid out in C11 Annex G. The implemantion uses the +      // following naming scheme: +      //   (a + ib) * (c + id)        ComplexValue LHS = Result; -      APFloat &LHS_r = LHS.getComplexFloatReal(); -      APFloat &LHS_i = LHS.getComplexFloatImag(); -      APFloat &RHS_r = RHS.getComplexFloatReal(); -      APFloat &RHS_i = RHS.getComplexFloatImag(); - -      APFloat Tmp = LHS_r; -      Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven); -      Result.getComplexFloatReal() = Tmp; -      Tmp = LHS_i; -      Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); -      Result.getComplexFloatReal().subtract(Tmp, APFloat::rmNearestTiesToEven); - -      Tmp = LHS_r; -      Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); -      Result.getComplexFloatImag() = Tmp; -      Tmp = LHS_i; -      Tmp.multiply(RHS_r, APFloat::rmNearestTiesToEven); -      Result.getComplexFloatImag().add(Tmp, APFloat::rmNearestTiesToEven); +      APFloat &A = LHS.getComplexFloatReal(); +      APFloat &B = LHS.getComplexFloatImag(); +      APFloat &C = RHS.getComplexFloatReal(); +      APFloat &D = RHS.getComplexFloatImag(); +      APFloat &ResR = Result.getComplexFloatReal(); +      APFloat &ResI = Result.getComplexFloatImag(); +      if (LHSReal) { +        assert(!RHSReal && "Cannot have two real operands for a complex op!"); +        ResR = A * C; +        ResI = A * D; +      } else if (RHSReal) { +        ResR = C * A; +        ResI = C * B; +      } else { +        // In the fully general case, we need to handle NaNs and infinities +        // robustly. +        APFloat AC = A * C; +        APFloat BD = B * D; +        APFloat AD = A * D; +        APFloat BC = B * C; +        ResR = AC - BD; +        ResI = AD + BC; +        if (ResR.isNaN() && ResI.isNaN()) { +          bool Recalc = false; +          if (A.isInfinity() || B.isInfinity()) { +            A = APFloat::copySign( +                APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); +            B = APFloat::copySign( +                APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); +            if (C.isNaN()) +              C = APFloat::copySign(APFloat(C.getSemantics()), C); +            if (D.isNaN()) +              D = APFloat::copySign(APFloat(D.getSemantics()), D); +            Recalc = true; +          } +          if (C.isInfinity() || D.isInfinity()) { +            C = APFloat::copySign( +                APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); +            D = APFloat::copySign( +                APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); +            if (A.isNaN()) +              A = APFloat::copySign(APFloat(A.getSemantics()), A); +            if (B.isNaN()) +              B = APFloat::copySign(APFloat(B.getSemantics()), B); +            Recalc = true; +          } +          if (!Recalc && (AC.isInfinity() || BD.isInfinity() || +                          AD.isInfinity() || BC.isInfinity())) { +            if (A.isNaN()) +              A = APFloat::copySign(APFloat(A.getSemantics()), A); +            if (B.isNaN()) +              B = APFloat::copySign(APFloat(B.getSemantics()), B); +            if (C.isNaN()) +              C = APFloat::copySign(APFloat(C.getSemantics()), C); +            if (D.isNaN()) +              D = APFloat::copySign(APFloat(D.getSemantics()), D); +            Recalc = true; +          } +          if (Recalc) { +            ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); +            ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); +          } +        } +      }      } else {        ComplexValue LHS = Result;        Result.getComplexIntReal() = @@ -7799,33 +8108,57 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {      break;    case BO_Div:      if (Result.isComplexFloat()) { +      // This is an implementation of complex division according to the +      // constraints laid out in C11 Annex G. The implemantion uses the +      // following naming scheme: +      //   (a + ib) / (c + id)        ComplexValue LHS = Result; -      APFloat &LHS_r = LHS.getComplexFloatReal(); -      APFloat &LHS_i = LHS.getComplexFloatImag(); -      APFloat &RHS_r = RHS.getComplexFloatReal(); -      APFloat &RHS_i = RHS.getComplexFloatImag(); -      APFloat &Res_r = Result.getComplexFloatReal(); -      APFloat &Res_i = Result.getComplexFloatImag(); - -      APFloat Den = RHS_r; -      Den.multiply(RHS_r, APFloat::rmNearestTiesToEven); -      APFloat Tmp = RHS_i; -      Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); -      Den.add(Tmp, APFloat::rmNearestTiesToEven); - -      Res_r = LHS_r; -      Res_r.multiply(RHS_r, APFloat::rmNearestTiesToEven); -      Tmp = LHS_i; -      Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); -      Res_r.add(Tmp, APFloat::rmNearestTiesToEven); -      Res_r.divide(Den, APFloat::rmNearestTiesToEven); - -      Res_i = LHS_i; -      Res_i.multiply(RHS_r, APFloat::rmNearestTiesToEven); -      Tmp = LHS_r; -      Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); -      Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven); -      Res_i.divide(Den, APFloat::rmNearestTiesToEven); +      APFloat &A = LHS.getComplexFloatReal(); +      APFloat &B = LHS.getComplexFloatImag(); +      APFloat &C = RHS.getComplexFloatReal(); +      APFloat &D = RHS.getComplexFloatImag(); +      APFloat &ResR = Result.getComplexFloatReal(); +      APFloat &ResI = Result.getComplexFloatImag(); +      if (RHSReal) { +        ResR = A / C; +        ResI = B / C; +      } else { +        if (LHSReal) { +          // No real optimizations we can do here, stub out with zero. +          B = APFloat::getZero(A.getSemantics()); +        } +        int DenomLogB = 0; +        APFloat MaxCD = maxnum(abs(C), abs(D)); +        if (MaxCD.isFinite()) { +          DenomLogB = ilogb(MaxCD); +          C = scalbn(C, -DenomLogB); +          D = scalbn(D, -DenomLogB); +        } +        APFloat Denom = C * C + D * D; +        ResR = scalbn((A * C + B * D) / Denom, -DenomLogB); +        ResI = scalbn((B * C - A * D) / Denom, -DenomLogB); +        if (ResR.isNaN() && ResI.isNaN()) { +          if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { +            ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; +            ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; +          } else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() && +                     D.isFinite()) { +            A = APFloat::copySign( +                APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); +            B = APFloat::copySign( +                APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); +            ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D); +            ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D); +          } else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) { +            C = APFloat::copySign( +                APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); +            D = APFloat::copySign( +                APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); +            ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D); +            ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D); +          } +        } +      }      } else {        if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0)          return Error(E, diag::note_expr_divide_by_zero); @@ -7966,6 +8299,7 @@ public:      default:        return ExprEvaluatorBaseTy::VisitCallExpr(E);      case Builtin::BI__assume: +    case Builtin::BI__builtin_assume:        // The argument is not evaluated!        return true;      } @@ -8338,6 +8672,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {    case Expr::CXXDeleteExprClass:    case Expr::CXXPseudoDestructorExprClass:    case Expr::UnresolvedLookupExprClass: +  case Expr::TypoExprClass:    case Expr::DependentScopeDeclRefExprClass:    case Expr::CXXConstructExprClass:    case Expr::CXXStdInitializerListExprClass: @@ -8373,6 +8708,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {    case Expr::PseudoObjectExprClass:    case Expr::AtomicExprClass:    case Expr::LambdaExprClass: +  case Expr::CXXFoldExprClass:      return ICEDiag(IK_NotICE, E->getLocStart());    case Expr::InitListExprClass: { @@ -8682,7 +9018,11 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,    if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc))      return false; -  assert(Result.isInt() && "pointer cast to int is not an ICE"); +  if (!Result.isInt()) { +    if (Loc) *Loc = E->getExprLoc(); +    return false; +  } +    if (Value) *Value = Result.getInt();    return true;  } @@ -8751,7 +9091,8 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,    ArgVector ArgValues(Args.size());    for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();         I != E; ++I) { -    if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) +    if ((*I)->isValueDependent() || +        !Evaluate(ArgValues[I - Args.begin()], Info, *I))        // If evaluation fails, throw away the argument entirely.        ArgValues[I - Args.begin()] = APValue();      if (Info.EvalStatus.HasSideEffects) | 
