diff options
| author | Eli Friedman <efriedma@quicinc.com> | 2024-08-01 16:18:20 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-01 16:18:20 -0700 |
| commit | 1762e01cca0186f1862db561cfd9019164b8c654 (patch) | |
| tree | b4f4bdc94d8d492246e220640c67bf4b110bcbc8 /clang/lib/CodeGen/CGExprAgg.cpp | |
| parent | ae6dc64ec670891cb15049277e43133d4df7fb4b (diff) | |
| download | llvm-1762e01cca0186f1862db561cfd9019164b8c654.zip llvm-1762e01cca0186f1862db561cfd9019164b8c654.tar.gz llvm-1762e01cca0186f1862db561cfd9019164b8c654.tar.bz2 | |
Fix codegen of consteval functions returning an empty class, and related issues (#93115)
Fix codegen of consteval functions returning an empty class, and related
issues
If a class is empty, don't store it to memory: the store might overwrite
useful data. Similarly, if a class has tail padding that might overlap
other fields, don't store the tail padding to memory.
The problem here turned out a bit more general than I initially thought:
basically all uses of EmitAggregateStore were broken. Call lowering had
a method that did mostly the right thing, though: CreateCoercedStore.
Adapt CreateCoercedStore so it always does the conservatively right
thing, and use it for both calls and ConstantExpr.
Also, along the way, fix the "overlap" bit in AggValueSlot: the bit was
set incorrectly for empty classes in some cases.
Fixes #93040.
Diffstat (limited to 'clang/lib/CodeGen/CGExprAgg.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index c3c10e7..d9f44f4 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -131,15 +131,12 @@ public: EnsureDest(E->getType()); if (llvm::Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) { - Address StoreDest = Dest.getAddress(); - // The emitted value is guaranteed to have the same size as the - // destination but can have a different type. Just do a bitcast in this - // case to avoid incorrect GEPs. - if (Result->getType() != StoreDest.getType()) - StoreDest = StoreDest.withElementType(Result->getType()); - - CGF.EmitAggregateStore(Result, StoreDest, - E->getType().isVolatileQualified()); + CGF.CreateCoercedStore( + Result, Dest.getAddress(), + llvm::TypeSize::getFixed( + Dest.getPreferredSize(CGF.getContext(), E->getType()) + .getQuantity()), + E->getType().isVolatileQualified()); return; } return Visit(E->getSubExpr()); @@ -2050,6 +2047,10 @@ CodeGenFunction::getOverlapForFieldInit(const FieldDecl *FD) { if (!FD->hasAttr<NoUniqueAddressAttr>() || !FD->getType()->isRecordType()) return AggValueSlot::DoesNotOverlap; + // Empty fields can overlap earlier fields. + if (FD->getType()->getAsCXXRecordDecl()->isEmpty()) + return AggValueSlot::MayOverlap; + // If the field lies entirely within the enclosing class's nvsize, its tail // padding cannot overlap any already-initialized object. (The only subobjects // with greater addresses that might already be initialized are vbases.) @@ -2072,6 +2073,10 @@ AggValueSlot::Overlap_t CodeGenFunction::getOverlapForBaseInit( if (IsVirtual) return AggValueSlot::MayOverlap; + // Empty bases can overlap earlier bases. + if (BaseRD->isEmpty()) + return AggValueSlot::MayOverlap; + // If the base class is laid out entirely within the nvsize of the derived // class, its tail padding cannot yet be initialized, so we can issue // stores at the full width of the base class. |
