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

ICE with concepts #46518

Closed
marehr opened this issue Aug 15, 2020 · 8 comments
Closed

ICE with concepts #46518

marehr opened this issue Aug 15, 2020 · 8 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla c++20

Comments

@marehr
Copy link

marehr commented Aug 15, 2020

Bugzilla Link 47174
Resolution FIXED
Resolved on Oct 11, 2021 20:29
Version trunk
OS Linux
Blocks #51489
CC @Quuxplusone,@mizvekov,@zygoloid,@saarraz,@tstellar
Fixed by commit(s) 219790c 168ece2

Extended Description

Hi clang-team,

(maybe you find a better summary)

the following code ICEs

#include <vector>
namespace ranges {
template <bool> struct if_then { template <typename T> using apply = T; };
template <typename I> char is_std_iterator_traits_specialized_impl_(void *);
template <typename I>
inline constexpr bool is_std_iterator_traits_specialized_v = 1 == sizeof(is_std_iterator_traits_specialized_impl_<I>(static_cast<std::iterator_traits<I> *>(nullptr)));
} // namespace ranges
namespace concepts {
template <typename T, typename U>
using common_reference_t = decltype(true ? std::declval<T &>() : std::declval<T &>());

template <typename T, typename U>
concept common_reference_with = requires()
{
  typename common_reference_t<T, U>;
};
} // namespace concepts
namespace ranges {
template <typename R>
using iter_value_t = typename if_then<is_std_iterator_traits_specialized_v<R>>::template apply<std::iterator_traits<R>>::value_type;

template <typename T>
concept input_range = ::concepts::common_reference_with<char &, iter_value_t<typename T::iterator> &>;
} // namespace ranges
namespace seqan3 {
template <typename rng_t>
concept sequence = ranges::input_range<rng_t> && std::is_same_v<rng_t, std::vector<char>>;

template <typename type>
struct debug_stream_printer;
} // namespace seqan3

template <typename rng_t> concept any_type = true;

namespace seqan3 {
template <ranges::input_range rng_t>
requires any_type<rng_t>
struct debug_stream_printer<rng_t> {};

template <sequence sequence_t>
requires any_type<sequence_t>
struct debug_stream_printer<sequence_t> {};
} // namespace seqan3

int main()
{
  seqan3::debug_stream_printer<std::vector<char>>{};
}

https://godbolt.org/z/fj9E73

with

clang++-git -std=c++2a ./ice.cpp

This code is a reduction from code that uses the ranges-v3 library.

@marehr
Copy link
Author

marehr commented Aug 15, 2020

assigned to @mizvekov

@Quuxplusone
Copy link
Contributor

// https://godbolt.org/z/1hEEaE
struct X {
template struct Y {
using type = int;
};
};

template concept C1 = sizeof(T) != 0;
template concept C2 = C1<typename T::template Y<1>::type>;

template requires true void f();
template requires true void f();

void test() {
f();
}

:8:35: error: no template named 'Y' template concept C2 = C1::type>; ^ :11:12: note: while substituting into concept arguments here; substitution failures not allowed in concept arguments template requires true void f(); ^ PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: /opt/compiler-explorer/clang-trunk/bin/clang++ -g -o ./output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++20 1. :14:10: current parser token ')' 2. :13:13: parsing function body 'test' 3. :13:13: in compound statement ('{}') #​0 0x0000564fe06a89ec llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x2f179ec) #​1 0x0000564fe06a6784 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x2f15784) #​2 0x0000564fe06a6a15 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x2f15a15) #​3 0x0000564fe0610838 CrashRecoverySignalHandler(int) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x2e7f838) #​4 0x00007f79806173c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0) #​5 0x0000564fe2493810 bool subsumes, clang::NamedDecl*, llvm::ArrayRef, bool&)::'lambda'(clang::AtomicConstraint const&, clang::AtomicConstraint const&)>(clang::Sema&, clang::NamedDecl*, llvm::ArrayRef, clang::NamedDecl*, llvm::ArrayRef, bool&, clang::Sema::IsAtLeastAsConstrained(clang::NamedDecl*, llvm::ArrayRef, clang::NamedDecl*, llvm::ArrayRef, bool&)::'lambda'(clang::AtomicConstraint const&, clang::AtomicConstraint const&)) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4d02810) #​6 0x0000564fe2495552 clang::Sema::IsAtLeastAsConstrained(clang::NamedDecl*, llvm::ArrayRef, clang::NamedDecl*, llvm::ArrayRef, bool&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4d04552) #​7 0x0000564fe29decdd clang::Sema::getMoreSpecializedTemplate(clang::FunctionTemplateDecl*, clang::FunctionTemplateDecl*, clang::SourceLocation, clang::TemplatePartialOrderingContext, unsigned int, unsigned int, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x524dcdd) #​8 0x0000564fe288a6b9 clang::isBetterOverloadCandidate(clang::Sema&, clang::OverloadCandidate const&, clang::OverloadCandidate const&, clang::SourceLocation, clang::OverloadCandidateSet::CandidateSetKind) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x50f96b9) #​9 0x0000564fe2890fbf clang::OverloadCandidateSet::BestViableFunction(clang::Sema&, clang::SourceLocation, clang::OverloadCandidate*&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x50fffbf) #​10 0x0000564fe28aebf7 clang::Sema::BuildOverloadedCallExpr(clang::Scope*, clang::Expr*, clang::UnresolvedLookupExpr*, clang::SourceLocation, llvm::MutableArrayRef, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x511dbf7) #​11 0x0000564fe265e6d0 clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef, clang::SourceLocation, clang::Expr*, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4ecd6d0) #​12 0x0000564fe265f364 clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef, clang::SourceLocation, clang::Expr*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4ece364) #​13 0x0000564fe22e44e6 clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b534e6) #​14 0x0000564fe22decbf clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b4dcbf) #​15 0x0000564fe22e1686 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b50686) #​16 0x0000564fe22e2844 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b51844) #​17 0x0000564fe22e34e9 clang::Parser::ParseExpression(clang::Parser::TypeCastState) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b524e9) #​18 0x0000564fe233c36d clang::Parser::ParseExprStatement(clang::Parser::ParsedStmtContext) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4bab36d) #​19 0x0000564fe23396db clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::Parser::ParsedAttributesWithRange&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4ba86db) #​20 0x0000564fe233a449 clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4ba9449) #​21 0x0000564fe23408a9 clang::Parser::ParseCompoundStatementBody(bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4baf8a9) #​22 0x0000564fe2344103 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4bb3103) #​23 0x0000564fe2298507 clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b07507) #​24 0x0000564fe22b46c5 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b236c5) #​25 0x0000564fe2293531 clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b02531) #​26 0x0000564fe2293c61 clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) (.part.250) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b02c61) #​27 0x0000564fe2299c09 clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b08c09) #​28 0x0000564fe229b191 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4b0a191) #​29 0x0000564fe228e2e9 clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4afd2e9) #​30 0x0000564fe14d6832 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3d45832) #​31 0x0000564fe0edd151 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x374c151) #​32 0x0000564fe0e8ee43 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x36fde43) #​33 0x0000564fe0fa46e3 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x38136e3) #​34 0x0000564fde6dc65c cc1_main(llvm::ArrayRef, char const*, void*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0xf4b65c) #​35 0x0000564fde6d8d0d ExecuteCC1Tool(llvm::SmallVectorImpl&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0xf47d0d) #​36 0x0000564fe0d55155 void llvm::function_ref::callback_fn >, std::__cxx11::basic_string, std::allocator >*, bool*) const::'lambda'()>(long) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x35c4155) #​37 0x0000564fe0610913 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x2e7f913) #​38 0x0000564fe0d55c87 clang::driver::CC1Command::Execute(llvm::ArrayRef >, std::__cxx11::basic_string, std::allocator >*, bool*) const (.part.172) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x35c4c87) #​39 0x0000564fe0d2e98a clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x359d98a) #​40 0x0000564fe0d2f4df clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl >&) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x359e4df) #​41 0x0000564fe0d38405 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl >&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x35a7405) #​42 0x0000564fde606266 main (/opt/compiler-explorer/clang-trunk/bin/clang+++0xe75266) #​43 0x00007f79800c80b3 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b3) #​44 0x0000564fde6d888a _start (/opt/compiler-explorer/clang-trunk/bin/clang+++0xf4788a)

@mizvekov
Copy link
Contributor

The minimal repro provided by Arthur shows two problems.

The ICE is fixed on main by 87aa318
Hopefully we can still cherry-pick this into the 13.x release branch.

The name lookup failure is a separate bug that I am still investigating.
It happens whenever performing the 'at least as constrained' check
with the C2 specialization. This causes the check to fail, and could lead to an erroneous ambiguity. This could be either in overload resolution, as shown, or when deciding between specializations to explicitly instantiate.
On the provided repro this is moot however because neither of those specializations is more constrained than the other and overload resolution there would be ambiguous anyway.

Here is a tweaked repro which should not be ambiguous:

struct X {
    template<int> struct Y {
        using type = int;
    };
};

template<class T> concept C1 = sizeof(T) >= 0;
template<class T> concept C2 = C1<typename T::template Y<0>::type>;

template<class T> requires C2<T> && C1<T> int f() { return 1; }
template<class T> requires C1<T> int f() { return 2; }
template int f<X>();

https://godbolt.org/z/7KGeMcx7K

It seems that when instantiating C1 from C2, we are simply dropping the typename T:: part and leaving only template Y<0>::type.

@mizvekov
Copy link
Contributor

mizvekov commented Aug 3, 2021

Fixed in trunk by 219790c

@tstellar
Copy link
Collaborator

Merged: 168ece2

@marehr
Copy link
Author

marehr commented Aug 17, 2021

Thank you!

@mizvekov
Copy link
Contributor

mentioned in issue llvm/llvm-bugzilla-archive#48656

@tstellar
Copy link
Collaborator

mentioned in issue #51489

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++20
Projects
None yet
Development

No branches or pull requests

4 participants