Skip to content

[clang] ICE on NTTP with a constrained placeholder type in static/non-static member function templates of class templates #146095

Open
@Shuangcheng-Ni

Description

@Shuangcheng-Ni

The code below causes ICE. The crash happens whether eq is declared static or non-static.

#include <concepts>

template <int>
struct S {
    template <class T, std::convertible_to<T> auto V>
    constexpr static bool eq(const T &arg) {
        return T{V} == arg;
    }
};

int main() { static_assert(S<0>::eq<long, '2'>(0x32)); }

Stack dump:

0.	Program arguments: /opt/compiler-explorer/clang-trunk-20250627/bin/clang-21 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -dumpdir /app/output.s- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name example.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -fno-verbose-asm -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/app -fcoverage-compilation-dir=/app -resource-dir /opt/compiler-explorer/clang-trunk-20250627/lib/clang/21 -internal-isystem /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/16.0.0/../../../../include/c++/16.0.0 -internal-isystem /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/16.0.0/../../../../include/c++/16.0.0/x86_64-linux-gnu -internal-isystem /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/16.0.0/../../../../include/c++/16.0.0/backward -internal-isystem /opt/compiler-explorer/clang-trunk-20250627/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/16.0.0/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++26 -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/example-b2ab85.o -x c++ <source>
1.	<source>:11:52: current parser token ')'
2.	<source>:11:12: parsing function body 'main'
3.	<source>:11:12: in compound statement ('{}')
 #0 0x0000000003c43078 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x3c43078)
 #1 0x0000000003c40c34 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x00007ee3d3042520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000000000708e049 clang::ASTContext::getSubstTemplateTypeParmType(clang::QualType, clang::Decl*, unsigned int, clang::UnsignedOrNone, bool) const (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x708e049)
 #4 0x0000000006d4104c (anonymous namespace)::TemplateInstantiator::BuildSubstTemplateTypeParmType(clang::TypeLocBuilder&, bool, bool, clang::Decl*, unsigned int, clang::UnsignedOrNone, clang::TemplateArgument, clang::SourceLocation) SemaTemplateInstantiate.cpp:0:0
 #5 0x0000000006d6f931 (anonymous namespace)::TemplateInstantiator::TransformTemplateTypeParmType(clang::TypeLocBuilder&, clang::TemplateTypeParmTypeLoc, bool) SemaTemplateInstantiate.cpp:0:0
 #6 0x0000000006d62057 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformType(clang::TypeLocBuilder&, clang::TypeLoc) SemaTemplateInstantiate.cpp:0:0
 #7 0x0000000006d63e97 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformType(clang::TypeSourceInfo*) SemaTemplateInstantiate.cpp:0:0
 #8 0x0000000006d693d1 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformTemplateArgument(clang::TemplateArgumentLoc const&, clang::TemplateArgumentLoc&, bool) SemaTemplateInstantiate.cpp:0:0
 #9 0x0000000006d6a16d bool clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformTemplateArguments<clang::TemplateArgumentLoc const*>(clang::TemplateArgumentLoc const*, clang::TemplateArgumentLoc const*, clang::TemplateArgumentListInfo&, bool) (.constprop.0) SemaTemplateInstantiate.cpp:0:0
#10 0x0000000006d6b78e clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformConceptSpecializationExpr(clang::ConceptSpecializationExpr*) SemaTemplateInstantiate.cpp:0:0
#11 0x0000000006d59789 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#12 0x0000000006d5fb25 clang::Sema::SubstConstraintExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6d5fb25)
#13 0x0000000006512e55 calculateConstraintSatisfaction(clang::Sema&, clang::Expr const*, clang::NamedDecl const*, clang::SourceLocation, clang::MultiLevelTemplateArgumentList const&, clang::ConstraintSatisfaction&) SemaConcept.cpp:0:0
#14 0x0000000006514eac CheckConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::AssociatedConstraint>, llvm::SmallVectorImpl<clang::Expr*>&, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) SemaConcept.cpp:0:0
#15 0x0000000006518157 clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::AssociatedConstraint>, llvm::SmallVectorImpl<clang::Expr*>&, clang::MultiLevelTemplateArgumentList const&, clang::SourceRange, clang::ConstraintSatisfaction&) (.constprop.0) SemaConcept.cpp:0:0
#16 0x000000000651922a clang::Sema::CheckFunctionTemplateConstraints(clang::SourceLocation, clang::FunctionDecl*, llvm::ArrayRef<clang::TemplateArgument>, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x651922a)
#17 0x0000000006cf95f0 clang::Sema::FinishTemplateArgumentDeduction(clang::FunctionTemplateDecl*, llvm::SmallVectorImpl<clang::DeducedTemplateArgument>&, unsigned int, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, llvm::SmallVectorImpl<clang::Sema::OriginalCallArg> const*, bool, bool, llvm::function_ref<bool (bool)>) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6cf95f0)
#18 0x0000000006cfa657 void llvm::function_ref<void ()>::callback_fn<clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool, bool, bool, clang::QualType, clang::Expr::Classification, bool, llvm::function_ref<bool (llvm::ArrayRef<clang::QualType>, bool)>)::'lambda1'()>(long) SemaTemplateDeduction.cpp:0:0
#19 0x00000000079d4fb1 clang::StackExhaustionHandler::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x79d4fb1)
#20 0x0000000006cf0c8b clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool, bool, bool, clang::QualType, clang::Expr::Classification, bool, llvm::function_ref<bool (llvm::ArrayRef<clang::QualType>, bool)>) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6cf0c8b)
#21 0x0000000006aee0bc AddTemplateOverloadCandidateImmediately(clang::Sema&, clang::OverloadCandidateSet&, clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, bool, bool, bool, clang::CallExpr::ADLCallKind, clang::OverloadCandidateParamOrder, bool) SemaOverload.cpp:0:0
#22 0x0000000006aef931 clang::Sema::AddTemplateOverloadCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, bool, bool, bool, clang::CallExpr::ADLCallKind, clang::OverloadCandidateParamOrder, bool) (.constprop.1) SemaOverload.cpp:0:0
#23 0x0000000006af0ad4 clang::Sema::AddOverloadedCallCandidates(clang::UnresolvedLookupExpr*, llvm::ArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, bool) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6af0ad4)
#24 0x0000000006af0d7e clang::Sema::buildOverloadedCallSet(clang::Scope*, clang::Expr*, clang::UnresolvedLookupExpr*, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::OverloadCandidateSet*, clang::ActionResult<clang::Expr*, true>*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6af0d7e)
#25 0x0000000006b085d3 clang::Sema::BuildOverloadedCallExpr(clang::Scope*, clang::Expr*, clang::UnresolvedLookupExpr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6b085d3)
#26 0x0000000006787cd2 clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6787cd2)
#27 0x000000000678c34c clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x678c34c)
#28 0x000000000628a86e clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult<clang::Expr*, true>) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x628a86e)
#29 0x000000000628292a clang::Parser::ParseCastExpression(clang::CastParseKind, bool, bool&, clang::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x628292a)
#30 0x000000000628469d clang::Parser::ParseCastExpression(clang::CastParseKind, bool, bool&, clang::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x628469d)
#31 0x0000000006290a89 clang::Parser::ParseConstantExpressionInExprEvalContext(clang::TypeCastState) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6290a89)
#32 0x000000000626722a clang::Parser::ParseStaticAssertDeclaration(clang::SourceLocation&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x626722a)
#33 0x0000000006254e3d clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6254e3d)
#34 0x0000000006321c96 clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 24u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&, clang::ParsedAttributes&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6321c96)
#35 0x00000000063225ce clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 24u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x63225ce)
#36 0x000000000632a35d clang::Parser::ParseCompoundStatementBody(bool) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x632a35d)
#37 0x000000000632ad9a clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x632ad9a)
#38 0x0000000006205a16 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6205a16)
#39 0x0000000006251f6f clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6251f6f)
#40 0x00000000061fddb7 clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec&, clang::AccessSpecifier) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x61fddb7)
#41 0x00000000061febce clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*, clang::AccessSpecifier) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x61febce)
#42 0x000000000620873f clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x620873f)
#43 0x0000000006209fa8 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x6209fa8)
#44 0x00000000061f839a clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x61f839a)
#45 0x0000000004590f6d clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x4590f6d)
#46 0x00000000048a5e0a clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x48a5e0a)
#47 0x000000000482155b clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x482155b)
#48 0x000000000499a8e3 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0x499a8e3)
#49 0x0000000000d9fa85 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0xd9fa85)
#50 0x0000000000d9796d ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#51 0x0000000000d9a811 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0xd9a811)
#52 0x0000000000c4e4f4 main (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0xc4e4f4)
#53 0x00007ee3d3029d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#54 0x00007ee3d3029e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#55 0x0000000000d97405 _start (/opt/compiler-explorer/clang-trunk-20250627/bin/clang-21+0xd97405)

The code compiles correctly in the following cases:

  • A trailing requires clause is used instead of a constrained placeholder type.
    #include <concepts>
    
    template <int>
    struct S {
        template <class T, auto V>
            requires std::convertible_to<decltype(V), T>
        constexpr static bool eq(const T &arg) {
            return T{V} == arg;
        }
    };
    
    int main() { static_assert(S<0>::eq<long, '2'>(0x32)); }
  • S is a class instead of a class template.
    #include <concepts>
    
    struct S {
        template <class T, std::convertible_to<T> auto V>
        constexpr static bool eq(const T &arg) {
            return T{V} == arg;
        }
    };
    
    int main() { static_assert(S::eq<long, '2'>(0x32)); }

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"confirmedVerified by a second partycrashPrefer [crash-on-valid] or [crash-on-invalid]regression:16Regression in 16 release

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions