Skip to content

Commit

Permalink
[clang][ExprConstant] fix __builtin_object_size for flexible array me…
Browse files Browse the repository at this point in the history
…mbers

As reported by @kees, GCC treats __builtin_object_size of structures
containing flexible array members (aka arrays with incomplete type) not
just as the sizeof the underlying type, but additionally the size of the
members in a designated initializer list.

Fixes: #62789

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D150892
  • Loading branch information
nickdesaulniers committed May 22, 2023
1 parent d39a784 commit 57c5c1a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
9 changes: 9 additions & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -51,6 +51,11 @@ C/C++ Language Potentially Breaking Changes
foo: asm goto ("# %0 %1"::"i"(&&foo)::foo);
- ``__builtin_object_size`` and ``__builtin_dynamic_object_size`` now add the
``sizeof`` the elements specified in designated initializers of flexible
array members for structs that contain them. This change is more consistent
with the behavior of GCC.

C++ Specific Potentially Breaking Changes
-----------------------------------------
- Clang won't search for coroutine_traits in std::experimental namespace any more.
Expand Down Expand Up @@ -422,6 +427,10 @@ Bug Fixes in This Version
(`#61746 <https://github.com/llvm/llvm-project/issues/61746>`_).
- Clang `TextNodeDumper` enabled through `-ast-dump` flag no longer evaluates the
initializer of constexpr `VarDecl` if the declaration has a dependent type.
- Match GCC's behavior for ``__builtin_object_size`` and
``__builtin_dynamic_object_size`` on structs containing flexible array
members.
(`#62789 <https://github.com/llvm/llvm-project/issues/62789>`_).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Expand Up @@ -11733,7 +11733,14 @@ static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc,
auto CheckedHandleSizeof = [&](QualType Ty, CharUnits &Result) {
if (Ty.isNull() || Ty->isIncompleteType() || Ty->isFunctionType())
return false;
return HandleSizeof(Info, ExprLoc, Ty, Result);
bool Ret = HandleSizeof(Info, ExprLoc, Ty, Result);
if (Ty->isStructureType() &&
Ty->getAsStructureType()->getDecl()->hasFlexibleArrayMember()) {
const auto *VD =
cast<VarDecl>(LVal.getLValueBase().get<const ValueDecl *>());
Result += VD->getFlexibleArrayInitChars(Info.Ctx);
}
return Ret;
};

// We want to evaluate the size of the entire object. This is a valid fallback
Expand Down
27 changes: 27 additions & 0 deletions clang/test/CodeGen/object-size.c
Expand Up @@ -525,6 +525,33 @@ void test31(void) {
gi = OBJECT_SIZE_BUILTIN(&dsv[9].snd[0], 1);
}

// CHECK-LABEL: @test32
static struct DynStructVar D32 = {
.fst = {},
.snd = { 0, 1, 2, },
};
unsigned long test32(void) {
// CHECK: ret i64 19
return OBJECT_SIZE_BUILTIN(&D32, 1);
}
// CHECK-LABEL: @test33
static struct DynStructVar D33 = {
.fst = {},
.snd = {},
};
unsigned long test33(void) {
// CHECK: ret i64 16
return OBJECT_SIZE_BUILTIN(&D33, 1);
}
// CHECK-LABEL: @test34
static struct DynStructVar D34 = {
.fst = {},
};
unsigned long test34(void) {
// CHECK: ret i64 16
return OBJECT_SIZE_BUILTIN(&D34, 1);
}

// CHECK-LABEL: @PR30346
void PR30346(void) {
struct sa_family_t {};
Expand Down

0 comments on commit 57c5c1a

Please sign in to comment.