Index: clang/docs/ClangCommandLineReference.rst =================================================================== --- clang/docs/ClangCommandLineReference.rst +++ clang/docs/ClangCommandLineReference.rst @@ -1941,6 +1941,10 @@ Specifies the largest alignment guaranteed by '::operator new(size\_t)' +.. option:: -fnew-infallible + +Treats throwing global C++ operator new as always returning valid memory (annotates with \_\_attribute\_\_((returns\_nonnull)) and throw()) + .. option:: -fnext-runtime .. option:: -fno-builtin- Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -276,6 +276,7 @@ "hidden visibility for static local variables in inline C++ " "methods when -fvisibility-inlines hidden is enabled") LANGOPT(GlobalAllocationFunctionVisibilityHidden , 1, 0, "hidden visibility for global operator new and delete declaration") +LANGOPT(NewInfallible , 1, 0, "Treats throwing global C++ operator new as always returning valid memory (annotates with __attribute__((returns_nonnull)) and throw())") BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2701,6 +2701,8 @@ def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group, HelpText<"Give global C++ operator new and delete declarations hidden visibility">, Flags<[CC1Option]>, MarshallingInfoFlag>; +def fnew_infallible : Flag<["-"], "fnew-infallible">, Group, + HelpText<"Treats throwing global C++ operator new as always returning valid memory (annotates with __attribute__((returns_nonnull)) and throw())">, Flags<[CC1Option]>, MarshallingInfoFlag>; defm whole_program_vtables : BoolFOption<"whole-program-vtables", CodeGenOpts<"WholeProgramVTables">, DefaultFalse, PosFlag, Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5671,7 +5671,7 @@ Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var, options::OPT_fno_visibility_inlines_hidden_static_local_var); Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden); - + Args.AddLastArg(CmdArgs, options::OPT_fnew_infallible); Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ); if (Args.hasFlag(options::OPT_fno_operator_names, Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -3049,6 +3049,9 @@ EPI.ExceptionSpec.Type = EST_Dynamic; EPI.ExceptionSpec.Exceptions = llvm::makeArrayRef(BadAllocType); } + if (getLangOpts().NewInfallible) { + EPI.ExceptionSpec.Type = EST_DynamicNone; + } } else { EPI.ExceptionSpec = getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; @@ -3063,6 +3066,10 @@ // Global allocation functions should always be visible. Alloc->setVisibleDespiteOwningModule(); + if (HasBadAllocExceptionSpec && getLangOpts().NewInfallible) + Alloc->addAttr( + ReturnsNonNullAttr::CreateImplicit(Context, Alloc->getLocation())); + Alloc->addAttr(VisibilityAttr::CreateImplicit( Context, LangOpts.GlobalAllocationFunctionVisibilityHidden ? VisibilityAttr::Hidden Index: clang/test/CodeGenCXX/new-infallible.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/new-infallible.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fnew-infallible -o - %s | FileCheck %s + +// CHECK: call noalias nonnull i8* @_Znwm(i64 4) + +// CHECK: ; Function Attrs: nobuiltin nounwind allocsize(0) +// CHECK-NEXT: declare nonnull i8* @_Znwm(i64) +int *new_infallible = new int;