Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang++] Crash when parsing out-of-class definition of member function with trailing requires clause #112222

Closed
PiliLatiesa opened this issue Oct 14, 2024 · 8 comments · Fixed by #112381
Assignees
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party crash-on-valid regression

Comments

@PiliLatiesa
Copy link

I'm observing crashes when compiling the following snipped with clang trunk. Clang 19 doesn't crash.

#include <cstdint>

template<typename T>
class TExprBase;

template<std::size_t dim, std::size_t rank, template<std::size_t, std::size_t> typename T>
class TExprBase<T<dim, rank>>
{
public:
  void Curl() const requires (dim == 3u && rank == 1u);
};

template<std::size_t dim, std::size_t rank, template<std::size_t, std::size_t> typename T>
void TExprBase<T<dim, rank>>::Curl() const requires (dim == 3u && rank == 1u)
{
}
@github-actions github-actions bot added the clang Clang issues not falling into any other category label Oct 14, 2024
@shafik
Copy link
Collaborator

shafik commented Oct 14, 2024

Confirmed: https://godbolt.org/z/jevEajn63

Unreachable:

not a non-type template argument
UNREACHABLE executed at /root/llvm-project/clang/lib/Sema/SemaTemplate.cpp:7669!

Backtrace:

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: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++20 <source>
1.	<source>:15:1: current parser token '{'
 #0 0x0000000003ba9d48 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3ba9d48)
 #1 0x0000000003ba7a0c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3ba7a0c)
 #2 0x0000000003af4c68 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x000078328da42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000078328da969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #5 0x000078328da42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #6 0x000078328da287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #7 0x0000000003b0053a (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3b0053a)
 #8 0x00000000071952a7 clang::Sema::BuildExpressionFromNonTypeTemplateArgument(clang::TemplateArgument const&, clang::SourceLocation) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x71952a7)
 #9 0x00000000073cace3 (anonymous namespace)::TemplateInstantiator::transformNonTypeTemplateParmRef(clang::Decl*, clang::NonTypeTemplateParmDecl const*, clang::SourceLocation, clang::TemplateArgument, std::optional<unsigned int>) SemaTemplateInstantiate.cpp:0:0
#10 0x00000000073dcc6d (anonymous namespace)::TemplateInstantiator::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#11 0x00000000073b1257 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#12 0x00000000073c0540 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformBinaryOperator(clang::BinaryOperator*) SemaTemplateInstantiate.cpp:0:0
#13 0x00000000073b0ede clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#14 0x00000000073c0540 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformBinaryOperator(clang::BinaryOperator*) SemaTemplateInstantiate.cpp:0:0
#15 0x00000000073b0ede clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#16 0x00000000073bba38 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformParenExpr(clang::ParenExpr*) SemaTemplateInstantiate.cpp:0:0
#17 0x00000000073b14d6 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#18 0x00000000073c141f clang::Sema::SubstConstraintExprWithoutSatisfaction(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x73c141f)
#19 0x0000000006924d6b SubstituteConstraintExpressionWithoutSatisfaction(clang::Sema&, clang::Sema::TemplateCompareNewDeclInfo const&, clang::Expr const*) SemaConcept.cpp:0:0
#20 0x000000000693078a clang::Sema::AreConstraintExpressionsEqual(clang::NamedDecl const*, clang::Expr const*, clang::Sema::TemplateCompareNewDeclInfo const&, clang::Expr const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x693078a)
#21 0x00000000070af4a1 IsOverloadOrOverrideImpl(clang::Sema&, clang::FunctionDecl*, clang::FunctionDecl*, bool, bool, bool) SemaOverload.cpp:0:0
#22 0x00000000070af901 clang::Sema::CheckOverload(clang::Scope*, clang::FunctionDecl*, clang::LookupResult const&, clang::NamedDecl*&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x70af901)
#23 0x0000000006a08570 clang::Sema::CheckFunctionDeclaration(clang::Scope*, clang::FunctionDecl*, clang::LookupResult&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6a08570)
#24 0x0000000006a0eb46 clang::Sema::ActOnFunctionDeclarator(clang::Scope*, clang::Declarator&, clang::DeclContext*, clang::TypeSourceInfo*, clang::LookupResult&, llvm::MutableArrayRef<clang::TemplateParameterList*>, bool&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6a0eb46)
#25 0x0000000006a13da0 clang::Sema::HandleDeclarator(clang::Scope*, clang::Declarator&, llvm::MutableArrayRef<clang::TemplateParameterList*>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6a13da0)
#26 0x0000000006a14750 clang::Sema::ActOnStartOfFunctionDef(clang::Scope*, clang::Declarator&, llvm::MutableArrayRef<clang::TemplateParameterList*>, clang::SkipBodyInfo*, clang::Sema::FnBodyKind) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6a14750)
#27 0x0000000006650140 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6650140)
#28 0x00000000066856ed clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x66856ed)
#29 0x000000000674eec6 clang::Parser::ParseDeclarationAfterTemplate(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo&, clang::ParsingDeclRAIIObject&, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x674eec6)
#30 0x000000000675c78c clang::Parser::ParseTemplateDeclarationOrSpecialization(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) (.part.0) ParseTemplate.cpp:0:0
#31 0x000000000675caaa clang::Parser::ParseDeclarationStartingWithTemplate(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x675caaa)
#32 0x000000000668dc93 clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x668dc93)
#33 0x000000000664c6d7 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x664c6d7)
#34 0x000000000664d57d clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x664d57d)
#35 0x000000000663fa9a clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x663fa9a)
#36 0x0000000004502248 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4502248)
#37 0x00000000047bbb49 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x47bbb49)
#38 0x000000000473a6ee clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x473a6ee)
#39 0x00000000048a16be clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x48a16be)
#40 0x0000000000cdb8ef cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xcdb8ef)
#41 0x0000000000cd35fa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#42 0x0000000004545f19 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#43 0x0000000003af5114 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3af5114)
#44 0x000000000454650f clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#45 0x000000000450be4d clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x450be4d)
#46 0x000000000450cf3d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x450cf3d)
#47 0x0000000004514865 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4514865)
#48 0x0000000000cd87bf clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xcd87bf)
#49 0x0000000000ba7d14 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xba7d14)
#50 0x000078328da29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#51 0x000078328da29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#52 0x0000000000cd30ae _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xcd30ae)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134

@shafik
Copy link
Collaborator

shafik commented Oct 14, 2024

Unreachable added in 5518a9d

CC @bolshakov-a

@shafik shafik added clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party crash-on-valid and removed clang Clang issues not falling into any other category labels Oct 14, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 14, 2024

@llvm/issue-subscribers-clang-frontend

Author: None (PiliLatiesa)

I'm observing crashes when compiling the following snipped with clang trunk. Clang 19 doesn't crash.
#include &lt;cstdint&gt;

template&lt;typename T&gt;
class TExprBase;

template&lt;std::size_t dim, std::size_t rank, template&lt;std::size_t, std::size_t&gt; typename T&gt;
class TExprBase&lt;T&lt;dim, rank&gt;&gt;
{
public:
  void Curl() const requires (dim == 3u &amp;&amp; rank == 1u);
};

template&lt;std::size_t dim, std::size_t rank, template&lt;std::size_t, std::size_t&gt; typename T&gt;
void TExprBase&lt;T&lt;dim, rank&gt;&gt;::Curl() const requires (dim == 3u &amp;&amp; rank == 1u)
{
}

@bolshakov-a
Copy link
Contributor

It's not me, it's after #111852.

@shafik
Copy link
Collaborator

shafik commented Oct 14, 2024

It's not me, it's after #111852.

Apologies.

CC @sdkrystian

@PiliLatiesa
Copy link
Author

Slightly reduced:

template<typename T>
class TBase;

template<int dim, template<int> typename T>
class TBase<T<dim>>
{
  void Curl() const requires (dim == 3u);
};

template<int dim, template<int> typename T>
void TBase<T<dim>>::Curl() const requires (dim == 3u) {} 

@bolshakov-a
Copy link
Contributor

Even this works breaks:

template<int T>
struct Tpl{};

template<typename T>
class TExprBase;

template<int dim>
class TExprBase<Tpl<dim>>
{
public:
  void Curl() const requires (dim == 3u);
};

template<int dim>
void TExprBase<Tpl<dim>>::Curl() const requires (dim == 3u)
{
}

TemplateArgument arg argument of TemplateInstantiator::transformNonTypeTemplateParmRef appears to be Tpl<dim> type template argument of the primary template instead of dim NTTP of the specialization, and the assertion fires correctly.

@sdkrystian
Copy link
Member

Further reduced to:

template<typename T, bool B>
struct A;

template<bool B>
struct A<int, B>
{
    void f() requires B;
};

template<bool B>
void A<int, B>::f() requires B { } // crash here

The problem is that TemplateInstantiationArgumentCollecter::VisitClassTemplatePartialSpecializationDecl uses the template argument list of the partial specialization, when it should use the template argument list of its template-head (as defined in [temp.arg.general] p2).

I'll have a fix ready shortly.

@sdkrystian sdkrystian self-assigned this Oct 15, 2024
sdkrystian added a commit that referenced this issue Oct 16, 2024
… specializations when collecting multi-level template argument lists (#112381)

After #111852 refactored multi-level template argument list collection,
the following results in a crash:
```
template<typename T, bool B>
struct A;

template<bool B>
struct A<int, B>
{
    void f() requires B;
};

template<bool B>
void A<int, B>::f() requires B { } // crash here
```

This happens because when collecting template arguments for constraint
normalization from a partial specialization, we incorrectly use the
template argument list of the partial specialization. We should be using
the template argument list of the _template-head_ (as defined in
[temp.arg.general] p2). Fixes #112222.
bricknerb pushed a commit to bricknerb/llvm-project that referenced this issue Oct 17, 2024
… specializations when collecting multi-level template argument lists (llvm#112381)

After llvm#111852 refactored multi-level template argument list collection,
the following results in a crash:
```
template<typename T, bool B>
struct A;

template<bool B>
struct A<int, B>
{
    void f() requires B;
};

template<bool B>
void A<int, B>::f() requires B { } // crash here
```

This happens because when collecting template arguments for constraint
normalization from a partial specialization, we incorrectly use the
template argument list of the partial specialization. We should be using
the template argument list of the _template-head_ (as defined in
[temp.arg.general] p2). Fixes llvm#112222.
EricWF pushed a commit to efcs/llvm-project that referenced this issue Oct 22, 2024
… specializations when collecting multi-level template argument lists (llvm#112381)

After llvm#111852 refactored multi-level template argument list collection,
the following results in a crash:
```
template<typename T, bool B>
struct A;

template<bool B>
struct A<int, B>
{
    void f() requires B;
};

template<bool B>
void A<int, B>::f() requires B { } // crash here
```

This happens because when collecting template arguments for constraint
normalization from a partial specialization, we incorrectly use the
template argument list of the partial specialization. We should be using
the template argument list of the _template-head_ (as defined in
[temp.arg.general] p2). Fixes llvm#112222.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party crash-on-valid regression
Projects
None yet
5 participants