llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.99k stars 11.95k forks source link

clang 16 crashes compiling template code that is fine with Clang15, GCC12, and GCC13 #63594

Closed RalphSteinhagen closed 10 months ago

RalphSteinhagen commented 1 year ago

I encountered an internal compiler crash in Clang 16 when compiling a C++20 project that previously compiled without issues using Clang 15, GCC 12, and GCC 13. It appears to be related to handling of template code with constexpr if and concepts.

Environment

Stack Trace

====================[ Build | qa_settings | Debug-System - Clang ]==============
/usr/bin/cmake --build /home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang --target qa_settings -j 22
[0/2] Re-checking globbed directories...
[1/2] Building CXX object test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o
FAILED: test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o 
/usr/bin/clang++  -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/test -I/home/steinhagen/git/graph-prototype/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/pmt-src/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/fmt-src/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/ut-src/include -isystem /home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/refl-cpp-src/include -g -std=gnu++20 -fPIE -fvisibility=hidden -fvisibility-inlines-hidden -fcolor-diagnostics -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual -Wpedantic -Wconversion -Wsign-conversion -Wnull-dereference -Wdouble-promotion -Wformat=2 -Wno-unknown-pragmas -Wimplicit-fallthrough -MD -MT test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o -MF test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o.d -o test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o -c /home/steinhagen/git/graph-prototype/test/qa_settings.cpp
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: /usr/bin/clang++ -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/test -I/home/steinhagen/git/graph-prototype/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/pmt-src/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/fmt-src/include -I/home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/ut-src/include -isystem /home/steinhagen/git/graph-prototype/cmake-build-debug-system---clang/_deps/refl-cpp-src/include -g -std=gnu++20 -fPIE -fvisibility=hidden -fvisibility-inlines-hidden -fcolor-diagnostics -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual -Wpedantic -Wconversion -Wsign-conversion -Wnull-dereference -Wdouble-promotion -Wformat=2 -Wno-unknown-pragmas -Wimplicit-fallthrough -MD -MT test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o -MF test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o.d -o test/CMakeFiles/qa_settings.dir/qa_settings.cpp.o -c /home/steinhagen/git/graph-prototype/test/qa_settings.cpp
1.  <eof> parser at end of file
2.  /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/bits/unique_ptr.h:1069:5: instantiating function definition 'std::make_unique<fair::graph::node_wrapper<fair::graph::setting_test::Source<float>>>'
3.  /home/steinhagen/git/graph-prototype/include/graph.hpp:504:5: instantiating function definition 'fair::graph::node_wrapper<fair::graph::setting_test::Source<float>>::node_wrapper'
4.  /home/steinhagen/git/graph-prototype/include/node.hpp:270:5: instantiating function definition 'fair::graph::node<fair::graph::setting_test::Source<float>>::node'
5.  /home/steinhagen/git/graph-prototype/include/node.hpp:272:5: instantiating function definition 'fair::graph::node<fair::graph::setting_test::Source<float>>::node'
6.  /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/bits/unique_ptr.h:1069:5: instantiating function definition 'std::make_unique<fair::graph::basic_settings<fair::graph::setting_test::Source<float>>, fair::graph::setting_test::Source<float> &>'
7.  /home/steinhagen/git/graph-prototype/include/settings.hpp:182:24: instantiating function definition 'fair::graph::basic_settings<fair::graph::setting_test::Source<float>>::basic_settings'
 #0 0x00007f044ee3d0e9 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/lib64/libLLVM.so.16+0x383d0e9)
 #1 0x00007f044ee3acc0 llvm::sys::RunSignalHandlers() (/lib64/libLLVM.so.16+0x383acc0)
 #2 0x00007f044ed566f1 (/lib64/libLLVM.so.16+0x37566f1)
 #3 0x00007f044b0412f0 __restore_rt (/lib64/libc.so.6+0x3e2f0)
 #4 0x00007f0454bdb1b0 clang::Sema::BuildExprRequirement(clang::Expr*, bool, clang::SourceLocation, clang::concepts::ExprRequirement::ReturnTypeRequirement) (/lib64/libclang-cpp.so.16+0x21db1b0)
 #5 0x00007f0454f8bc9c (/lib64/libclang-cpp.so.16+0x258bc9c)
 #6 0x00007f0454f81095 (/lib64/libclang-cpp.so.16+0x2581095)
 #7 0x00007f0454f9a7e5 (/lib64/libclang-cpp.so.16+0x259a7e5)
 #8 0x00007f0454f972da (/lib64/libclang-cpp.so.16+0x25972da)
 #9 0x00007f0454f8dd06 (/lib64/libclang-cpp.so.16+0x258dd06)
#10 0x00007f0454f8858b (/lib64/libclang-cpp.so.16+0x258858b)
#11 0x00007f0454f7d70a (/lib64/libclang-cpp.so.16+0x257d70a)
#12 0x00007f0454fb850c clang::Sema::InstantiateVariableInitializer(clang::VarDecl*, clang::VarDecl*, clang::MultiLevelTemplateArgumentList const&) (/lib64/libclang-cpp.so.16+0x25b850c)
#13 0x00007f0454fa985c clang::Sema::BuildVariableInstantiation(clang::VarDecl*, clang::VarDecl*, clang::MultiLevelTemplateArgumentList const&, llvm::SmallVector<clang::Sema::LateInstantiatedAttribute, 16u>*, clang::DeclContext*, clang::LocalInstantiationScope*, bool, clang::VarTemplateSpecializationDecl*) (/lib64/libclang-cpp.so.16+0x25a985c)
#14 0x00007f0454fa89f0 clang::TemplateDeclInstantiator::VisitVarDecl(clang::VarDecl*, bool, llvm::ArrayRef<clang::BindingDecl*>*) (/lib64/libclang-cpp.so.16+0x25a89f0)
#15 0x00007f0454fb9f61 clang::Sema::SubstDecl(clang::Decl*, clang::DeclContext*, clang::MultiLevelTemplateArgumentList const&) (/lib64/libclang-cpp.so.16+0x25b9f61)
clang-16.0: error: clang frontend command failed with exit code 139 (use -v to see invocation)
clang version 16.0.6
Target: x86_64-suse-linux
Thread model: posix
InstalledDir: /usr/bin
clang-16.0: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-16.0: note: diagnostic msg: /tmp/qa_settings-2d8784.cpp
clang-16.0: note: diagnostic msg: /tmp/qa_settings-2d8784.sh
clang-16.0: note: diagnostic msg: 

********************
ninja: build stopped: subcommand failed.

Full code is here: clang16_regression.zip

Additional Information

The crash seems to occur in template code with constexpr if and concepts. Specifically, the code between lines 288919-288936 in the attached source code. Disabling this section makes the code compile with Clang 16.

Here is the specific section of the code (constructor) where the crash occurs:

// ...
auto iterate_over_member = [&](auto member) {
    using RawType = std::remove_cvref_t<decltype(member(*_node))>;
    // disable clang format because v16 cannot handle in-line requires clauses with return types nicely yet
    // clang-format off
    if constexpr (requires(Node t) { { unwrap_if_wrapped_t<decltype(t.meta_information)> {} } -> std::same_as<property_map>; }) {
        if constexpr (requires(Node t) { { t.description } -> std::same_as<const std::string_view &>; }) {
            _node->meta_information.value["description"] = std::string(_node->description);
        }

        if constexpr (AnnotatedType<RawType>) {
            _node->meta_information.value[fmt::format("{}::description", get_display_name(member))] = std::string(RawType::description());
            _node->meta_information.value[fmt::format("{}::documentation", get_display_name(member))] = std::string(RawType::documentation());
            _node->meta_information.value[fmt::format("{}::unit", get_display_name(member))] = std::string(RawType::unit());
            _node->meta_information.value[fmt::format("{}::visible", get_display_name(member))] = RawType::visible();
        }
    }
    // clang-format on
};
// [..]

Any help or workaround would be highly appreciated. Thank you for your time and effort in improving Clang! :+1:

llvmbot commented 1 year ago

@llvm/issue-subscribers-clang-frontend

RalphSteinhagen commented 1 year ago

@shafik I tried to reduce the problem to a true MVP but those did not reproduce the crash. Maybe this is linked to the complexity, possibly unbound internal stack size, or similar that is just not reported correctly on the crash.

However, I reduced the problem to the location that needs to be commented out (last commit) that triggered this crash.

Hope this helps. A fix and/or any workaround would be highly appreciated. Thanks in advance.

RalphSteinhagen commented 1 year ago

@ivan-cukic found a viable workaround for the requires {...} clause evaluation inside the constexpr-if expression. This works out fine for our purposes. Kudos to Ivan. :+1:

diff --git a/include/settings.hpp b/include/settings.hpp
index 3c1e7a6..61abbca 100644
--- a/include/settings.hpp
+++ b/include/settings.hpp
@@ -207,12 +207,14 @@ public:
                     fair::graph::tag::DEFAULT_TAGS);

             // handle meta-information for UI and other non-processing-related purposes
-            auto iterate_over_member = [&](auto member) {
-                using RawType = std::remove_cvref_t<decltype(member(*_node))>;
+            auto iterate_over_member = [&]<typename Member>(Member &&member) {
+                using RawType = typename Member::value_type;//  std::remove_cvref_t<decltype(member(*_node))>;
                 // disable clang format because v16 cannot handle in-line requires clauses with return types nicely yet
                 // clang-format off
-                if constexpr (requires(Node t) { { unwrap_if_wrapped_t<decltype(t.meta_information)> {} } -> std::same_as<property_map>; }) {
-                    if constexpr (requires(Node t) { { t.description } -> std::same_as<const std::string_view &>; }) {
+                if constexpr (requires(Node t) { t.meta_information; }) {
+                    static_assert(std::is_same_v<unwrap_if_wrapped_t<decltype(_node->meta_information)>, property_map>);
+                    if constexpr (requires(Node t) { t.description; }) {
+                        static_assert(std::is_same_v<std::remove_cvref_t<unwrap_if_wrapped_t<decltype(_node->description)>>, std::string_view>);
                         _node->meta_information.value["description"] = std::string(_node->description);
                     }

Please feel free to close this issue or keep it open if you want to investigate why clang16 and not clang15 crashes further.

LYP951018 commented 10 months ago

It seems that this issue has also been fixed by https://github.com/llvm/llvm-project/pull/76967, I can compile this code locally using clang trunk.