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

Concepts met ICE with assertions builds with member function call that lacks parentheses #52909

Closed
ChuanqiXu9 opened this issue Dec 29, 2021 · 7 comments
Assignees
Labels
c++20 clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts

Comments

@ChuanqiXu9
Copy link
Member

See https://godbolt.org/z/Ke5Mfoa8h. This is similar with #52905 but it should be a different bug.

@Quuxplusone
Copy link
Contributor

template<class T> constexpr bool B = true;
template<class T> concept True = B<T>;

template <class T>
concept Beginable = requires(T t) {
    { t.begin } -> True;
};

struct A { int begin(); };
static_assert(Beginable<A>);

Clang with assertions enabled says:

mangling a placeholder type
UNREACHABLE executed at /root/llvm-project/clang/lib/AST/ItaniumMangle.cpp:3017!
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++ -g -o /app/output.s -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -c -std=c++20 <source>
1.	<source>:11:27: current parser token ')'
2.	<source>:2:34: Mangling declaration 'B'
 #0 0x0000559a2784e90f PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #1 0x0000559a2784c710 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a4c710)
 #2 0x0000559a27783bd8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007fa508c8f3c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
 #4 0x00007fa50875e18b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4618b)
 #5 0x00007fa50873d859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x25859)
 #6 0x0000559a2778cd5a (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x398cd5a)
 #7 0x0000559a2a4c066d (anonymous namespace)::CXXNameMangler::mangleType(clang::QualType) ItaniumMangle.cpp:0:0
 #8 0x0000559a2a4d1710 (anonymous namespace)::CXXNameMangler::mangleTemplateArg(clang::TemplateArgument, bool) ItaniumMangle.cpp:0:0
 #9 0x0000559a2a4d225c (anonymous namespace)::CXXNameMangler::mangleTemplateArgs(clang::TemplateName, clang::TemplateArgumentList const&) ItaniumMangle.cpp:0:0
#10 0x0000559a2a4cd7e7 (anonymous namespace)::CXXNameMangler::mangleNameWithAbiTags(clang::GlobalDecl, llvm::SmallVector<llvm::StringRef, 4u> const*) ItaniumMangle.cpp:0:0
#11 0x0000559a2a4cd95e (anonymous namespace)::CXXNameMangler::mangleName(clang::GlobalDecl) ItaniumMangle.cpp:0:0
#12 0x0000559a2a4ce21d (anonymous namespace)::CXXNameMangler::mangle(clang::GlobalDecl) ItaniumMangle.cpp:0:0
#13 0x0000559a2a4d0a3e (anonymous namespace)::ItaniumMangleContextImpl::mangleCXXName(clang::GlobalDecl, llvm::raw_ostream&) ItaniumMangle.cpp:0:0
#14 0x0000559a2a4ed78c clang::MangleContext::mangleName(clang::GlobalDecl, llvm::raw_ostream&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x66ed78c)
#15 0x0000559a27c6a52b getMangledNameImpl(clang::CodeGen::CodeGenModule&, clang::GlobalDecl, clang::NamedDecl const*, bool) CodeGenModule.cpp:0:0
#16 0x0000559a27c7de71 clang::CodeGen::CodeGenModule::getMangledName(clang::GlobalDecl) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3e7de71)
#17 0x0000559a27ca47f6 clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3ea47f6)
#18 0x0000559a27cabda4 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) (.part.6742) CodeGenModule.cpp:0:0
#19 0x0000559a29fcb7b8 clang::Sema::InstantiateVariableDefinition(clang::SourceLocation, clang::VarDecl*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x61cb7b8)
#20 0x0000559a2985609f clang::Sema::runWithSufficientStackSpace(clang::SourceLocation, llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5a5609f)
#21 0x0000559a29b04591 DoMarkVarDeclReferenced(clang::Sema&, clang::SourceLocation, clang::VarDecl*, clang::Expr*, llvm::DenseMap<clang::VarDecl const*, int, llvm::DenseMapInfo<clang::VarDecl const*, void>, llvm::detail::DenseMapPair<clang::VarDecl const*, int> >&) SemaExpr.cpp:0:0
#22 0x0000559a29b04a9e clang::Sema::MarkDeclRefReferenced(clang::DeclRefExpr*, clang::Expr const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d04a9e)
#23 0x0000559a29b05ff2 clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&, clang::NestedNameSpecifierLoc, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d05ff2)
#24 0x0000559a29b06718 clang::Sema::BuildDeclRefExpr(clang::ValueDecl*, clang::QualType, clang::ExprValueKind, clang::DeclarationNameInfo const&, clang::CXXScopeSpec const*, clang::NamedDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d06718)
#25 0x0000559a29b06a50 clang::Sema::BuildDeclarationNameExpr(clang::CXXScopeSpec const&, clang::DeclarationNameInfo const&, clang::NamedDecl*, clang::NamedDecl*, clang::TemplateArgumentListInfo const*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d06a50)
#26 0x0000559a29e6ab2b clang::Sema::CheckVarTemplateId(clang::CXXScopeSpec const&, clang::DeclarationNameInfo const&, clang::VarTemplateDecl*, clang::SourceLocation, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x606ab2b)
#27 0x0000559a29e6ac80 clang::Sema::BuildTemplateIdExpr(clang::CXXScopeSpec const&, clang::SourceLocation, clang::LookupResult&, bool, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x606ac80)
#28 0x0000559a29f73d25 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformUnresolvedLookupExpr(clang::UnresolvedLookupExpr*) SemaTemplateInstantiate.cpp:0:0
#29 0x0000559a29f57e6d clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#30 0x0000559a29f8a08f clang::Sema::SubstExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x618a08f)
#31 0x0000559a29954811 calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0

@Quuxplusone Quuxplusone added clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts labels Jan 16, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 16, 2022

@llvm/issue-subscribers-clang-frontend

@ChuanqiXu9
Copy link
Member Author

It hits the unreachable here:

#include "clang/AST/BuiltinTypes.def"
case BuiltinType::Dependent:
if (!NullOut)
llvm_unreachable("mangling a placeholder type");

The corresponding type is BoundMember, which would refer to A.begin in the example attached.

It looks easy to fix it by remove the unreachable assertion. But I feel it might not be a good solution. @urnathan @dwblaikie do you have opinion on this?

@Quuxplusone
Copy link
Contributor

@ChuanqiXu9: The assert-fail is happening when Clang tries to instantiate (and thus mangle the name of) B<decltype(t.begin)>. But it should never get that far! The C++ front-end should be noticing that (t.begin) is not a valid expression and thus causing the constraint to fail even before we start checking whether True<decltype(t.begin)> is satisfied.

Replace {t.begin}->True with requires True<decltype(t.begin)> and the problem goes away: https://godbolt.org/z/PK4fM3qnM

template<class T> constexpr bool B = true;
template<class T> concept True = B<T>;

template <class T>
concept Beginable = requires(T t) {
    requires True<decltype(t.begin)>;
};

struct A { int begin(); };
static_assert(Beginable<A>);

The problem is insufficient error-diagnosing on the front end. The mangling codepath's invariant/assertion is correct.

@ChuanqiXu9
Copy link
Member Author

I think you are right. And I can get a reduced example from your example: https://godbolt.org/z/7d3Pqsd86, it really helps.

@ChuanqiXu9 ChuanqiXu9 self-assigned this Jan 26, 2022
@Quuxplusone
Copy link
Contributor

Here's a related assertion failure, in which I use BuiltinType::Overload rather than BuiltinType::BoundMember to trigger the misbehavior:

template<class T> concept True = true;

template<class T> concept C = requires {
    { T::begin } -> True;
};

struct A {
    static void begin(int);
    static void begin(double);
};

int y = C<A>;

Clang trunk says:

clang++: /root/llvm-project/clang/lib/AST/ASTContext.cpp:3374: clang::QualType clang::ASTContext::getLValueReferenceType(clang::QualType, bool) const: Assertion `getCanonicalType(T) != OverloadTy && "Unresolved overloaded function type"' failed.
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++ -g -o /app/output.s -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++20 <source>
1.	<source>:12:13: current parser token ';'
 #0 0x000055b3f6e6926f PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #1 0x000055b3f6e67070 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a67070)
 #2 0x000055b3f6d9e868 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007ff31b5763c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
 #4 0x00007ff31b04518b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4618b)
 #5 0x00007ff31b024859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x25859)
 #6 0x00007ff31b024729 (/lib/x86_64-linux-gnu/libc.so.6+0x25729)
 #7 0x00007ff31b035f36 (/lib/x86_64-linux-gnu/libc.so.6+0x36f36)
 #8 0x000055b3f9833178 clang::ASTContext::getLValueReferenceType(clang::QualType, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6433178)
 #9 0x000055b3f91f5245 clang::Sema::BuildExprRequirement(clang::Expr*, bool, clang::SourceLocation, clang::concepts::ExprRequirement::ReturnTypeRequirement) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5df5245)
#10 0x000055b3f95b43d7 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformRequiresExpr(clang::RequiresExpr*) SemaTemplateInstantiate.cpp:0:0
#11 0x000055b3f9590eb1 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#12 0x000055b3f95c2faf clang::Sema::SubstExpr(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x61c2faf)
#13 0x000055b3f8f8c8a1 calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)::operator()(clang::Expr const*) const SemaConcept.cpp:0:0
#14 0x000055b3f8f8dc00 bool calculateConstraintSatisfaction<calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)>(clang::Sema&, clang::Expr const*, clang::ConstraintSatisfaction&, calculateConstraintSatisfaction(clang::Sema&, clang::NamedDecl const*, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceLocation, clang::MultiLevelTemplateArgumentList&, clang::Expr const*, clang::ConstraintSatisfaction&)::'lambda'(clang::Expr const*)&&) SemaConcept.cpp:0:0
#15 0x000055b3f8f8e3ca clang::Sema::CheckConstraintSatisfaction(clang::NamedDecl const*, llvm::ArrayRef<clang::Expr const*>, llvm::ArrayRef<clang::TemplateArgument>, clang::SourceRange, clang::ConstraintSatisfaction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5b8e3ca)
#16 0x000055b3f94a1aad clang::Sema::CheckConceptTemplateId(clang::CXXScopeSpec const&, clang::SourceLocation, clang::DeclarationNameInfo const&, clang::NamedDecl*, clang::ConceptDecl*, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x60a1aad)
#17 0x000055b3f94a3b3a clang::Sema::BuildTemplateIdExpr(clang::CXXScopeSpec const&, clang::SourceLocation, clang::LookupResult&, bool, clang::TemplateArgumentListInfo const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x60a3b3a)
#18 0x000055b3f9155f41 clang::Sema::ActOnIdExpression(clang::Scope*, clang::CXXScopeSpec&, clang::SourceLocation, clang::UnqualifiedId&, bool, bool, clang::CorrectionCandidateCallback*, bool, clang::Token*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5d55f41)
#19 0x000055b3f8de9777 clang::Parser::tryParseCXXIdExpression(clang::CXXScopeSpec&, bool, clang::Token&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x59e9777)
#20 0x000055b3f8de99f2 clang::Parser::ParseCXXIdExpression(bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x59e99f2)
#21 0x000055b3f8dd4bab clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x59d4bab)
#22 0x000055b3f8dd55fb clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x59d55fb)
#23 0x000055b3f8dd6c66 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x59d6c66)
[...]

@Quuxplusone
Copy link
Contributor

This is now https://reviews.llvm.org/D118552

ahatanaka pushed a commit to apple/llvm-project that referenced this issue May 26, 2022
Bug llvm#52905 was originally papered over in a different way, but
I believe this is the actually proper fix, or at least closer to
it. We need to detect placeholder types as close to the front-end
as possible, and cause them to fail constraints, rather than letting
them persist into later stages.

Fixes llvm#52905.
Fixes llvm#52909.
Fixes llvm#53075.

Differential Revision: https://reviews.llvm.org/D118552

(cherry picked from commit f6ce456)
ahatanaka added a commit to apple/llvm-project that referenced this issue May 27, 2022
…4758)

Bug llvm#52905 was originally papered over in a different way, but I believe this is the actually proper fix, or at least closer to it. We need to detect placeholder types as close to the front-end as possible, and cause them to fail constraints, rather than letting them persist into later stages.

Fixes llvm#52905.
Fixes llvm#52909.
Fixes llvm#53075.

Differential Revision: https://reviews.llvm.org/D118552

(cherry picked from commit f6ce456)

Co-authored-by: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++20 clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts
Projects
Status: No status
Development

No branches or pull requests

3 participants