forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[RFC][C++20][Modules] Fix crash when function and lambda inside loade…
…d from different modules (llvm#104512) Summary: Because AST loading code is lazy and happens in unpredictable order it could happen that function and lambda inside function can be loaded from different modules. In this case, captured DeclRefExpr won’t match the corresponding VarDecl inside function. In AST it looks like this: ``` FunctionDecl 0x555564f4aff0 <Conv.h:33:1, line:41:1> line:33:35 imported in ./thrift_cpp2_base.h hidden tryTo 'Expected<Tgt, const char *> ()' inline |-also in ./folly-conv.h `-CompoundStmt 0x555564f7cfc8 <col:43, line:41:1> |-DeclStmt 0x555564f7ced8 <line:34:3, col:17> | `-VarDecl 0x555564f7cef8 <col:3, col:16> col:7 imported in ./thrift_cpp2_base.h hidden referenced result 'Tgt' cinit | `-IntegerLiteral 0x555564f7d080 <col:16> 'int' 0 |-CallExpr 0x555564f7cea8 <line:39:3, col:76> '<dependent type>' | |-UnresolvedLookupExpr 0x555564f7bea0 <col:3, col:19> '<overloaded function type>' lvalue (no ADL) = 'then_' 0x555564f7bef0 | |-CXXTemporaryObjectExpr 0x555564f7bcb0 <col:25, col:45> 'Expected<bool, int>':'folly::Expected<bool, int>' 'void () noexcept' zeroing | `-LambdaExpr 0x555564f7bc88 <col:48, col:75> '(lambda at Conv.h:39:48)' | |-CXXRecordDecl 0x555564f76b88 <col:48> col:48 imported in ./folly-conv.h hidden implicit <undeserialized declarations> class definition | | |-also in ./thrift_cpp2_base.h | | `-DefinitionData lambda empty standard_layout trivially_copyable literal can_const_default_init | | |-DefaultConstructor defaulted_is_constexpr | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param | | |-MoveConstructor exists simple trivial needs_implicit | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param | | |-MoveAssignment | | `-Destructor simple irrelevant trivial constexpr needs_implicit | `-CompoundStmt 0x555564f7d1a8 <col:58, col:75> | `-ReturnStmt 0x555564f7d198 <col:60, col:67> | `-DeclRefExpr 0x555564f7d0a0 <col:67> 'Tgt' lvalue Var 0x555564f7d0c8 'result' 'Tgt' refers_to_enclosing_variable_or_capture `-ReturnStmt 0x555564f7bc78 <line:40:3, col:11> `-InitListExpr 0x555564f7bc38 <col:10, col:11> 'void' ``` This diff changes AST deserialization to load lambdas inside canonical function declaration earlier right after the function to make sure that their canonical decl is loaded from the same module. Test Plan: check-clang
- Loading branch information
1 parent
25ece8b
commit 98a21cb
Showing
6 changed files
with
174 additions
and
1 deletion.
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
76 changes: 76 additions & 0 deletions
76
clang/test/Headers/crash-instantiated-in-scope-cxx-modules.cpp
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,76 @@ | ||
// RUN: rm -fR %t | ||
// RUN: split-file %s %t | ||
// RUN: cd %t | ||
// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header -Werror=uninitialized folly-conv.h | ||
// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header -Werror=uninitialized thrift_cpp2_base.h | ||
// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header -Werror=uninitialized -fmodule-file=folly-conv.pcm -fmodule-file=thrift_cpp2_base.pcm logger_base.h | ||
|
||
//--- Conv.h | ||
#pragma once | ||
|
||
template <typename _Tp, typename _Up = _Tp&&> | ||
_Up __declval(int); | ||
|
||
template <typename _Tp> | ||
auto declval() noexcept -> decltype(__declval<_Tp>(0)); | ||
|
||
namespace folly { | ||
|
||
template <class Value, class Error> | ||
struct Expected { | ||
template <class Yes> | ||
auto thenOrThrow() -> decltype(declval<Value&>()) { | ||
return 1; | ||
} | ||
}; | ||
|
||
struct ExpectedHelper { | ||
template <class Error, class T> | ||
static constexpr Expected<T, Error> return_(T) { | ||
return Expected<T, Error>(); | ||
} | ||
|
||
template <class This, class Fn, class E = int, class T = ExpectedHelper> | ||
static auto then_(This&&, Fn&&) | ||
-> decltype(T::template return_<E>((declval<Fn>()(true), 0))) { | ||
return Expected<int, int>(); | ||
} | ||
}; | ||
|
||
template <class Tgt> | ||
inline Expected<Tgt, const char*> tryTo() { | ||
Tgt result = 0; | ||
// In build with asserts: | ||
// clang/lib/Sema/SemaTemplateInstantiate.cpp: llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *clang::LocalInstantiationScope::findInstantiationOf(const Decl *): Assertion `isa<LabelDecl>(D) && "declaration not instantiated in this scope"' failed. | ||
// In release build compilation error on the line below inside lambda: | ||
// error: variable 'result' is uninitialized when used here [-Werror,-Wuninitialized] | ||
ExpectedHelper::then_(Expected<bool, int>(), [&](bool) { return result; }); | ||
return {}; | ||
} | ||
|
||
} // namespace folly | ||
|
||
inline void bar() { | ||
folly::tryTo<int>(); | ||
} | ||
// expected-no-diagnostics | ||
|
||
//--- folly-conv.h | ||
#pragma once | ||
#include "Conv.h" | ||
// expected-no-diagnostics | ||
|
||
//--- thrift_cpp2_base.h | ||
#pragma once | ||
#include "Conv.h" | ||
// expected-no-diagnostics | ||
|
||
//--- logger_base.h | ||
#pragma once | ||
import "folly-conv.h"; | ||
import "thrift_cpp2_base.h"; | ||
|
||
inline void foo() { | ||
folly::tryTo<unsigned>(); | ||
} | ||
// expected-no-diagnostics |
30 changes: 30 additions & 0 deletions
30
clang/test/Headers/crash-instantiated-in-scope-cxx-modules2.cpp
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,30 @@ | ||
// RUN: rm -fR %t | ||
// RUN: split-file %s %t | ||
// RUN: cd %t | ||
// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header header.h | ||
// RUN: %clang_cc1 -std=c++20 -fmodule-file=header.pcm main.cpp | ||
|
||
//--- header.h | ||
template <typename T> | ||
void f(T) {} | ||
|
||
class A { | ||
virtual ~A(); | ||
}; | ||
|
||
inline A::~A() { | ||
f([](){}); | ||
} | ||
|
||
struct B { | ||
void g() { | ||
f([](){ | ||
[](){}; | ||
}); | ||
} | ||
}; | ||
// expected-no-diagnostics | ||
|
||
//--- main.cpp | ||
import "header.h"; | ||
// expected-no-diagnostics |