Add -fcheck-new and -fno-check-new, from GCC, which make the compiler
not assume pointers returned from operator new are non-null.
Fixes #16931.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Time | Test | |
---|---|---|
50 ms | x64 debian > Clang.CodeGenCXX::fcheck-new.cpp |
Event Timeline
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
2 | Do you really want -O2 or do you just want to run mem2reg to eliminate all the alloca noise? |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
2 | I added -O2 because I was testing with it, since if -fcheck-new doesn't work, it's way more noticeable, as the nullptr check gets optimized out; if it works, the branching is pretty visible and shows exactly what the option does. Also, to eliminate all the noise :) I can definitely remove -O2 though, if you want to. |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
2 | Thinking about this more, I think the branching complicates matters. All that optimisation happens in LLVM IR land, but you're just touching Clang CodeGen. Is int *foo() { return new int; } checking the attributes on the call to _Znwm not enough (and with mem2reg just to clean it up so the function body is trivial)? Also you should specify a target triple as this will just be LLVM_DEFAULT_TARGET_TRIPLE and change both the type for new (i32 vs i64) and its mangling (j vs m for unsigned int vs unsigned long, and *-windows-msvc is totally different), right? | |
9 | Another advantage of not using -O2 is you lose the TBAA noise | |
clang/test/Driver/clang_f_opts.c | ||
73 | Hmmm |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
2 | Not sure why they were checked before, but you'll need this to actually get the attributes checked |
clang/test/Driver/clang_f_opts.c | ||
---|---|---|
73 | Huh, running clang-format on clang_f_opts.c makes it do that. I fixed that up in the new revision but that should possibly be fixed. |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
3 | Not sure how this doesn't need -Xclang -disable-O0-optnone to work?.. |
clang/lib/Sema/SemaDecl.cpp | ||
---|---|---|
15440 | 'invalidates' or 'negates' are better words here. |
Could someone please review it or tell me what needs to be done before pushing this? Thanks.
clang/lib/Frontend/CompilerInvocation.cpp | ||
---|---|---|
4117 | Use CodeGenOpts<"CheckNew"> and avoid change to this file. CodeGenOpts seems more suitable than LangOpts. | |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
4 | Please remove opt. Optimizations should be tested in the llvm/ layer, not in clang codegen. If utils/update_cc_test_checks.py does not generate good looking IR, write it by hand. |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
4 | Disagree. This is a pattern that is extremely useful for testing Clang's IR generation whilst cleaning up the alloca so the IR is readable. This is not about the generated checks, this is about alloca/load/store everywhere being a pain to inspect, whereas a simple mem2reg cleans this up. |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
4 | How should I proceed about this? Sorry, I haven't thought about this pending change-set for a few months now, oops! |
This review may be stuck/dead, consider abandoning if no longer relevant.
Removing myself as reviewer in attempt to clean dashboard.
clang/lib/Frontend/CompilerInvocation.cpp | ||
---|---|---|
4117 | Sorry, I haven't looked at this rev in a good while due to $REASONS. Could you elaborate on this? I'm not opposed to moving it to CodeGenOpts per se, but I would like to understand your reasoning. It seems to me that fcheck-new is more of a language change (since it removes the implicit [[nonnull]] on the result of operator new) than a codegen change, although it does have its effects on codegen, naturally. A quick look at CodeGenOpts in Options.td would hint to me that these mostly/only affect codegen itself. What do you think? |
clang/lib/Frontend/CompilerInvocation.cpp | ||
---|---|---|
4117 | OK. LangOpts looks good since it affects Sema and in GCC this option is a C++ dialect option (https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html). Can you use MarshallingInfoFlag<LangOpts and remove the change to CompilerInvocation.cpp? You can find other MarshallingInfoFlag<LangOpts examples in Options.td |
Address MaskRay's comments on Options.td, adjust the help message, rebase to current tip
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
3 | It will change (the attributes of _Znwm). From the test (with -fcheck-new): [[CALL:%.*]] = call noalias noundef ptr @_Znwm(i64 noundef 4) #[[ATTR2:[0-9]+]] The same test (but without -fcheck-new, tested locally): %1 = tail call noalias noundef nonnull dereferenceable(4) ptr @_Znwm(i64 noundef 4) #2 As you'll see, the non-fcheck-new has nonnull attached to _Znwm, while -fcheck-new doesn't. This is exactly the behavior we want to test for. |
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
3 | OK, you are right about nonull. I think my point still holds as with a constructor the effect will be more visible with a new.notnull: basic block. Also, with the simple IR, opt -S -mem2reg is a no-op. You should remove it. | |
8 | #[[ATTR2:[0-9]+]] If ATTR2 is not checked, remove #[[ATTR2:[0-9]+]] |
Addressed MaskRay's feedback:
Added a testcase that showcases the conditional calling of a constructor (due to new not being tagged nonnull) Kept the testcase with the simple _Znwm call Deleted the ATTR tags at the end Removed opt mem2reg
clang/test/CodeGenCXX/fcheck-new.cpp | ||
---|---|---|
4 | remove -S since -emit-llvm wins .This is different from clang driver -S -emit-llvm |
See addOptInFlag in this file.