This is an archive of the discontinued LLVM Phabricator instance.

Skip exception cleanups when the innermost scope is EHTerminateScope.
ClosedPublic

Authored by jyknight on Nov 10 2021, 2:46 PM.

Details

Summary

EHTerminateScope is used to implement C++ noexcept semantics, and per
C++ [except.terminate], it is implemented-defined whether no, some, or
all cleanups are run prior to terminate.

We now define the behavior as "some" -- cleanups in nested function
calls will still be run, but not those in the noexcept function
itself.

Diff Detail

Event Timeline

jyknight requested review of this revision.Nov 10 2021, 2:46 PM
jyknight created this revision.
Herald added a project: Restricted Project. · View Herald Transcript
rsmith accepted this revision.Dec 6 2021, 3:35 PM

I think it's generally better to not run cleanups on the way to a terminate call, not only for code size but also for debuggability. This change seems like an improvement to me.

clang/lib/CodeGen/CGCleanup.cpp
189

Does the situation where both IsEHCleanup and IsNormalCleanup end up set to false work well? (Eg, do we avoid generating cleanup code entirely, even for things like conditional cleanups where we might otherwise generate a condition variable?) Eg, in a case like this:

struct A { A(); ~A() noexcept(false); };
void f(bool b) noexcept { (b ? (void)A() : void()), (b ? (void)A() : void()); }

... we currently inject some i1s to track whether each A is alive, and could presumably omit them here.

If this patch isn't enough to handle that, maybe this isn't worth worrying about at this level and we can just let the optimizer remove them again?

This revision is now accepted and ready to land.Dec 6 2021, 3:35 PM
This revision was landed with ongoing or failed builds.Jan 14 2022, 3:02 PM
This revision was automatically updated to reflect the committed changes.

Is this from the patch https://lab.llvm.org/buildbot/#/builders/127/builds/22789/steps/8/logs/stdio

FAILED: projects/compiler-rt/lib/sanitizer_common/tests/SANITIZER_TEST_OBJECTS.sanitizer_leb128_test.cpp.x86_64.o 
cmd.exe /C "cd /D C:\b\slave\sanitizer-windows\build\stage1\projects\compiler-rt\lib\sanitizer_common\tests && C:\b\slave\sanitizer-windows\build\stage1\.\bin\clang.exe -DGTEST_NO_LLVM_SUPPORT=1 -DGTEST_HAS_RTTI=0 -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googletest/include -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googletest -Wno-deprecated-declarations -DGTEST_NO_LLVM_SUPPORT=1 -DGTEST_HAS_RTTI=0 -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googlemock/include -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googlemock -IC:/b/slave/sanitizer-windows/llvm-project/compiler-rt/include -IC:/b/slave/sanitizer-windows/llvm-project/compiler-rt/lib -IC:/b/slave/sanitizer-windows/llvm-project/compiler-rt/lib/sanitizer_common -fno-rtti -O2 -Werror=sign-compare -Wno-gnu-zero-variadic-macro-arguments -gline-tables-only -gcodeview -c -o SANITIZER_TEST_OBJECTS.sanitizer_leb128_test.cpp.x86_64.o C:/b/slave/sanitizer-windows/llvm-project/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp"
Assertion failed: C != EHStack.stable_end() && "deactivating bottom of stack?", file C:\b\slave\sanitizer-windows\llvm-project\clang\lib\CodeGen\CGCleanup.cpp, line 1281
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: C:\\b\\slave\\sanitizer-windows\\build\\stage1\\.\\bin\\clang.exe -DGTEST_NO_LLVM_SUPPORT=1 -DGTEST_HAS_RTTI=0 -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googletest/include -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googletest -Wno-deprecated-declarations -DGTEST_NO_LLVM_SUPPORT=1 -DGTEST_HAS_RTTI=0 -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googlemock/include -IC:/b/slave/sanitizer-windows/llvm-project/llvm/utils/unittest/googlemock -IC:/b/slave/sanitizer-windows/llvm-project/compiler-rt/include -IC:/b/slave/sanitizer-windows/llvm-project/compiler-rt/lib -IC:/b/slave/sanitizer-windows/llvm-project/compiler-rt/lib/sanitizer_common -fno-rtti -O2 -Werror=sign-compare -Wno-gnu-zero-variadic-macro-arguments -gline-tables-only -gcodeview -c -o SANITIZER_TEST_OBJECTS.sanitizer_leb128_test.cpp.x86_64.o C:/b/slave/sanitizer-windows/llvm-project/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp
1.	<eof> parser at end of file
2.	Per-file LLVM IR generation
3.	C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include\system_error:452:5: Generating code for declaration 'std::_System_error::_System_error'
 #0 0x00007ff7343a7665 HandleAbort C:\b\slave\sanitizer-windows\llvm-project\llvm\lib\Support\Windows\Signals.inc:408:0
 #1 0x00007fff135dd167 (C:\windows\SYSTEM32\ucrtbase.DLL+0x6d167)
 #2 0x00007fff135ddff1 (C:\windows\SYSTEM32\ucrtbase.DLL+0x6dff1)
 #3 0x00007fff135dfca1 (C:\windows\SYSTEM32\ucrtbase.DLL+0x6fca1)
 #4 0x00007fff135dffaf (C:\windows\SYSTEM32\ucrtbase.DLL+0x6ffaf)
 #5 0x00007ff73496f167 clang::CodeGen::CodeGenFunction::DeactivateCleanupBlock(class clang::CodeGen::EHScopeStack::stable_iterator, class llvm::Instruction *) C:\b\slave\sanitizer-windows\llvm-project\clang\lib\CodeGen\CGCleanup.cpp:1282:0
 #6 0x00007ff734734e67 clang::CodeGen::CodeGenFunction::EmitCall(class clang::CodeGen::CGFunctionInfo const &, class clang::CodeGen::CGCallee const &, class clang::CodeGen::ReturnValueSlot, class clang::CodeGen::CallArgList const &, class llvm::CallBase **, bool, class clang::SourceLocation) C:\b\slave\sanitizer-windows\llvm-project\clang\lib\CodeGen\CGCall.cpp:5143:0
 #7 0x00007ff734819276 clang::CodeGen::CodeGenFunction::EmitCall(class clang::QualType, class clang::CodeGen::CGCallee const &, class clang::CallExpr const *, class clang::CodeGen::ReturnValueSlot, class llvm::Value *) C:\b\slave\sanitizer-windows\llvm-project\clang\lib\CodeGen\CGExpr.cpp:5345:0
 #8 0x00007ff7348196c2 clang::CodeGen::CodeGenFunction::EmitCallExpr(class clang::CallExpr const *, class clang::CodeGen::ReturnValueSlot) C:\b\slave\sanitizer-windows\llvm-project\clang\lib\CodeGen\CGExpr.cpp:4889:0
 #9 0x00007ff7349ab1e6 llvm::function_ref<clang::CodeGen::RValue __cdecl(clang::CodeGen::ReturnValueSlot)>::callback_fn<<lambda_309ac722cb2fd76e387238e7a265d24

Also on local debian build I see:

AIL: Clang :: CodeGenCXX/exceptions.cpp (8970 of 85999)
******************** TEST 'Clang :: CodeGenCXX/exceptions.cpp' FAILED ********************
Script:
--
: 'RUN: at line 1';   /usr/local/google/home/vitalybuka/src/llvm.git/out/z/bin/clang -cc1 -internal-isystem /usr/local/google/home/vitalybuka/src/llvm.git/out/z/lib/clang/14.0.0/include -nostdsysteminc /usr/local/google/home/vitalybuka/src/llvm.git/llvm-project/clang/test/CodeGenCXX/exceptions.cpp -triple=x86_64-linux-gnu -emit-llvm -std=c++98 -o - -fcxx-exceptions -fexceptions | /usr/local/google/home/vitalybuka/src/llvm.git/out/z/bin/FileCheck -check-prefix=CHECK -check-prefix=CHECK98 /usr/local/google/home/vitalybuka/src/llvm.git/llvm-project/clang/test/CodeGenCXX/exceptions.cpp
: 'RUN: at line 2';   /usr/local/google/home/vitalybuka/src/llvm.git/out/z/bin/clang -cc1 -internal-isystem /usr/local/google/home/vitalybuka/src/llvm.git/out/z/lib/clang/14.0.0/include -nostdsysteminc /usr/local/google/home/vitalybuka/src/llvm.git/llvm-project/clang/test/CodeGenCXX/exceptions.cpp -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions | /usr/local/google/home/vitalybuka/src/llvm.git/out/z/bin/FileCheck -check-prefix=CHECK -check-prefix=CHECK11 /usr/local/google/home/vitalybuka/src/llvm.git/llvm-project/clang/test/CodeGenCXX/exceptions.cpp
--
Exit Code: 1

Command Output (stderr):
--
/usr/local/google/home/vitalybuka/src/llvm.git/llvm-project/clang/test/CodeGenCXX/exceptions.cpp:461:12: error: CHECK: expected string not found in input
 // CHECK: call void @_ZdaPv(i8* [[TEST9_NEW]])
           ^
<stdin>:1387:41: note: scanning from here
 %call = call noalias nonnull i8* @_Znam(i64 18) #10
                                        ^
<stdin>:1387:41: note: with "TEST9_NEW" equal to "%call"
 %call = call noalias nonnull i8* @_Znam(i64 18) #10
                                        ^
<stdin>:1397:2: note: possible intended match here
 call void @_ZN5test91AC1Ev(%"struct.test9::A"* nonnull align 1 dereferenceable(1) %arrayctor.cur)
 ^

Input file: <stdin>
Check file: /usr/local/google/home/vitalybuka/src/llvm.git/llvm-project/clang/test/CodeGenCXX/exceptions.cpp

-dump-input=help explains the following input dump.

Input was:
<<<<<<
             .
             .
             .
          1382: declare void @_ZN5test81AD1Ev(%"struct.test8::A"* nonnull align 1 dereferenceable(1)) unnamed_addr #1 
          1383:  
          1384: ; Function Attrs: noinline optnone 
          1385: define dso_local %"struct.test9::A"* @_ZN5test94testEv() #0 { 
          1386: entry: 
          1387:  %call = call noalias nonnull i8* @_Znam(i64 18) #10 
check:461'0                                             X~~~~~~~~~~~~ error: no match found
check:461'1                                                           with "TEST9_NEW" equal to "%call"
          1388:  %0 = bitcast i8* %call to i64* 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1389:  store i64 10, i64* %0, align 8 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1390:  %1 = getelementptr inbounds i8, i8* %call, i64 8 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1391:  %2 = bitcast i8* %1 to %"struct.test9::A"* 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1392:  %arrayctor.end = getelementptr inbounds %"struct.test9::A", %"struct.test9::A"* %2, i64 10 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1393:  br label %arrayctor.loop 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~
          1394:  
check:461'0     ~
          1395: arrayctor.loop: ; preds = %arrayctor.loop, %entry 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1396:  %arrayctor.cur = phi %"struct.test9::A"* [ %2, %entry ], [ %arrayctor.next, %arrayctor.loop ] 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1397:  call void @_ZN5test91AC1Ev(%"struct.test9::A"* nonnull align 1 dereferenceable(1) %arrayctor.cur) 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:461'2      ?                                                                                                  possible intended match
          1398:  %arrayctor.next = getelementptr inbounds %"struct.test9::A", %"struct.test9::A"* %arrayctor.cur, i64 1 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1399:  %arrayctor.done = icmp eq %"struct.test9::A"* %arrayctor.next, %arrayctor.end 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1400:  br i1 %arrayctor.done, label %arrayctor.cont, label %arrayctor.loop 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1401:  
check:461'0     ~
          1402: arrayctor.cont: ; preds = %arrayctor.loop 
check:461'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             .
             .
             .
>>>>>>

--

********************
thakis added a subscriber: thakis.Jan 14 2022, 3:55 PM

This breaks a bunch of tests on Mac: http://45.33.8.238/macm1/25623/step_7.txt

Please take a look and revert for now if it takes a while to fix.

haowei added a subscriber: haowei.EditedFeb 4 2022, 9:43 AM

Hi, we are seeing clang Windows build breakages after this change was relanded, error message:

Assertion failed: isa<X>(Val) && "cast<Ty>() argument of incompatible type!", file C:\b\s\w\ir\x\w\llvm-llvm-project\llvm\include\llvm/Support/Casting.h, line 262
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: C:\\b\\s\\w\\ir\\x\\w\\staging\\llvm_build\\.\\bin\\clang-cl.exe /nologo -TP -DNDEBUG -DUNICODE -D_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH -D_ALLOW_MSC_VER_MISMATCH -D_CRTBLD -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -D_LIBCPP_BUILDING_LIBRARY -D_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -IC:\\b\\s\\w\\ir\\x\\w\\llvm-llvm-project\\libcxx\\src /DWIN32 /D_WINDOWS /Zc:inline /Zc:__cplusplus /Zc:strictStrings /Oi /Zc:rvalueCast /bigobj /W4 -wd4141 -wd4146 -wd4244 -wd4267 -wd4291 -wd4351 -wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4100 -wd4127 -wd4512 -wd4505 -wd4610 -wd4510 -wd4702 -wd4245 -wd4706 -wd4310 -wd4701 -wd4703 -wd4389 -wd4611 -wd4805 -wd4204 -wd4577 -wd4091 -wd4592 -wd4319 -wd4709 -wd4324 -w14062 -we4238 /Gw -no-canonical-prefixes --target=x86_64-pc-windows-msvc /MD /Zi /O2 /Ob1 --target=x86_64-pc-windows-msvc -UNDEBUG -W4 -Wextra -W -Wwrite-strings -Wno-unused-parameter -Wno-long-long -Werror=return-type -Wextra-semi -Wundef -Wformat-nonliteral -Wno-user-defined-literals -Wno-covered-switch-default -Wno-suggest-override -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-compat -Wno-undef -Wno-reserved-id-macro -Wno-gnu-include-next -Wno-gcc-compat -Wno-zero-as-null-pointer-constant -Wno-deprecated-dynamic-exception-spec -Wno-sign-conversion -Wno-old-style-cast -Wno-deprecated -Wno-shift-sign-overflow -Wno-double-promotion -Wno-error -EHsc /IC:/b/s/w/ir/x/w/staging/llvm_build/include/c++/v1 /IC:/b/s/w/ir/x/w/staging/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -std:c++latest /showIncludes /Folibcxx\\src\\CMakeFiles\\cxx_static.dir\\future.cpp.obj /Fdlibcxx\\src\\CMakeFiles\\cxx_static.dir\\cxx_static.pdb -c C:\\b\\s\\w\\ir\\x\\w\\llvm-llvm-project\\libcxx\\src\\future.cpp
1.	<eof> parser at end of file
2.	C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\src\future.cpp:16:1 <Spelling=C:/b/s/w/ir/x/w/staging/llvm_build/include/c++/v1\__config:824:47>: LLVM IR generation of declaration 'std'
3.	C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\src\future.cpp:204:16: Generating code for declaration 'std::promise<void>::~promise'
4.	C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\src\future.cpp:205:1: LLVM IR generation of compound statement ('{}')
5.	C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\src\future.cpp:207:5: LLVM IR generation of compound statement ('{}')

We confirmed it by local bisecting. Full build log: https://logs.chromium.org/logs/fuchsia/buildbucket/cr-buildbucket/8823297314867545825/+/u/clang/build/stdout
Could you take a look? If it takes time to fix, could you revert the change please. Thanks.

Found the problem, tweaking a test-case; will commit shortly.