https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/93115
If a class is empty, don't store it to memory: the store might overwrite useful data. (See also d60c3d08.) Fixes #93040. >From bdfcc729c309fc5b1092b67d7c3c803c852ae251 Mon Sep 17 00:00:00 2001 From: Eli Friedman <efrie...@quicinc.com> Date: Wed, 22 May 2024 17:30:41 -0700 Subject: [PATCH] Fix codegen of consteval functions returning an empty class. If a class is empty, don't store it to memory: the store might overwrite useful data. (See also d60c3d08.) Fixes #93040. --- clang/lib/CodeGen/CGExprAgg.cpp | 11 +++++++++++ clang/test/CodeGenCXX/cxx2a-consteval.cpp | 24 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index bba00257fd4f0..b1638fa318270 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -135,6 +135,17 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { EnsureDest(E->getType()); if (llvm::Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) { + // An empty record can overlap other data (if declared with + // no_unique_address); omit the store for such types - as there is no + // actual data to store. + if (CGF.getLangOpts().CPlusPlus) { + if (const RecordType *RT = E->getType()->getAs<RecordType>()) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); + if (Record->isEmpty()) + return; + } + } + 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 diff --git a/clang/test/CodeGenCXX/cxx2a-consteval.cpp b/clang/test/CodeGenCXX/cxx2a-consteval.cpp index 075cab58358ab..5d5a62f9928fe 100644 --- a/clang/test/CodeGenCXX/cxx2a-consteval.cpp +++ b/clang/test/CodeGenCXX/cxx2a-consteval.cpp @@ -1,4 +1,3 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s @@ -275,3 +274,26 @@ void f() { // EVAL-FN: call void @_ZN7GH821542S3C2Ei } } + +namespace GH93040 { +struct C { char c = 1; }; +struct Empty { consteval Empty() {} }; +struct Test : C, Empty { + [[no_unique_address]] Empty e; +}; + +void f() { + Test test; + +// Make sure we don't overwrite the initialization of c. + +// EVAL-FN-LABEL: define {{.*}} void @_ZN7GH930404TestC2Ev +// EVAL-FN: entry: +// EVAL-FN-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// EVAL-FN-NEXT: store ptr {{.*}}, ptr [[THIS_ADDR]], align 8 +// EVAL-FN-NEXT: [[THIS:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// EVAL-FN-NEXT: call void @_ZN7GH930401CC2Ev(ptr noundef nonnull align 1 dereferenceable(1) [[THIS]]) +// EVAL-FN-NEXT: %0 = getelementptr inbounds i8, ptr [[THIS]], i64 1 +// EVAL-FN-NEXT: ret void +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits