-
Notifications
You must be signed in to change notification settings - Fork 12k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[C++20] [Modules] Handle inconsistent deduced function return type fr…
…om importing modules Close #78830 Close #60085 The direct reason of the issues is that in a module unit, the return type of a function is deduced to a concrete type (e.g., int) but in the other module unit, the return type of the same function is not deduced yet (e.g, auto). Then when we importing the 2 modules, the later function is selected but the code generator doesn't know how to generate the auto type. So here is the crash. The tricky part here is that, when the ASTReader reads the second unreduced function, it finds the reading function has the same signature with the already read deduced one and they have the same ODRHash. So that the ASTReader skips loading the function body of the unreduced function then the code generator can't infer the undeduced type like it usually can. Also this is generally fine for functions without deducing type since it is sufficient to emit a function call without the function body. Also in fact, we've already handled the case that the functon has deduced type and its deducing state is inconsist in different modules: https://github.com/llvm/llvm-project/blob/3ea92ea2f9d236569f82825cdba6d59bcc22495c/clang/lib/Serialization/ASTReader.cpp#L9531-L9544 and https://github.com/llvm/llvm-project/blob/3ea92ea2f9d236569f82825cdba6d59bcc22495c/clang/lib/Serialization/ASTReaderDecl.cpp#L3643-L3647. We've handled the case: (1) If we read the undeduced functions first and read the deduced functions later, the compiler will propagate the deduced type info for redecls in the end of the reading. (2) If we read the deduced functions first and read the undeduced functions later, we will propagae the deduced type info when we **complete the redecl chain**. However, in the reporting issues, we're in the second case and reproducer didn't trigger the action to complete the redecl chain. So here is the crash. Then it is obvious how should fix the problem. We should complete the redecl chain for undeduced function types in the end of the reading for the second case.
- Loading branch information
1 parent
7da7695
commit ba1e84f
Showing
5 changed files
with
172 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// RUN: rm -rf %t | ||
// RUN: mkdir %t | ||
// RUN: split-file %s %t | ||
// | ||
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/d.cppm \ | ||
// RUN: -emit-module-interface -o %t/d.pcm | ||
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cppm \ | ||
// RUN: -emit-module-interface -o %t/c.pcm -fprebuilt-module-path=%t | ||
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \ | ||
// RUN: -emit-module-interface -o %t/b.pcm -fprebuilt-module-path=%t | ||
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \ | ||
// RUN: -emit-module-interface -o %t/a.pcm -fprebuilt-module-path=%t | ||
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.pcm \ | ||
// RUN: -S -emit-llvm -disable-llvm-passes -o - -fprebuilt-module-path=%t \ | ||
// RUN: | FileCheck %t/a.cppm | ||
|
||
//--- d.cppm | ||
export module d; | ||
|
||
export template<typename> | ||
struct integer { | ||
using type = int; | ||
|
||
static constexpr auto value() { | ||
return 0; | ||
} | ||
|
||
friend constexpr void f(integer const x) { | ||
x.value(); | ||
} | ||
}; | ||
|
||
export constexpr void ddd(auto const value) { | ||
f(value); | ||
} | ||
|
||
|
||
template<typename T> | ||
constexpr auto dd = T(); | ||
|
||
export template<typename T> | ||
constexpr auto d() { | ||
dd<T>; | ||
} | ||
|
||
//--- c.cppm | ||
export module c; | ||
|
||
import d; | ||
|
||
template<typename T> | ||
auto cc = T(); | ||
|
||
auto c() { | ||
cc<integer<int>>; | ||
integer<int>().value(); | ||
} | ||
|
||
//--- b.cppm | ||
export module b; | ||
|
||
import d; | ||
|
||
auto b() { | ||
integer<int>::type; | ||
} | ||
|
||
//--- a.cppm | ||
export module a; | ||
|
||
import b; | ||
import c; | ||
import d; | ||
|
||
constexpr void aa() { | ||
d<integer<unsigned>>(); | ||
ddd(integer<int>()); | ||
} | ||
|
||
export extern "C" void a() { | ||
aa(); | ||
} | ||
|
||
// Checks that we emit the IR successfully. | ||
// CHECK: define{{.*}}@a( |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// RUN: rm -rf %t | ||
// RUN: mkdir -p %t | ||
// RUN: split-file %s %t | ||
// | ||
// RUN: %clang_cc1 -std=c++20 %t/Type.cppm -emit-module-interface -o \ | ||
// RUN: %t/MyVec-Type.pcm -triple=x86_64-linux-gnu | ||
// RUN:%clang_cc1 -std=c++20 %t/Vec.cppm -emit-module-interface -o \ | ||
// RUN: %t/MyVec-Vec.pcm -fmodule-file=MyVec:Type=%t/MyVec-Type.pcm \ | ||
// RUN: -triple=x86_64-linux-gnu | ||
// RUN: %clang_cc1 -std=c++20 %t/Vec2.cppm -emit-module-interface -o \ | ||
// RUN: %t/MyVec-Vec2.pcm -fmodule-file=MyVec:Type=%t/MyVec-Type.pcm \ | ||
// RUN: -triple=x86_64-linux-gnu | ||
// RUN: %clang_cc1 -std=c++20 %t/Calculator.cppm -emit-module-interface -o \ | ||
// RUN: %t/MyVec-Calculator.pcm -fmodule-file=MyVec:Vec=%t/MyVec-Vec.pcm \ | ||
// RUN: -fmodule-file=MyVec:Vec2=%t/MyVec-Vec2.pcm \ | ||
// RUN: -fmodule-file=MyVec:Type=%t/MyVec-Type.pcm \ | ||
// RUN: -triple=x86_64-linux-gnu | ||
// RUN: %clang_cc1 -std=c++20 %t/MyVec-Calculator.pcm -S -emit-llvm \ | ||
// RUN: -fmodule-file=MyVec:Vec=%t/MyVec-Vec.pcm \ | ||
// RUN: -fmodule-file=MyVec:Vec2=%t/MyVec-Vec2.pcm \ | ||
// RUN: -fmodule-file=MyVec:Type=%t/MyVec-Type.pcm \ | ||
// RUN: -triple=x86_64-linux-gnu -o - \ | ||
// RUN: | FileCheck %t/Calculator.cppm | ||
|
||
//--- Type.cppm | ||
export module MyVec:Type; | ||
|
||
template <class T> struct Size { | ||
auto total() const { return 1; } | ||
}; | ||
|
||
//--- Vec.cppm | ||
export module MyVec:Vec; | ||
import :Type; | ||
|
||
int size_ = Size<int>().total(); | ||
|
||
//--- Vec2.cppm | ||
export module MyVec:Vec2; | ||
import :Type; | ||
|
||
struct Vec2 { | ||
Size<int> size_; | ||
}; | ||
|
||
//--- Calculator.cppm | ||
export module MyVec:Calculator; | ||
|
||
import :Vec; | ||
import :Vec2; | ||
|
||
auto Calculate() { return Size<int>().total(); }; | ||
|
||
// Check the emitted module initializer to make sure we generate the module unit | ||
// successfully. | ||
// CHECK: @_ZW5MyVec9Calculatev |