llvm / llvm-project

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

`-ast-dump-decl-types` crashes on codes involving concepts #94928

Closed zyn0217 closed 2 weeks ago

zyn0217 commented 3 months ago
backtrace

``` clang++: /root/llvm-project/llvm/include/llvm/Support/Casting.h:662: decltype(auto) llvm::dyn_cast(From*) [with To = clang::ValueDecl; From = clang::Decl]: Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed. #0 0x0000000003a01968 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a01968) #1 0x00000000039ff64c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x39ff64c) #2 0x0000000003948068 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0 #3 0x00007a2c9c642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #4 0x00007a2c9c6969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc) #5 0x00007a2c9c642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476) #6 0x00007a2c9c6287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3) #7 0x00007a2c9c62871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b) #8 0x00007a2c9c639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96) #9 0x00000000045cb5a5 (anonymous namespace)::ASTPrinter::print(clang::Decl*) ASTConsumers.cpp:0:0 #10 0x00000000045cd6ef (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #11 0x00000000045cda6a clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseDeclContextHelper(clang::DeclContext*) (.part.0) ASTConsumers.cpp:0:0 #12 0x00000000045d72f9 clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) ASTConsumers.cpp:0:0 #13 0x00000000045cd670 (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #14 0x000000000635b0ac clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x635b0ac) ... ```

Code:

namespace ns {

template <typename T>
concept C = true;

} // namespace ns

using ns::C;

template <typename T> concept Foo = C<T>;

template <C... T, C auto U>
auto FooFunc(C auto V) -> C decltype(auto) {
  C auto W = V;
  return W;
}

Command line:

-std=c++20 -Xclang -ast-dump -Xclang -ast-dump-decl-types -Xclang -ast-dump-filter="Foo"

https://godbolt.org/z/ebcMq8b4e

llvmbot commented 3 months ago

@llvm/issue-subscribers-c-20

Author: Younan Zhang (zyn0217)

<details><summary>backtrace</summary> <p> ``` clang++: /root/llvm-project/llvm/include/llvm/Support/Casting.h:662: decltype(auto) llvm::dyn_cast(From*) [with To = clang::ValueDecl; From = clang::Decl]: Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed. #0 0x0000000003a01968 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a01968) #1 0x00000000039ff64c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x39ff64c) #2 0x0000000003948068 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0 #3 0x00007a2c9c642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #4 0x00007a2c9c6969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc) #5 0x00007a2c9c642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476) #6 0x00007a2c9c6287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3) #7 0x00007a2c9c62871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b) #8 0x00007a2c9c639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96) #9 0x00000000045cb5a5 (anonymous namespace)::ASTPrinter::print(clang::Decl*) ASTConsumers.cpp:0:0 #10 0x00000000045cd6ef (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #11 0x00000000045cda6a clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseDeclContextHelper(clang::DeclContext*) (.part.0) ASTConsumers.cpp:0:0 #12 0x00000000045d72f9 clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) ASTConsumers.cpp:0:0 #13 0x00000000045cd670 (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #14 0x000000000635b0ac clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x635b0ac) ... ``` </p> </details> Code: ```cpp namespace ns { template <typename T> concept C = true; } // namespace ns using ns::C; template <typename T> concept Foo = C<T>; template <C... T, C auto U> auto FooFunc(C auto V) -> C decltype(auto) { C auto W = V; return W; } ``` Command line: ``` -std=c++20 -Xclang -ast-dump -Xclang -ast-dump-decl-types -Xclang -ast-dump-filter="Foo" ``` https://godbolt.org/z/ebcMq8b4e
llvmbot commented 3 months ago

@llvm/issue-subscribers-clang-frontend

Author: Younan Zhang (zyn0217)

<details><summary>backtrace</summary> <p> ``` clang++: /root/llvm-project/llvm/include/llvm/Support/Casting.h:662: decltype(auto) llvm::dyn_cast(From*) [with To = clang::ValueDecl; From = clang::Decl]: Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed. #0 0x0000000003a01968 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a01968) #1 0x00000000039ff64c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x39ff64c) #2 0x0000000003948068 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0 #3 0x00007a2c9c642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #4 0x00007a2c9c6969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc) #5 0x00007a2c9c642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476) #6 0x00007a2c9c6287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3) #7 0x00007a2c9c62871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b) #8 0x00007a2c9c639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96) #9 0x00000000045cb5a5 (anonymous namespace)::ASTPrinter::print(clang::Decl*) ASTConsumers.cpp:0:0 #10 0x00000000045cd6ef (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #11 0x00000000045cda6a clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseDeclContextHelper(clang::DeclContext*) (.part.0) ASTConsumers.cpp:0:0 #12 0x00000000045d72f9 clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) ASTConsumers.cpp:0:0 #13 0x00000000045cd670 (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #14 0x000000000635b0ac clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x635b0ac) ... ``` </p> </details> Code: ```cpp namespace ns { template <typename T> concept C = true; } // namespace ns using ns::C; template <typename T> concept Foo = C<T>; template <C... T, C auto U> auto FooFunc(C auto V) -> C decltype(auto) { C auto W = V; return W; } ``` Command line: ``` -std=c++20 -Xclang -ast-dump -Xclang -ast-dump-decl-types -Xclang -ast-dump-filter="Foo" ``` https://godbolt.org/z/ebcMq8b4e
llvmbot commented 2 months ago

Hi!

This issue may be a good introductory issue for people new to working on LLVM. If you would like to work on this issue, your first steps are:

  1. Check that no other contributor has already been assigned to this issue. If you believe that no one is actually working on it despite an assignment, ping the person. After one week without a response, the assignee may be changed.
  2. In the comments of this issue, request for it to be assigned to you, or just create a pull request after following the steps below. Mention this issue in the description of the pull request.
  3. Fix the issue locally.
  4. Run the test suite locally. Remember that the subdirectories under test/ create fine-grained testing targets, so you can e.g. use make check-clang-ast to only run Clang's AST tests.
  5. Create a Git commit.
  6. Run git clang-format HEAD~1 to format your changes.
  7. Open a pull request to the upstream repository on GitHub. Detailed instructions can be found in GitHub's documentation. Mention this issue in the description of the pull request.

If you have any further questions about this issue, don't hesitate to ask via a comment in the thread below.

llvmbot commented 2 months ago

@llvm/issue-subscribers-good-first-issue

Author: Younan Zhang (zyn0217)

<details><summary>backtrace</summary> <p> ``` clang++: /root/llvm-project/llvm/include/llvm/Support/Casting.h:662: decltype(auto) llvm::dyn_cast(From*) [with To = clang::ValueDecl; From = clang::Decl]: Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed. #0 0x0000000003a01968 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a01968) #1 0x00000000039ff64c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x39ff64c) #2 0x0000000003948068 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0 #3 0x00007a2c9c642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520) #4 0x00007a2c9c6969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc) #5 0x00007a2c9c642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476) #6 0x00007a2c9c6287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3) #7 0x00007a2c9c62871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b) #8 0x00007a2c9c639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96) #9 0x00000000045cb5a5 (anonymous namespace)::ASTPrinter::print(clang::Decl*) ASTConsumers.cpp:0:0 #10 0x00000000045cd6ef (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #11 0x00000000045cda6a clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseDeclContextHelper(clang::DeclContext*) (.part.0) ASTConsumers.cpp:0:0 #12 0x00000000045d72f9 clang::RecursiveASTVisitor<(anonymous namespace)::ASTPrinter>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) ASTConsumers.cpp:0:0 #13 0x00000000045cd670 (anonymous namespace)::ASTPrinter::TraverseDecl(clang::Decl*) ASTConsumers.cpp:0:0 #14 0x000000000635b0ac clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x635b0ac) ... ``` </p> </details> Code: ```cpp namespace ns { template <typename T> concept C = true; } // namespace ns using ns::C; template <typename T> concept Foo = C<T>; template <C... T, C auto U> auto FooFunc(C auto V) -> C decltype(auto) { C auto W = V; return W; } ``` Command line: ``` -std=c++20 -Xclang -ast-dump -Xclang -ast-dump-decl-types -Xclang -ast-dump-filter="Foo" ``` https://godbolt.org/z/ebcMq8b4e
ofAlpaca commented 2 months ago

@zyn0217 @cor3ntin The crash likely occurred because TD->getTemplatedDecl() returned NULL, which in turn caused the assertion failure of dyn_cast<ValueDecl>(InnerD). If my assumption was right, I could add a if (InnerD) to prevent from referenceing NULL pointer. https://github.com/llvm/llvm-project/blob/94e966255fb4309f24805273d2e17f63a4e36d17/clang/lib/Frontend/ASTConsumers.cpp#L102-L109

zyn0217 commented 2 months ago

@ofAlpaca Yeah, but it would be great if there's any chance we can dump the ConceptDecls in that case instead of just disregarding them.

ofAlpaca commented 2 months ago

@zyn0217 @cor3ntin I also discover a similar error while using template-template parameter. https://godbolt.org/z/jsGr7sYeK It produces the same error as concept does.

I believe the reason for concept and template-template parameter crash is that they pass nullptr instead of NameDecl *Decl when initalizing TemplateDecl. https://github.com/llvm/llvm-project/blob/40940980bf87832b0275dcfa91ab03738c569b18/clang/include/clang/AST/DeclTemplate.h#L394-L406

Therefore, when calling getTemplateDecl(), it will return nullptr and cause assertion fail. https://github.com/llvm/llvm-project/blob/40940980bf87832b0275dcfa91ab03738c569b18/clang/include/clang/AST/DeclTemplate.h#L444

firstmoonlight commented 3 weeks ago

Hi, @ofAlpaca, I agree with you.

template < template-parameter-list >
concept concept-name attr (optional) = constraint-expression;

While concept has this form, So I believe that the concept will not have its underlying template, which means TemplatedDecl* will be nullptr. So When we encounter the nullptr, we should ignore it. And I would like to fix it like below.

if (DumpDeclTypes) {
  Decl *InnerD = D;
  if (auto *TD = dyn_cast<TemplateDecl>(D)) {
    if (TD->getTemplatedDecl()) InnerD = TD->getTemplatedDecl();
  }

Will you have time to create a pull request to this issue, otherwise I'll do this lately.

ofAlpaca commented 3 weeks ago

Hi @firstmoonlight, Thank you for reviewing my comment. And yes, I could send a PR for this issue.