r301963 - Revert r301822 (and dependent r301825), which tried to improve the
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue May 2 13:42:03 PDT 2017
On 2 May 2017 at 12:21, Daniel Jasper via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: djasper
> Date: Tue May 2 14:21:42 2017
> New Revision: 301963
>
> URL: http://llvm.org/viewvc/llvm-project?rev=301963&view=rev
> Log:
> Revert r301822 (and dependent r301825), which tried to improve the
> handling of constexprs with unknown bounds.
>
> This triggers a corner case of the language where it's not yet clear
> whether this should be an error:
>
> struct A {
> static void *const a[];
> static void *const b[];
> };
> constexpr void *A::a[] = {&b[0]};
> constexpr void *A::b[] = {&a[0]};
>
> When discovering the initializer for A::a, the bounds of A::b aren't known
> yet.
> It is unclear whether warning about errors should be deferred until the
> end of
> the translation unit, possibly resolving errors that can be resolved. In
> practice, the compiler can know the bounds of all arrays in this example.
>
I've started a discussion on the C++ core reflector about this.
> Credits for reproducers and explanation go to Richard Smith. Richard,
> please
> add more info in case my explanation is wrong.
>
> Removed:
> cfe/trunk/test/SemaCXX/constexpr-array-unknown-bound.cpp
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> cfe/trunk/lib/AST/ExprConstant.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticASTKinds.td?rev=301963&r1=301962&r2=301963&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Tue May 2
> 14:21:42 2017
> @@ -154,14 +154,12 @@ def note_constexpr_baa_insufficient_alig
> def note_constexpr_baa_value_insufficient_alignment : Note<
> "value of the aligned pointer (%0) is not a multiple of the asserted %1
> "
> "%plural{1:byte|:bytes}1">;
> -def note_constexpr_array_unknown_bound_arithmetic : Note<
> - "cannot perform pointer arithmetic on pointer to array without constant
> bound">;
>
> def warn_integer_constant_overflow : Warning<
> "overflow in expression; result is %0 with type %1">,
> InGroup<DiagGroup<"integer-overflow">>;
>
> -// This is a temporary diagnostic, and shall be removed once our
> +// This is a temporary diagnostic, and shall be removed once our
> // implementation is complete, and like the preceding constexpr notes
> belongs
> // in Sema.
> def note_unimplemented_constexpr_lambda_feature_ast : Note<
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/
> ExprConstant.cpp?rev=301963&r1=301962&r2=301963&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue May 2 14:21:42 2017
> @@ -148,8 +148,7 @@ namespace {
> static unsigned
> findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base,
> ArrayRef<APValue::LValuePathEntry> Path,
> - uint64_t &ArraySize, QualType &Type, bool
> &IsArray,
> - bool &IsUnsizedArray) {
> + uint64_t &ArraySize, QualType &Type, bool
> &IsArray) {
> // This only accepts LValueBases from APValues, and APValues don't
> support
> // arrays that lack size info.
> assert(!isBaseAnAllocSizeCall(Base) &&
> @@ -158,34 +157,28 @@ namespace {
> Type = getType(Base);
>
> for (unsigned I = 0, N = Path.size(); I != N; ++I) {
> - if (auto AT = Ctx.getAsArrayType(Type)) {
> + if (Type->isArrayType()) {
> + const ConstantArrayType *CAT =
> + cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
> + Type = CAT->getElementType();
> + ArraySize = CAT->getSize().getZExtValue();
> MostDerivedLength = I + 1;
> IsArray = true;
> - if (auto CAT = Ctx.getAsConstantArrayType(Type))
> - ArraySize = CAT->getSize().getZExtValue();
> - else {
> - ArraySize = 0;
> - IsUnsizedArray = true;
> - }
> - Type = AT->getElementType();
> } else if (Type->isAnyComplexType()) {
> const ComplexType *CT = Type->castAs<ComplexType>();
> Type = CT->getElementType();
> ArraySize = 2;
> MostDerivedLength = I + 1;
> IsArray = true;
> - IsUnsizedArray = false;
> } else if (const FieldDecl *FD = getAsField(Path[I])) {
> Type = FD->getType();
> ArraySize = 0;
> MostDerivedLength = I + 1;
> IsArray = false;
> - IsUnsizedArray = false;
> } else {
> // Path[I] describes a base class.
> ArraySize = 0;
> IsArray = false;
> - IsUnsizedArray = false;
> }
> }
> return MostDerivedLength;
> @@ -207,9 +200,8 @@ namespace {
> /// Is this a pointer one past the end of an object?
> unsigned IsOnePastTheEnd : 1;
>
> - /// Indicator of whether the most-derived object is an unsized array
> (e.g.
> - /// of unknown bound).
> - unsigned MostDerivedIsAnUnsizedArray : 1;
> + /// Indicator of whether the first entry is an unsized array.
> + unsigned FirstEntryIsAnUnsizedArray : 1;
>
> /// Indicator of whether the most-derived object is an array element.
> unsigned MostDerivedIsArrayElement : 1;
> @@ -239,28 +231,25 @@ namespace {
>
> explicit SubobjectDesignator(QualType T)
> : Invalid(false), IsOnePastTheEnd(false),
> - MostDerivedIsAnUnsizedArray(false), MostDerivedIsArrayElement(
> false),
> + FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(
> false),
> MostDerivedPathLength(0), MostDerivedArraySize(0),
> MostDerivedType(T) {}
>
> SubobjectDesignator(ASTContext &Ctx, const APValue &V)
> : Invalid(!V.isLValue() || !V.hasLValuePath()),
> IsOnePastTheEnd(false),
> - MostDerivedIsAnUnsizedArray(false), MostDerivedIsArrayElement(
> false),
> + FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(
> false),
> MostDerivedPathLength(0), MostDerivedArraySize(0) {
> assert(V.isLValue() && "Non-LValue used to make an LValue
> designator?");
> if (!Invalid) {
> IsOnePastTheEnd = V.isLValueOnePastTheEnd();
> ArrayRef<PathEntry> VEntries = V.getLValuePath();
> Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
> - if (auto Base = V.getLValueBase()) {
> - if (auto Decl = Base.dyn_cast<ValueDecl const*>())
> - Base = cast<ValueDecl>(Decl->getMostRecentDecl());
> - bool IsArray = false, IsUnsizedArray = false;
> + if (V.getLValueBase()) {
> + bool IsArray = false;
> MostDerivedPathLength = findMostDerivedSubobject(
> - Ctx, Base, V.getLValuePath(), MostDerivedArraySize,
> - MostDerivedType, IsArray, IsUnsizedArray);
> - MostDerivedIsArrayElement = IsArray;
> - MostDerivedIsAnUnsizedArray = IsUnsizedArray;
> + Ctx, V.getLValueBase(), V.getLValuePath(),
> MostDerivedArraySize,
> + MostDerivedType, IsArray);
> + MostDerivedIsArrayElement = IsArray;
> }
> }
> }
> @@ -274,7 +263,7 @@ namespace {
> /// known bound.
> bool isMostDerivedAnUnsizedArray() const {
> assert(!Invalid && "Calling this makes no sense on invalid
> designators");
> - return MostDerivedIsAnUnsizedArray;
> + return Entries.size() == 1 && FirstEntryIsAnUnsizedArray;
> }
>
> /// Determine what the most derived array's size is. Results in an
> assertion
> @@ -314,7 +303,6 @@ namespace {
> // This is a most-derived object.
> MostDerivedType = CAT->getElementType();
> MostDerivedIsArrayElement = true;
> - MostDerivedIsAnUnsizedArray = false;
> MostDerivedArraySize = CAT->getSize().getZExtValue();
> MostDerivedPathLength = Entries.size();
> }
> @@ -327,7 +315,6 @@ namespace {
>
> MostDerivedType = ElemTy;
> MostDerivedIsArrayElement = true;
> - MostDerivedIsAnUnsizedArray = true;
> // The value in MostDerivedArraySize is undefined in this case. So,
> set it
> // to an arbitrary value that's likely to loudly break things if
> it's
> // used.
> @@ -346,7 +333,6 @@ namespace {
> if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
> MostDerivedType = FD->getType();
> MostDerivedIsArrayElement = false;
> - MostDerivedIsAnUnsizedArray = false;
> MostDerivedArraySize = 0;
> MostDerivedPathLength = Entries.size();
> }
> @@ -361,14 +347,53 @@ namespace {
> // is unlikely to matter.
> MostDerivedType = EltTy;
> MostDerivedIsArrayElement = true;
> - MostDerivedIsAnUnsizedArray = false;
> MostDerivedArraySize = 2;
> MostDerivedPathLength = Entries.size();
> }
> void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
> const APSInt &N);
> /// Add N to the address of this subobject.
> - void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N);
> + void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N) {
> + if (Invalid || !N) return;
> + uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
> + if (isMostDerivedAnUnsizedArray()) {
> + // Can't verify -- trust that the user is doing the right thing
> (or if
> + // not, trust that the caller will catch the bad behavior).
> + // FIXME: Should we reject if this overflows, at least?
> + Entries.back().ArrayIndex += TruncatedN;
> + return;
> + }
> +
> + // [expr.add]p4: For the purposes of these operators, a pointer to a
> + // nonarray object behaves the same as a pointer to the first
> element of
> + // an array of length one with the type of the object as its
> element type.
> + bool IsArray = MostDerivedPathLength == Entries.size() &&
> + MostDerivedIsArrayElement;
> + uint64_t ArrayIndex =
> + IsArray ? Entries.back().ArrayIndex : (uint64_t)IsOnePastTheEnd;
> + uint64_t ArraySize =
> + IsArray ? getMostDerivedArraySize() : (uint64_t)1;
> +
> + if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) {
> + // Calculate the actual index in a wide enough type, so we can
> include
> + // it in the note.
> + N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65));
> + (llvm::APInt&)N += ArrayIndex;
> + assert(N.ugt(ArraySize) && "bounds check failed for in-bounds
> index");
> + diagnosePointerArithmetic(Info, E, N);
> + setInvalid();
> + return;
> + }
> +
> + ArrayIndex += TruncatedN;
> + assert(ArrayIndex <= ArraySize &&
> + "bounds check succeeded for out-of-bounds index");
> +
> + if (IsArray)
> + Entries.back().ArrayIndex = ArrayIndex;
> + else
> + IsOnePastTheEnd = (ArrayIndex != 0);
> + }
> };
>
> /// A stack frame in the constexpr call stack.
> @@ -470,7 +495,7 @@ namespace {
> // FIXME: Force the precision of the source value down so we don't
> // print digits which are usually useless (we don't really care
> here if
> // we truncate a digit by accident in edge cases). Ideally,
> - // APFloat::toString would automatically print the shortest
> + // APFloat::toString would automatically print the shortest
> // representation which rounds to the correct value, but it's a
> bit
> // tricky to implement.
> unsigned precision =
> @@ -695,7 +720,7 @@ namespace {
> private:
> OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId,
> unsigned ExtraNotes, bool IsCCEDiag) {
> -
> +
> if (EvalStatus.Diag) {
> // If we have a prior diagnostic, it will be noting that the
> expression
> // isn't a constant expression. This diagnostic is more important,
> @@ -748,7 +773,7 @@ namespace {
> unsigned ExtraNotes = 0) {
> return Diag(Loc, DiagId, ExtraNotes, false);
> }
> -
> +
> OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId
> = diag::note_invalid_subexpr_in_const_expr,
> unsigned ExtraNotes = 0) {
> @@ -1061,53 +1086,6 @@ void SubobjectDesignator::diagnosePointe
> setInvalid();
> }
>
> -void SubobjectDesignator::adjustIndex(EvalInfo &Info, const Expr *E,
> APSInt N) {
> - if (Invalid || !N) return;
> -
> - uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
> - if (isMostDerivedAnUnsizedArray()) {
> - // If we're dealing with an array without constant bound, the
> expression is
> - // not a constant expression.
> - if (!Info.checkingPotentialConstantExpression())
> - Info.CCEDiag(E, diag::note_constexpr_array_
> unknown_bound_arithmetic);
> - // Can't verify -- trust that the user is doing the right thing (or if
> - // not, trust that the caller will catch the bad behavior).
> - // FIXME: Should we reject if this overflows, at least?
> - Entries.back().ArrayIndex += TruncatedN;
> - return;
> - }
> -
> - // [expr.add]p4: For the purposes of these operators, a pointer to a
> - // nonarray object behaves the same as a pointer to the first element of
> - // an array of length one with the type of the object as its element
> type.
> - bool IsArray = MostDerivedPathLength == Entries.size() &&
> - MostDerivedIsArrayElement;
> - uint64_t ArrayIndex =
> - IsArray ? Entries.back().ArrayIndex : (uint64_t)IsOnePastTheEnd;
> - uint64_t ArraySize =
> - IsArray ? getMostDerivedArraySize() : (uint64_t)1;
> -
> - if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) {
> - // Calculate the actual index in a wide enough type, so we can include
> - // it in the note.
> - N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65));
> - (llvm::APInt&)N += ArrayIndex;
> - assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index");
> - diagnosePointerArithmetic(Info, E, N);
> - setInvalid();
> - return;
> - }
> -
> - ArrayIndex += TruncatedN;
> - assert(ArrayIndex <= ArraySize &&
> - "bounds check succeeded for out-of-bounds index");
> -
> - if (IsArray)
> - Entries.back().ArrayIndex = ArrayIndex;
> - else
> - IsOnePastTheEnd = (ArrayIndex != 0);
> -}
> -
> CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
> const FunctionDecl *Callee, const LValue
> *This,
> APValue *Arguments)
> @@ -1236,6 +1214,8 @@ namespace {
> IsNullPtr);
> else {
> assert(!InvalidBase && "APValues can't handle invalid LValue
> bases");
> + assert(!Designator.FirstEntryIsAnUnsizedArray &&
> + "Unsized array with a valid base?");
> V = APValue(Base, Offset, Designator.Entries,
> Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
> }
> @@ -1300,9 +1280,12 @@ namespace {
> if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field :
> CSK_Base))
> Designator.addDeclUnchecked(D, Virtual);
> }
> - void addUnsizedArray(EvalInfo &Info, const Expr *E, QualType ElemTy) {
> - if (checkSubobject(Info, E, CSK_ArrayToPointer))
> - Designator.addUnsizedArrayUnchecked(ElemTy);
> + void addUnsizedArray(EvalInfo &Info, QualType ElemTy) {
> + assert(Designator.Entries.empty() && getType(Base)->isPointerType()
> );
> + assert(isBaseAnAllocSizeCall(Base) &&
> + "Only alloc_size bases can have unsized arrays");
> + Designator.FirstEntryIsAnUnsizedArray = true;
> + Designator.addUnsizedArrayUnchecked(ElemTy);
> }
> void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType
> *CAT) {
> if (checkSubobject(Info, E, CSK_ArrayToPointer))
> @@ -3033,15 +3016,6 @@ static CompleteObject findCompleteObject
>
> if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal))
> return CompleteObject();
> -
> - // The complete object can be an array of unknown bound, in which
> case we
> - // have to find the most recent declaration and adjust the type
> accordingly.
> - if (Info.Ctx.getAsIncompleteArrayType(BaseType)) {
> - QualType MostRecentType =
> - cast<ValueDecl const>(D->getMostRecentDecl())->getType();
> - if (Info.Ctx.getAsConstantArrayType(MostRecentType))
> - BaseType = MostRecentType;
> - }
> } else {
> const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
>
> @@ -4124,13 +4098,13 @@ static bool CheckConstexprFunction(EvalI
>
> if (Info.getLangOpts().CPlusPlus11) {
> const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
> -
> +
> // If this function is not constexpr because it is an inherited
> // non-constexpr constructor, diagnose that directly.
> auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
> if (CD && CD->isInheritingConstructor()) {
> auto *Inherited = CD->getInheritedConstructor().getConstructor();
> - if (!Inherited->isConstexpr())
> + if (!Inherited->isConstexpr())
> DiagDecl = CD = Inherited;
> }
>
> @@ -4667,7 +4641,7 @@ public:
> return false;
> This = &ThisVal;
> Args = Args.slice(1);
> - } else if (MD && MD->isLambdaStaticInvoker()) {
> + } else if (MD && MD->isLambdaStaticInvoker()) {
> // Map the static invoker for the lambda back to the call
> operator.
> // Conveniently, we don't have to slice out the 'this' argument
> (as is
> // being done for the non-static case), since a static member
> function
> @@ -4702,7 +4676,7 @@ public:
> FD = LambdaCallOp;
> }
>
> -
> +
> } else
> return Error(E);
>
> @@ -5462,7 +5436,7 @@ static bool evaluateLValueAsAllocSize(Ev
> Result.setInvalid(E);
>
> QualType Pointee = E->getType()->castAs<PointerType>()->
> getPointeeType();
> - Result.addUnsizedArray(Info, E, Pointee);
> + Result.addUnsizedArray(Info, Pointee);
> return true;
> }
>
> @@ -5541,7 +5515,7 @@ public:
> // Update 'Result' to refer to the data member/field of the closure
> object
> // that represents the '*this' capture.
> if (!HandleLValueMember(Info, E, Result,
> - Info.CurrentCall->LambdaThisCaptureField))
> + Info.CurrentCall->LambdaThisCaptureField))
> return false;
> // If we captured '*this' by reference, replace the field with its
> referent.
> if (Info.CurrentCall->LambdaThisCaptureField->getType()
> @@ -5682,18 +5656,12 @@ bool PointerExprEvaluator::VisitCastExpr
> Info, Result, SubExpr))
> return false;
> }
> -
> // The result is a pointer to the first element of the array.
> if (const ConstantArrayType *CAT
> = Info.Ctx.getAsConstantArrayType(SubExpr->getType()))
> Result.addArray(Info, E, CAT);
> - // If the array hasn't been given a bound yet, add it as an unsized
> one.
> - else {
> - auto AT = Info.Ctx.getAsArrayType(SubExpr->getType());
> - assert(AT && "Array to pointer decay on non-array object?");
> - Result.addUnsizedArray(Info, E, AT->getElementType());
> - }
> -
> + else
> + Result.Designator.setInvalid();
> return true;
>
> case CK_FunctionToPointerDecay:
> @@ -5761,7 +5729,7 @@ bool PointerExprEvaluator::visitNonBuilt
>
> Result.setInvalid(E);
> QualType PointeeTy = E->getType()->castAs<PointerType>()->
> getPointeeType();
> - Result.addUnsizedArray(Info, E, PointeeTy);
> + Result.addUnsizedArray(Info, PointeeTy);
> return true;
> }
>
> @@ -6395,7 +6363,7 @@ bool RecordExprEvaluator::VisitLambdaExp
> if (ClosureClass->isInvalidDecl()) return false;
>
> if (Info.checkingPotentialConstantExpression()) return true;
> -
> +
> const size_t NumFields =
> std::distance(ClosureClass->field_begin(),
> ClosureClass->field_end());
>
> @@ -6414,7 +6382,7 @@ bool RecordExprEvaluator::VisitLambdaExp
> assert(CaptureInitIt != E->capture_init_end());
> // Get the initializer for this field
> Expr *const CurFieldInit = *CaptureInitIt++;
> -
> +
> // If there is no initializer, either this is a VLA or an error has
> // occurred.
> if (!CurFieldInit)
> @@ -6615,18 +6583,18 @@ VectorExprEvaluator::VisitInitListExpr(c
>
> // The number of initializers can be less than the number of
> // vector elements. For OpenCL, this can be due to nested vector
> - // initialization. For GCC compatibility, missing trailing elements
> + // initialization. For GCC compatibility, missing trailing elements
> // should be initialized with zeroes.
> unsigned CountInits = 0, CountElts = 0;
> while (CountElts < NumElements) {
> // Handle nested vector initialization.
> - if (CountInits < NumInits
> + if (CountInits < NumInits
> && E->getInit(CountInits)->getType()->isVectorType()) {
> APValue v;
> if (!EvaluateVector(E->getInit(CountInits), v, Info))
> return Error(E);
> unsigned vlen = v.getVectorLength();
> - for (unsigned j = 0; j < vlen; j++)
> + for (unsigned j = 0; j < vlen; j++)
> Elements.push_back(v.getVectorElt(j));
> CountElts += vlen;
> } else if (EltTy->isIntegerType()) {
> @@ -6902,7 +6870,7 @@ public:
> }
>
> bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) {
> - assert(E->getType()->isIntegralOrEnumerationType() &&
> + assert(E->getType()->isIntegralOrEnumerationType() &&
> "Invalid evaluation result.");
> assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
> "Invalid evaluation result.");
> @@ -6916,7 +6884,7 @@ public:
> }
>
> bool Success(uint64_t Value, const Expr *E, APValue &Result) {
> - assert(E->getType()->isIntegralOrEnumerationType() &&
> + assert(E->getType()->isIntegralOrEnumerationType() &&
> "Invalid evaluation result.");
> Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
> return true;
> @@ -6992,7 +6960,7 @@ public:
> }
> return Success(Info.ArrayInitIndex, E);
> }
> -
> +
> // Note, GNU defines __null as an integer, not a pointer.
> bool VisitGNUNullExpr(const GNUNullExpr *E) {
> return ZeroInitialization(E);
> @@ -7356,8 +7324,10 @@ static bool isDesignatorAtObjectEnd(cons
>
> unsigned I = 0;
> QualType BaseType = getType(Base);
> - // If this is an alloc_size base, we should ignore the initial array
> index
> - if (isBaseAnAllocSizeCall(Base)) {
> + if (LVal.Designator.FirstEntryIsAnUnsizedArray) {
> + assert(isBaseAnAllocSizeCall(Base) &&
> + "Unsized array in non-alloc_size call?");
> + // If this is an alloc_size base, we should ignore the initial array
> index
> ++I;
> BaseType = BaseType->castAs<PointerType>()->getPointeeType();
> }
> @@ -8144,12 +8114,12 @@ bool DataRecursiveIntBinOpEvaluator::
> Result = RHSResult.Val;
> return true;
> }
> -
> +
> if (E->isLogicalOp()) {
> bool lhsResult, rhsResult;
> bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult);
> bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult);
> -
> +
> if (LHSIsOK) {
> if (RHSIsOK) {
> if (E->getOpcode() == BO_LOr)
> @@ -8165,26 +8135,26 @@ bool DataRecursiveIntBinOpEvaluator::
> return Success(rhsResult, E, Result);
> }
> }
> -
> +
> return false;
> }
> -
> +
> assert(E->getLHS()->getType()->isIntegralOrEnumerationType() &&
> E->getRHS()->getType()->isIntegralOrEnumerationType());
> -
> +
> if (LHSResult.Failed || RHSResult.Failed)
> return false;
> -
> +
> const APValue &LHSVal = LHSResult.Val;
> const APValue &RHSVal = RHSResult.Val;
> -
> +
> // Handle cases like (unsigned long)&a + 4.
> if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) {
> Result = LHSVal;
> addOrSubLValueAsInteger(Result, RHSVal.getInt(), E->getOpcode() ==
> BO_Sub);
> return true;
> }
> -
> +
> // Handle cases like 4 + (unsigned long)&a
> if (E->getOpcode() == BO_Add &&
> RHSVal.isLValue() && LHSVal.isInt()) {
> @@ -8192,7 +8162,7 @@ bool DataRecursiveIntBinOpEvaluator::
> addOrSubLValueAsInteger(Result, LHSVal.getInt(), /*IsSub*/false);
> return true;
> }
> -
> +
> if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue())
> {
> // Handle (intptr_t)&&A - (intptr_t)&&B.
> if (!LHSVal.getLValueOffset().isZero() ||
> @@ -8231,7 +8201,7 @@ bool DataRecursiveIntBinOpEvaluator::
>
> void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
> Job &job = Queue.back();
> -
> +
> switch (job.Kind) {
> case Job::AnyExprKind: {
> if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(job.E)) {
> @@ -8241,12 +8211,12 @@ void DataRecursiveIntBinOpEvaluator::pro
> return;
> }
> }
> -
> +
> EvaluateExpr(job.E, Result);
> Queue.pop_back();
> return;
> }
> -
> +
> case Job::BinOpKind: {
> const BinaryOperator *Bop = cast<BinaryOperator>(job.E);
> bool SuppressRHSDiags = false;
> @@ -8261,7 +8231,7 @@ void DataRecursiveIntBinOpEvaluator::pro
> enqueue(Bop->getRHS());
> return;
> }
> -
> +
> case Job::BinOpVisitedLHSKind: {
> const BinaryOperator *Bop = cast<BinaryOperator>(job.E);
> EvalResult RHS;
> @@ -8271,7 +8241,7 @@ void DataRecursiveIntBinOpEvaluator::pro
> return;
> }
> }
> -
> +
> llvm_unreachable("Invalid Job::Kind!");
> }
>
> @@ -8783,7 +8753,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr
> const RecordType *BaseRT = CurrentType->getAs<RecordType>();
> if (!BaseRT)
> return Error(OOE);
> -
> +
> // Add the offset to the base.
> Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->
> getDecl()));
> break;
> @@ -9978,7 +9948,7 @@ static bool FastEvaluateAsRValue(const E
> IsConst = false;
> return true;
> }
> -
> +
> // FIXME: Evaluating values of large array and record types can cause
> // performance problems. Only do so in C++11 for now.
> if (Exp->isRValue() && (Exp->getType()->isArrayType() ||
> @@ -10000,7 +9970,7 @@ bool Expr::EvaluateAsRValue(EvalResult &
> bool IsConst;
> if (FastEvaluateAsRValue(this, Result, Ctx, IsConst, false))
> return IsConst;
> -
> +
> EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
> return ::EvaluateAsRValue(Info, this, Result.Val);
> }
>
> Removed: cfe/trunk/test/SemaCXX/constexpr-array-unknown-bound.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/constexpr-array-unknown-bound.cpp?rev=301962&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/constexpr-array-unknown-bound.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constexpr-array-unknown-bound.cpp (removed)
> @@ -1,25 +0,0 @@
> -// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++1z -fsyntax-only -verify
> -
> -const extern int arr[];
> -constexpr auto p = arr; // ok
> -constexpr int f(int i) {return p[i];} // expected-note {{read of
> dereferenced one-past-the-end pointer}}
> -
> -constexpr int arr[] {1, 2, 3};
> -constexpr auto p2 = arr + 2; // ok
> -constexpr int x = f(2); // ok
> -constexpr int y = f(3); // expected-error {{constant expression}}
> -// expected-note-re at -1 {{in call to 'f({{.*}})'}}
> -
> -struct A {int m[];} a;
> -constexpr auto p3 = a.m; // ok
> -constexpr auto p4 = a.m + 1; // expected-error {{constant expression}}
> expected-note {{constant bound}}
> -
> -void g(int i) {
> - int arr[i];
> - constexpr auto *p = arr + 2; // expected-error {{constant expression}}
> expected-note {{constant bound}}
> -
> - // FIXME: Give a better diagnostic here. The issue is that computing
> - // sizeof(*arr2) within the array indexing fails due to the VLA.
> - int arr2[2][i];
> - constexpr int m = ((void)arr2[2], 0); // expected-error {{constant
> expression}}
> -}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170502/1ef45293/attachment-0001.html>
More information about the cfe-commits
mailing list