[clang] MSan: poison the default-init allocation before calling constructors (PR #188001)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 23 02:15:58 PDT 2026
https://github.com/dingxiangfei2009 created https://github.com/llvm/llvm-project/pull/188001
This is to address the MSan side of the discrepency between GCC and LLVM.
Related to #185793
_[godbolt](https://godbolt.org/z/PGzKzszMj)_
This change is to align with the standards pertaining to reserved global placement `new`s in the default initialisation style.
>From 6e3b2fa62fc7e7ce547f581d98851302699b033b Mon Sep 17 00:00:00 2001
From: Xiangfei Ding <dingxiangfei2009 at protonmail.ch>
Date: Thu, 19 Mar 2026 16:04:41 +0000
Subject: [PATCH] MSan: poison the default-init allocation before calling
constructors
This change is to align with the standards pertaining to reserved global
placement `new`s in the default initialisation style.
Signed-off-by: Xiangfei Ding <dingxiangfei2009 at protonmail.ch>
---
clang/lib/CodeGen/CGExprCXX.cpp | 8 ++++
.../test/CodeGenCXX/sanitize-default-init.cpp | 38 +++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 clang/test/CodeGenCXX/sanitize-default-init.cpp
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 82300c3ede183..864d29a70a738 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -17,8 +17,11 @@
#include "CodeGenFunction.h"
#include "ConstantEmitter.h"
#include "TargetInfo.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Intrinsics.h"
using namespace clang;
@@ -1611,6 +1614,11 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
allocatorArgs.add(RValue::get(allocation, *this), arg->getType());
}
+ if (E->getInitializationStyle() == CXXNewInitializationStyle::None &&
+ SanOpts.has(SanitizerKind::Memory)) {
+ Builder.CreateStore(llvm::PoisonValue::get(ConvertTypeForMem(allocType)),
+ allocation);
+ }
} else {
const FunctionProtoType *allocatorType =
allocator->getType()->castAs<FunctionProtoType>();
diff --git a/clang/test/CodeGenCXX/sanitize-default-init.cpp b/clang/test/CodeGenCXX/sanitize-default-init.cpp
new file mode 100644
index 0000000000000..b9f864c6db085
--- /dev/null
+++ b/clang/test/CodeGenCXX/sanitize-default-init.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -x c++ -fsanitize=memory -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+
+// Sanitise the placement new with default initialisation style.
+
+namespace std {
+ using size_t = decltype(sizeof(0));
+} // end namespace std
+
+void *operator new(std::size_t, void *p) noexcept { return p; }
+
+struct Simple {
+ int x;
+};
+
+struct WithCtor {
+ int x;
+ WithCtor() {
+ bool flag = x > 0;
+ }
+};
+
+// CHECK-LABEL: define {{.*}} i32 @main()
+int main() {
+ {
+ Simple s;
+ s.x = 42;
+ // CHECK: store %struct.Simple poison,
+ new (&s) Simple;
+ bool flag = s.x == 42; // This is UB
+ }
+ {
+ WithCtor w;
+ w.x = 42;
+ // CHECK: store %struct.WithCtor poison,
+ auto *ptr = new (&w) WithCtor; // This is UB
+ // CHECK: call void @_ZN8WithCtorC1Ev
+ }
+}
More information about the cfe-commits
mailing list