Skip to content

Commit 93902a8

Browse files
committed
Allow casts like (char*)&b + 1 to passthrough for non-constexpr const initialization
1 parent a42db2f commit 93902a8

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,7 +2176,7 @@ static bool interp__builtin_assume_dereferenceable(InterpState &S, CodePtr OpPC,
21762176
const CallExpr *Call) {
21772177
assert(Call->getNumArgs() == 2);
21782178

2179-
APSInt ReqSize = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
2179+
APSInt ReqSize = popToAPSInt(S, Call->getArg(1));
21802180
const Pointer &Ptr = S.Stk.pop<Pointer>();
21812181

21822182
if (ReqSize.isZero())
@@ -2186,7 +2186,12 @@ static bool interp__builtin_assume_dereferenceable(InterpState &S, CodePtr OpPC,
21862186
<< AK_Read << S.Current->getRange(OpPC);
21872187
return false;
21882188
}
2189-
if (!Ptr.isLive() || !Ptr.isBlockPointer())
2189+
if (!Ptr.isBlockPointer()) {
2190+
if (Ptr.isIntegralPointer())
2191+
return true;
2192+
return false;
2193+
}
2194+
if (!Ptr.isLive())
21902195
return false;
21912196
if (Ptr.isPastEnd()) {
21922197
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)

clang/lib/AST/ExprConstant.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19701,8 +19701,11 @@ class VoidExprEvaluator
1970119701
return true;
1970219702

1970319703
LValue Pointer;
19704-
if (!EvaluatePointer(E->getArg(0), Pointer, Info))
19704+
if (!EvaluatePointer(E->getArg(0), Pointer, Info)) {
19705+
if (EvaluateBuiltinConstantP(Info, E->getArg(0)))
19706+
return true;
1970519707
return false;
19708+
}
1970619709
if (Pointer.Designator.Invalid)
1970719710
return false;
1970819711
if (Pointer.isNullPointer()) {

clang/test/SemaCXX/builtin-assume-dereferenceable-constexpr.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,24 @@ constexpr int arr2[5] = {1, 2, 3, 4, 5};
9090
constexpr int too_large = (__builtin_assume_dereferenceable(arr2, 6 * sizeof(int)), 12); // expected-error {{constexpr variable 'too_large' must be initialized by a constant expression}} expected-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
9191

9292
constexpr int null = (__builtin_assume_dereferenceable(nullptr, 4), 12); // expected-error {{constexpr variable 'null' must be initialized by a constant expression}} expected-note {{read of dereferenced null pointer is not allowed in a constant expression}}
93+
94+
int b = 10;
95+
const int f = (__builtin_assume_dereferenceable((char*)&b + 1, 3), 12);
96+
int a = f;
97+
98+
int c[10] = {};
99+
const int g = (__builtin_assume_dereferenceable((unsigned char*)c + 5, 35), 42);
100+
int d = g;
101+
102+
long long ll = 100;
103+
const int h = (__builtin_assume_dereferenceable((void*)&ll, 8), 99);
104+
int e = h;
105+
106+
struct Foo { int x; int y; int z; };
107+
Foo foo = {1, 2, 3};
108+
const int i = (__builtin_assume_dereferenceable((short*)&foo + 2, 8), 77);
109+
int j = i;
110+
111+
double darr[10] = {};
112+
const int k = (__builtin_assume_dereferenceable((int*)darr, 40), 55);
113+
int l = k;

0 commit comments

Comments
 (0)