-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[Clang][counted_by] Don't treat a __bdos argument as an array if it isn't #125298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
If the __bdos field isn't an array, don't process it. We'll default to using the llvm.objectsize intrinsic.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Bill Wendling (bwendling) ChangesIf the __bdos argument isn't an array (e.g. a pointer), due to Fixes: cff0a46 ("[Clang][counted_by] Refactor __builtin_dynamic_object_size on FAMs (#122198)") Full diff: https://github.com/llvm/llvm-project/pull/125298.diff 1 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 11fa295dad9524..21faf85a16e2d2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1319,12 +1319,36 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
// size_t field_offset = offsetof (struct s, field);
Value *FieldOffset = nullptr;
+ llvm::ConstantInt *FieldBaseSize = nullptr;
if (FlexibleArrayMemberFD != FD) {
std::optional<int64_t> Offset = GetFieldOffset(Ctx, RD, FD);
if (!Offset)
return nullptr;
FieldOffset =
llvm::ConstantInt::get(ResType, *Offset / CharWidth, IsSigned);
+
+ if (Idx) {
+ // From option (4):
+ // size_t field_base_size = sizeof (*ptr->field_array);
+ if (!FieldTy->isArrayType())
+ // The field isn't an array. For example:
+ //
+ // struct {
+ // int count;
+ // char *string;
+ // int array[] __counted_by(count);
+ // } x;
+ //
+ // __builtin_dynamic_object_size(x.string[42], 0);
+ //
+ // If built with '-Wno-int-conversion', FieldTy won't be an array here.
+ return nullptr;
+
+ const ArrayType *ArrayTy = Ctx.getAsArrayType(FieldTy);
+ CharUnits BaseSize = Ctx.getTypeSizeInChars(ArrayTy->getElementType());
+ FieldBaseSize =
+ llvm::ConstantInt::get(ResType, BaseSize.getQuantity(), IsSigned);
+ }
}
// size_t count = (size_t) ptr->count;
@@ -1376,12 +1400,6 @@ CodeGenFunction::emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE,
llvm::ConstantInt::get(ResType, Size.getKnownMinValue() / CharWidth);
if (Idx) { // Option (4) '&ptr->field_array[idx]'
- // size_t field_base_size = sizeof (*ptr->field_array);
- const ArrayType *ArrayTy = Ctx.getAsArrayType(FieldTy);
- CharUnits BaseSize = Ctx.getTypeSizeInChars(ArrayTy->getElementType());
- auto *FieldBaseSize =
- llvm::ConstantInt::get(ResType, BaseSize.getQuantity(), IsSigned);
-
// field_offset += index * field_base_size;
Value *Mul = Builder.CreateMul(Index, FieldBaseSize, "field_offset",
!IsSigned, IsSigned);
|
Note that the early placement of this code is so that no executable code is generated if we have to bail out. |
This tentatively looks good to me. Do you need a reduced test case for this? typedef struct {
char __padding[0];
} spinlock_t;
struct {
int priv_len;
spinlock_t addr_list_lock;
char *dev_addr;
char priv[] __attribute__((__counted_by__(priv_len)));
} falcon_reconfigure_xmac_core_efx;
void falcon_reconfigure_xmac_core() {
long __q_size_field = __builtin_dynamic_object_size(
&falcon_reconfigure_xmac_core_efx.dev_addr[4], 1);
_Bool __ret_do_once = __q_size_field, __ret_cond = __ret_do_once;
static _Bool __already_done;
__ret_cond &&__already_done;
} |
I got a testcase from creduce. It's similar to your testcase. Basically, it's indexing into a pointer field, which isn't going to give the correct result either way. I expect that it's indexing into an array instead. |
Oops! I forgot to push the testcases :) |
Sorry I didn't get around to re-reviewing #122198 earlier... it looks like this is the with lvalue-to-rvalue conversions I mentioned on the review. You do not want to look through lvalue-to-rvalue conversions; the StructFieldAccess visitor should bail out if it sees one. |
@efriedma-quic Thanks, I'll send a patch. |
@efriedma-quic Created #125571 |
This was superseded by #125571. |
If the __bdos argument isn't an array (e.g. a pointer), default
to using the 'llvm.objectsize' intrinsic, since we're not (yet)
able to calculate the size.
Fixes: cff0a46 ("[Clang][counted_by] Refactor __builtin_dynamic_object_size on FAMs (#122198)")
Signed-off-by: Bill Wendling [email protected]