[clang] 7d8c2a2 - [Clang] Do not apply inaccessiblememonly to ::operator new() (#224316)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 20 23:51:58 PDT 2026
Author: Nikita Popov
Date: 2026-09-21T08:51:52+02:00
New Revision: 7d8c2a2f3436df5c564b61b75cd472f2c4a18a7e
URL: https://github.com/llvm/llvm-project/commit/7d8c2a2f3436df5c564b61b75cd472f2c4a18a7e
DIFF: https://github.com/llvm/llvm-project/commit/7d8c2a2f3436df5c564b61b75cd472f2c4a18a7e.diff
LOG: [Clang] Do not apply inaccessiblememonly to ::operator new() (#224316)
Do not apply `memory(inaccessiblemem: readwrite, errnomem: write)` to
`::operator new()` style calls (as opposed to `new T`). This matches the
cases where we mark the call as `builtin`, i.e. we only consider it
inaccessiblememonly in the cases where the allocation is also elidable.
I've left the old `noalias` handling alone, so that part keeps being
applied to `::operator new()` as before. Let me know if I should move
that to EmitNewDeleteCall() as well.
Added:
Modified:
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CGExprCXX.cpp
clang/test/CodeGenCXX/new_hot_cold.cpp
clang/test/CodeGenCXX/operator-new.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 50e04280e2a7d..4c3a4c75d3b52 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2804,17 +2804,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
AddAttributesFromFunctionProtoType(
getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>());
if (AttrOnCallSite && Fn->isReplaceableGlobalAllocationFunction()) {
- // A sane operator new returns a non-aliasing pointer and does not
- // read or write accessible memory.
+ // A sane operator new returns a non-aliasing pointer.
if (getCodeGenOpts().AssumeSaneOperatorNew &&
- Fn->getDeclName().isAnyOperatorNew()) {
+ Fn->getDeclName().isAnyOperatorNew())
RetAttrs.addAttribute(llvm::Attribute::NoAlias);
- // FIXME: inaccessiblemem could cause issues if LTO makes the
- // previously inaccessible memory accessible after linking.
- FuncAttrs.addMemoryAttr(
- llvm::MemoryEffects::inaccessibleOrErrnoMemOnly(
- llvm::ModRefInfo::ModRef, llvm::ModRefInfo::Mod));
- }
}
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn);
const bool IsVirtualCall = MD && MD->isVirtual();
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 97bfcd7bda4e8..8279611accba3 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1391,9 +1391,19 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
///
/// We model such elidable calls with the 'builtin' attribute.
llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr);
- if (CalleeDecl->isReplaceableGlobalAllocationFunction() && Fn &&
- Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
- CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);
+ if (CalleeDecl->isReplaceableGlobalAllocationFunction() && Fn) {
+ if (Fn->hasFnAttribute(llvm::Attribute::NoBuiltin))
+ CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);
+
+ // A sane operator new does not read or write accessible memory.
+ if (CGF.CGM.getCodeGenOpts().AssumeSaneOperatorNew &&
+ CalleeDecl->getDeclName().isAnyOperatorNew()) {
+ // FIXME: inaccessiblemem could cause issues if LTO makes the
+ // previously inaccessible memory accessible after linking.
+ CallOrInvoke->setMemoryEffects(
+ llvm::MemoryEffects::inaccessibleOrErrnoMemOnly(
+ llvm::ModRefInfo::ModRef, llvm::ModRefInfo::Mod));
+ }
}
return RV;
diff --git a/clang/test/CodeGenCXX/new_hot_cold.cpp b/clang/test/CodeGenCXX/new_hot_cold.cpp
index 439166ddea566..e8ebba1cceee6 100644
--- a/clang/test/CodeGenCXX/new_hot_cold.cpp
+++ b/clang/test/CodeGenCXX/new_hot_cold.cpp
@@ -124,7 +124,7 @@ void hot_cold_new_align_nothrow_array() {
// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = { nobuiltin allocsize(0) {{.*}} }
// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOTHROW]] = { nobuiltin nounwind allocsize(0) {{.*}} }
-// CHECK-DAG: attributes [[ATTR_NO_BUILTIN_CALL]] = { allocsize(0) memory(inaccessiblemem: readwrite, errnomem: write) }
+// CHECK-DAG: attributes [[ATTR_NO_BUILTIN_CALL]] = { allocsize(0) }
// CHECK-DAG: attributes [[ATTR_BUILTIN_CALL]] = { builtin allocsize(0) memory(inaccessiblemem: readwrite, errnomem: write) }
-// CHECK-DAG: attributes [[ATTR_NO_BUILTIN_NOTHROW_CALL]] = { nounwind allocsize(0) memory(inaccessiblemem: readwrite, errnomem: write) }
+// CHECK-DAG: attributes [[ATTR_NO_BUILTIN_NOTHROW_CALL]] = { nounwind allocsize(0) }
// CHECK-DAG: attributes [[ATTR_BUILTIN_NOTHROW_CALL]] = { builtin nounwind allocsize(0) memory(inaccessiblemem: readwrite, errnomem: write) }
diff --git a/clang/test/CodeGenCXX/operator-new.cpp b/clang/test/CodeGenCXX/operator-new.cpp
index e741d85fe4cd2..7d89a24941256 100644
--- a/clang/test/CodeGenCXX/operator-new.cpp
+++ b/clang/test/CodeGenCXX/operator-new.cpp
@@ -27,5 +27,14 @@ void *f2(long N) {
}
// ALL: declare noundef nonnull ptr @_Znaj(
+
+void *f3(unsigned long N) {
+ // SANE: call noalias noundef nonnull ptr @_Znwj(i32 noundef {{.*}}) [[ATTR2:#[0-9]+]]
+ // SANENOT: call noundef nonnull ptr @_Znwj(i32 noundef {{.*}}) [[ATTR2:#[0-9]+]]
+ return ::operator new(N);
+}
+
// SANE: attributes [[ATTR]] = { builtin allocsize(0) memory(inaccessiblemem: readwrite, errnomem: write) }
+// SANE: attributes [[ATTR2]] = { allocsize(0) }
// SANENOT: attributes [[ATTR]] = { builtin allocsize(0) }
+// SANENOT: attributes [[ATTR2]] = { allocsize(0) }
More information about the cfe-commits
mailing list