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) } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
