forked from OSchip/llvm-project
Revert "Improve constant expression evaluation of arrays of unknown bound."
This reverts commit r311970. Breaks internal tests. llvm-svn: 312108
This commit is contained in:
parent
591255183b
commit
542c84b2a1
|
@ -127,10 +127,6 @@ def note_constexpr_access_null : Note<
|
|||
def note_constexpr_access_past_end : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of}0 "
|
||||
"dereferenced one-past-the-end pointer is not allowed in a constant expression">;
|
||||
def note_constexpr_access_unsized_array : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of}0 "
|
||||
"pointer to element of array without known bound "
|
||||
"is not allowed in a constant expression">;
|
||||
def note_constexpr_access_inactive_union_member : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of}0 "
|
||||
"member %1 of union with %select{active member %3|no active member}2 "
|
||||
|
@ -158,11 +154,6 @@ def note_constexpr_baa_insufficient_alignment : Note<
|
|||
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_unsupported_unsized_array : Note<
|
||||
"array-to-pointer decay of array member without known bound is not supported">;
|
||||
def note_constexpr_unsized_array_indexed : Note<
|
||||
"indexing of array without known bound is not allowed "
|
||||
"in a constant expression">;
|
||||
|
||||
def warn_integer_constant_overflow : Warning<
|
||||
"overflow in expression; result is %0 with type %1">,
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace clang {
|
|||
DIAG_SIZE_SERIALIZATION = 120,
|
||||
DIAG_SIZE_LEX = 400,
|
||||
DIAG_SIZE_PARSE = 500,
|
||||
DIAG_SIZE_AST = 150,
|
||||
DIAG_SIZE_AST = 110,
|
||||
DIAG_SIZE_COMMENT = 100,
|
||||
DIAG_SIZE_SEMA = 3500,
|
||||
DIAG_SIZE_ANALYSIS = 100
|
||||
|
|
|
@ -141,12 +141,6 @@ namespace {
|
|||
return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E);
|
||||
}
|
||||
|
||||
/// The bound to claim that an array of unknown bound has.
|
||||
/// 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.
|
||||
static const uint64_t AssumedSizeForUnsizedArray =
|
||||
std::numeric_limits<uint64_t>::max() / 2;
|
||||
|
||||
/// Determines if an LValue with the given LValueBase will have an unsized
|
||||
/// array in its designator.
|
||||
/// Find the path length and type of the most-derived subobject in the given
|
||||
|
@ -154,8 +148,7 @@ namespace {
|
|||
static unsigned
|
||||
findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base,
|
||||
ArrayRef<APValue::LValuePathEntry> Path,
|
||||
uint64_t &ArraySize, QualType &Type, bool &IsArray,
|
||||
bool &FirstEntryIsUnsizedArray) {
|
||||
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) &&
|
||||
|
@ -165,18 +158,12 @@ namespace {
|
|||
|
||||
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
|
||||
if (Type->isArrayType()) {
|
||||
const ArrayType *AT = Ctx.getAsArrayType(Type);
|
||||
Type = AT->getElementType();
|
||||
const ConstantArrayType *CAT =
|
||||
cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
|
||||
Type = CAT->getElementType();
|
||||
ArraySize = CAT->getSize().getZExtValue();
|
||||
MostDerivedLength = I + 1;
|
||||
IsArray = true;
|
||||
|
||||
if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
|
||||
ArraySize = CAT->getSize().getZExtValue();
|
||||
} else {
|
||||
assert(I == 0 && "unexpected unsized array designator");
|
||||
FirstEntryIsUnsizedArray = true;
|
||||
ArraySize = AssumedSizeForUnsizedArray;
|
||||
}
|
||||
} else if (Type->isAnyComplexType()) {
|
||||
const ComplexType *CT = Type->castAs<ComplexType>();
|
||||
Type = CT->getElementType();
|
||||
|
@ -259,12 +246,10 @@ namespace {
|
|||
Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
|
||||
if (V.getLValueBase()) {
|
||||
bool IsArray = false;
|
||||
bool FirstIsUnsizedArray = false;
|
||||
MostDerivedPathLength = findMostDerivedSubobject(
|
||||
Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize,
|
||||
MostDerivedType, IsArray, FirstIsUnsizedArray);
|
||||
MostDerivedType, IsArray);
|
||||
MostDerivedIsArrayElement = IsArray;
|
||||
FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +318,7 @@ namespace {
|
|||
// 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.
|
||||
MostDerivedArraySize = AssumedSizeForUnsizedArray;
|
||||
MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2;
|
||||
MostDerivedPathLength = Entries.size();
|
||||
}
|
||||
/// Update this designator to refer to the given base or member of this
|
||||
|
@ -365,7 +350,6 @@ namespace {
|
|||
MostDerivedArraySize = 2;
|
||||
MostDerivedPathLength = Entries.size();
|
||||
}
|
||||
void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E);
|
||||
void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
|
||||
const APSInt &N);
|
||||
/// Add N to the address of this subobject.
|
||||
|
@ -373,7 +357,6 @@ namespace {
|
|||
if (Invalid || !N) return;
|
||||
uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue();
|
||||
if (isMostDerivedAnUnsizedArray()) {
|
||||
diagnoseUnsizedArrayPointerArithmetic(Info, E);
|
||||
// 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?
|
||||
|
@ -1085,19 +1068,9 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
|
|||
setInvalid();
|
||||
return false;
|
||||
}
|
||||
// Note, we do not diagnose if isMostDerivedAnUnsizedArray(), because there
|
||||
// must actually be at least one array element; even a VLA cannot have a
|
||||
// bound of zero. And if our index is nonzero, we already had a CCEDiag.
|
||||
return true;
|
||||
}
|
||||
|
||||
void SubobjectDesignator::diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info,
|
||||
const Expr *E) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_unsized_array_indexed);
|
||||
// Do not set the designator as invalid: we can represent this situation,
|
||||
// and correct handling of __builtin_object_size requires us to do so.
|
||||
}
|
||||
|
||||
void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
|
||||
const Expr *E,
|
||||
const APSInt &N) {
|
||||
|
@ -1241,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);
|
||||
}
|
||||
|
@ -1313,14 +1288,10 @@ 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 (!Designator.Entries.empty()) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_unsupported_unsized_array);
|
||||
Designator.setInvalid();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(getType(Base)->isPointerType() || getType(Base)->isArrayType());
|
||||
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);
|
||||
}
|
||||
|
@ -2627,11 +2598,9 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
|
|||
if (Sub.Invalid)
|
||||
// A diagnostic will have already been produced.
|
||||
return handler.failed();
|
||||
if (Sub.isOnePastTheEnd() || Sub.isMostDerivedAnUnsizedArray()) {
|
||||
if (Sub.isOnePastTheEnd()) {
|
||||
if (Info.getLangOpts().CPlusPlus11)
|
||||
Info.FFDiag(E, Sub.isOnePastTheEnd()
|
||||
? diag::note_constexpr_access_past_end
|
||||
: diag::note_constexpr_access_unsized_array)
|
||||
Info.FFDiag(E, diag::note_constexpr_access_past_end)
|
||||
<< handler.AccessKind;
|
||||
else
|
||||
Info.FFDiag(E);
|
||||
|
@ -5491,7 +5460,7 @@ static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base,
|
|||
Result.setInvalid(E);
|
||||
|
||||
QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType();
|
||||
Result.addUnsizedArray(Info, E, Pointee);
|
||||
Result.addUnsizedArray(Info, Pointee);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5701,8 +5670,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
case CK_ArrayToPointerDecay: {
|
||||
case CK_ArrayToPointerDecay:
|
||||
if (SubExpr->isGLValue()) {
|
||||
if (!evaluateLValue(SubExpr, Result))
|
||||
return false;
|
||||
|
@ -5713,13 +5681,12 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
|||
return false;
|
||||
}
|
||||
// The result is a pointer to the first element of the array.
|
||||
auto *AT = Info.Ctx.getAsArrayType(SubExpr->getType());
|
||||
if (auto *CAT = dyn_cast<ConstantArrayType>(AT))
|
||||
if (const ConstantArrayType *CAT
|
||||
= Info.Ctx.getAsConstantArrayType(SubExpr->getType()))
|
||||
Result.addArray(Info, E, CAT);
|
||||
else
|
||||
Result.addUnsizedArray(Info, E, AT->getElementType());
|
||||
Result.Designator.setInvalid();
|
||||
return true;
|
||||
}
|
||||
|
||||
case CK_FunctionToPointerDecay:
|
||||
return evaluateLValue(SubExpr, Result);
|
||||
|
@ -5786,7 +5753,7 @@ bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) {
|
|||
|
||||
Result.setInvalid(E);
|
||||
QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType();
|
||||
Result.addUnsizedArray(Info, E, PointeeTy);
|
||||
Result.addUnsizedArray(Info, PointeeTy);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7347,8 +7314,7 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) {
|
|||
/// Please note: this function is specialized for how __builtin_object_size
|
||||
/// views "objects".
|
||||
///
|
||||
/// If this encounters an invalid RecordDecl or otherwise cannot determine the
|
||||
/// correct result, it will always return true.
|
||||
/// If this encounters an invalid RecordDecl, it will always return true.
|
||||
static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
|
||||
assert(!LVal.Designator.Invalid);
|
||||
|
||||
|
@ -7379,8 +7345,9 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
|
|||
unsigned I = 0;
|
||||
QualType BaseType = getType(Base);
|
||||
if (LVal.Designator.FirstEntryIsAnUnsizedArray) {
|
||||
// If we don't know the array bound, conservatively assume we're looking at
|
||||
// the final array element.
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -604,34 +604,6 @@ static_assert(NATDCArray{}[1][1].n == 0, "");
|
|||
|
||||
}
|
||||
|
||||
// FIXME: The rules in this case are unclear, but we conservatively choose to
|
||||
// reject any cases where pointer arithmetic is not statically known to be
|
||||
// valid.
|
||||
namespace ArrayOfUnknownBound {
|
||||
extern int arr[];
|
||||
constexpr int *a = arr;
|
||||
constexpr int *b = &arr[0];
|
||||
static_assert(a == b, "");
|
||||
constexpr int *c = &arr[1]; // expected-error {{constant}} expected-note {{indexing of array without known bound}}
|
||||
constexpr int *d = &a[1]; // expected-error {{constant}} expected-note {{indexing of array without known bound}}
|
||||
constexpr int *e = a + 1; // expected-error {{constant}} expected-note {{indexing of array without known bound}}
|
||||
|
||||
struct X {
|
||||
int a;
|
||||
int b[]; // expected-warning {{C99}}
|
||||
};
|
||||
extern X x;
|
||||
constexpr int *xb = x.b; // expected-error {{constant}} expected-note {{not supported}}
|
||||
|
||||
struct Y { int a; };
|
||||
extern Y yarr[];
|
||||
constexpr Y *p = yarr;
|
||||
constexpr int *q = &p->a;
|
||||
|
||||
extern const int carr[]; // expected-note {{here}}
|
||||
constexpr int n = carr[0]; // expected-error {{constant}} expected-note {{non-constexpr variable}}
|
||||
}
|
||||
|
||||
namespace DependentValues {
|
||||
|
||||
struct I { int n; typedef I V[10]; };
|
||||
|
|
Loading…
Reference in New Issue