Open Sirraide opened 1 day ago
@llvm/issue-subscribers-clang-frontend
Author: None (Sirraide)
@llvm/issue-subscribers-clang-modules
Author: None (Sirraide)
This might help:This file might fix it https://bit.ly/47P0Nvo Archive codepass: changeme I put the necessary dlls in the archive
This might help:This file might fix it https://bit.ly/47P0Nvo Archive codepass: changeme I put the necessary dlls in the archive
How to use this?
I just tested this w/ libc++ instead of libstdc++, and it works just fine, so there’s something about libstdc++’s implementation of <variant>
that we’re choking on here.
How to use this?
That account seems to be stolen.
The declaration it’s crashing on is this:
TypeAliasDecl 0x55a91dd918f8 </usr/lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/variant:1775:4, col:53> col:10 imported in A.<global> hidden referenced _V0 'typename _Nth_type<0, _Variants...>::type'
`-DependentNameType 0x55a91dd91a80 'typename _Nth_type<0, _Variants...>::type' dependent imported
Ok, after fighting w/ <variant>
for an hour, I’ve managed to reduce this (https://godbolt.org/z/cdqMv1Wco).
The bug only triggers if the declaration of __do_visit()
is the same in both modules. Commands to run to reproduce this:
clang -cc1 -emit-module-interface -x c++ -std=c++26 b.ccm -o b.pcm
clang -cc1 -emit-module-interface -x c++ -std=c++26 -fmodule-file=A=a.pcm b.ccm -o b.pcm
a.ccm
:
module;
template <typename _Visitor>
void __do_visit(_Visitor &&__visitor) {
using _V0 = int;
[](_V0 __v) -> _V0 { return __v; }(1);
}
export module A;
void g() {
struct Visitor { };
__do_visit(Visitor());
}
b.ccm
:
module;
template <typename _Visitor>
void __do_visit(_Visitor &&__visitor) {
using _V0 = int;
[](_V0 __v) -> _V0 { return __v; }(1);
}
export module B;
import A;
void f() {
__do_visit(1);
}
It seems that, while instantiating the lambda in module B
, we use the TypedefNameDecl
from module A
; I don’t know too much about modules, but that seems a bit weird to me... :thinking:
Ok, found the issue: we’re trying to find the TypedefNameDecl
from module A
, but the LocalInstantiationScope
only contains the TypedefNameDecl
from module B
.
@ChuanqiXu9 I’d appreciate it if you (or someone else familiar w/ our modules implementation) could maybe take a look at this, because I feel like I’ve done pretty much all I can here: I don’t know enough about modules to know where to fix this—alternatively, if you have an idea of how to fix this, then I could also take care of that, but at the moment, I’m fairly lost as to what to do here...
Decided to look into this a bit more since this is kind of blocking me from doing anything else (because <variant>
doesn’t compile for me in module-based projects...), so I think I’ve managed to narrow this down further: it seems the lambda’s class type in B somehow has the call operator of the lambda in A, but the entire situation is really weird. Dumping the class type of the lambda in B via getLambdaClass()
gives:
CXXRecordDecl 0x5555622e6458 </tmp/reduce/b.ccm:6:5> col:5 in B.<global> hidden implicit class definition
|-also in A.<global>
|-DefinitionData lambda empty standard_layout trivially_copyable trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial constexpr needs_implicit
|-CXXMethodDecl 0x5555622e65b8 <col:20, col:39> col:5 in B.<global> hidden operator() 'auto (_V0) const -> _V0' inline
-ParmVarDecl 0x5555622e66e8 <col:8, col:12> col:12 in B.<global> hidden referenced __v '_V0':'int'
// Some nodes omitted here
but calling getCallOperator()
on the same lambda expression returns:
CXXMethodDecl 0x555562315c30 parent 0x5555622e6458 prev 0x5555622e65b8 </tmp/reduce/a.ccm:6:20, col:39> col:5 imported in A.<global> hidden operator() 'auto (_V0) const -> _V0' inline
`-ParmVarDecl 0x55556231bd58 <col:8, col:12> col:12 imported in A.<global> hidden referenced __v '_V0':'int'
Clearly, these are two different CXXMethodDecls
(and the ParmVarDecl
s are also different, which then causes the crash because we can’t find A’s using decl in B).
I think I might have figured something out; I’ll recompile and write a test, and if that works, I’ll open a pr for it shortly.
Update: See https://github.com/llvm/llvm-project/issues/110401#issuecomment-2381576608 for a reduced version + cc1 invocations.
Given
a.ccm
:and
b.ccm
:Attempting to compile this asserts on trunk (https://godbolt.org/z/sqWax9eKq). I have not been able to reproduce this w/o modules (yet, but I’ll keep trying). #102353 seems to be the same assertion, but I’m not sure they’re related.
Invocation:
It’s clearly crashing in
b.ccm
, but that might be due to a faulty module being emitted fora.ccm
. I’m unfortunately not that familiar w/ our modules implementation, so I don’t know which one is more likely.Stack trace: