Skip to content

Commit

Permalink
Revert "[Sema] Address-space sensitive check for unbounded arrays (v2)"
Browse files Browse the repository at this point in the history
This reverts commit e42a347.
  • Loading branch information
tauchris committed Jun 11, 2021
1 parent e42a347 commit 7e9822c
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 170 deletions.
8 changes: 0 additions & 8 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -9176,14 +9176,6 @@ def warn_array_index_precedes_bounds : Warning<
def warn_array_index_exceeds_bounds : Warning<
"array index %0 is past the end of the array (which contains %1 "
"element%s2)">, InGroup<ArrayBounds>;
def warn_ptr_arith_exceeds_max_addressable_bounds : Warning<
"the pointer incremented by %0 refers past the last possible element for an array in %1-bit "
"address space containing %2-bit (%3-byte) elements (max possible %4 element%s5)">,
InGroup<ArrayBounds>;
def warn_array_index_exceeds_max_addressable_bounds : Warning<
"array index %0 refers past the last possible element for an array in %1-bit "
"address space containing %2-bit (%3-byte) elements (max possible %4 element%s5)">,
InGroup<ArrayBounds>;
def note_array_declared_here : Note<
"array %0 declared here">;

Expand Down
89 changes: 13 additions & 76 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -14536,92 +14536,27 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ConstantArrayType *ArrayTy =
Context.getAsConstantArrayType(BaseExpr->getType());

const Type *BaseType =
ArrayTy == nullptr ? nullptr : ArrayTy->getElementType().getTypePtr();
bool IsUnboundedArray = (BaseType == nullptr);
if (EffectiveType->isDependentType() ||
(!IsUnboundedArray && BaseType->isDependentType()))
if (!ArrayTy)
return;

const Type *BaseType = ArrayTy->getElementType().getTypePtr();
if (EffectiveType->isDependentType() || BaseType->isDependentType())
return;

Expr::EvalResult Result;
if (!IndexExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects))
return;

llvm::APSInt index = Result.Val.getInt();
if (IndexNegated) {
index.setIsUnsigned(false);
if (IndexNegated)
index = -index;
}

const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = DRE->getDecl();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();

if (IsUnboundedArray) {
if (index.isUnsigned() || !index.isNegative()) {
const auto &ASTC = getASTContext();
unsigned AddrBits =
ASTC.getTargetInfo().getPointerWidth(ASTC.getTargetAddressSpace(
EffectiveType->getCanonicalTypeInternal()));
if (index.getBitWidth() < AddrBits)
index = index.zext(AddrBits);
CharUnits ElemCharUnits = ASTC.getTypeSizeInChars(EffectiveType);
llvm::APInt ElemBytes(index.getBitWidth(), ElemCharUnits.getQuantity());
// If index has more active bits than address space, we already know
// we have a bounds violation to warn about. Otherwise, compute
// address of (index + 1)th element, and warn about bounds violation
// only if that address exceeds address space.
if (index.getActiveBits() <= AddrBits) {
bool Overflow;
llvm::APInt Product(index);
Product += 1;
Product = Product.umul_ov(ElemBytes, Overflow);
if (!Overflow && Product.getActiveBits() <= AddrBits)
return;
}

// Need to compute max possible elements in address space, since that
// is included in diag message.
llvm::APInt MaxElems = llvm::APInt::getMaxValue(AddrBits);
MaxElems = MaxElems.zext(std::max(AddrBits + 1, ElemBytes.getBitWidth()));
MaxElems += 1;
ElemBytes = ElemBytes.zextOrTrunc(MaxElems.getBitWidth());
MaxElems = MaxElems.udiv(ElemBytes);

unsigned DiagID =
ASE ? diag::warn_array_index_exceeds_max_addressable_bounds
: diag::warn_ptr_arith_exceeds_max_addressable_bounds;

// Diag message shows element size in bits and in "bytes" (platform-
// dependent CharUnits)
DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
PDiag(DiagID)
<< index.toString(10, true) << AddrBits
<< (unsigned)ASTC.toBits(ElemCharUnits)
<< ElemBytes.toString(10, false)
<< MaxElems.toString(10, false)
<< (unsigned)MaxElems.getLimitedValue(~0U)
<< IndexExpr->getSourceRange());

if (!ND) {
// Try harder to find a NamedDecl to point at in the note.
while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
BaseExpr = ASE->getBase()->IgnoreParenCasts();
if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = DRE->getDecl();
if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();
}

if (ND)
DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
PDiag(diag::note_array_declared_here) << ND);
}
return;
}

if (index.isUnsigned() || !index.isNegative()) {
// It is possible that the type of the base expression after
// IgnoreParenCasts is incomplete, even though the type of the base
Expand Down Expand Up @@ -14684,8 +14619,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
}
}

unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds
: diag::warn_ptr_arith_exceeds_bounds;
unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds;
if (ASE)
DiagID = diag::warn_array_index_exceeds_bounds;

DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
PDiag(DiagID) << toString(index, 10, true)
Expand All @@ -14706,11 +14642,12 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,

if (!ND) {
// Try harder to find a NamedDecl to point at in the note.
while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
while (const ArraySubscriptExpr *ASE =
dyn_cast<ArraySubscriptExpr>(BaseExpr))
BaseExpr = ASE->getBase()->IgnoreParenCasts();
if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = DRE->getDecl();
if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();
}

Expand Down
8 changes: 4 additions & 4 deletions clang/test/Sema/const-eval.c
Expand Up @@ -140,10 +140,10 @@ EVAL_EXPR(52, &pr24622 == (void *)&PR24622); // expected-error {{not an integer

// We evaluate these by providing 2s' complement semantics in constant
// expressions, like we do for integers.
void *PR28739a = (__int128)(unsigned long)-1 + &PR28739a; // expected-warning {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 64-bit (8-byte) elements (max possible 2305843009213693952 elements)}}
void *PR28739b = &PR28739b + (__int128)(unsigned long)-1; // expected-warning {{refers past the last possible element}}
__int128 PR28739c = (&PR28739c + (__int128)(unsigned long)-1) - &PR28739c; // expected-warning {{refers past the last possible element}}
void *PR28739d = &(&PR28739d)[(__int128)(unsigned long)-1]; // expected-warning {{refers past the last possible element}}
void *PR28739a = (__int128)(unsigned long)-1 + &PR28739a;
void *PR28739b = &PR28739b + (__int128)(unsigned long)-1;
__int128 PR28739c = (&PR28739c + (__int128)(unsigned long)-1) - &PR28739c;
void *PR28739d = &(&PR28739d)[(__int128)(unsigned long)-1];

struct PR35214_X {
int k;
Expand Down
80 changes: 0 additions & 80 deletions clang/test/Sema/unbounded-array-bounds.c

This file was deleted.

3 changes: 1 addition & 2 deletions clang/test/SemaCXX/constant-expression-cxx14.cpp
Expand Up @@ -1027,9 +1027,8 @@ constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant
}

constexpr void PR28739(int n) { // expected-error {{never produces a constant}}
int *p = &n; // expected-note {{array 'p' declared here}}
int *p = &n;
p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
// expected-warning@-1 {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 32-bit (4-byte) elements (max possible 4611686018427387904 elements)}}
}

constexpr void Void(int n) {
Expand Down

0 comments on commit 7e9822c

Please sign in to comment.