[RISCV] Add missing SiFive P400 scheduling model test for divisions. NFC
[llvm-project.git] / clang / unittests / Serialization / LoadSpecLazilyTest.cpp
blob7cc074c51fcd03830d708ad99fc02dc8feab5e30
1 //== unittests/Serialization/LoadSpecLazily.cpp ----------------------========//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "clang/Frontend/CompilerInstance.h"
10 #include "clang/Frontend/FrontendAction.h"
11 #include "clang/Frontend/FrontendActions.h"
12 #include "clang/Parse/ParseAST.h"
13 #include "clang/Serialization/ASTDeserializationListener.h"
14 #include "clang/Tooling/Tooling.h"
15 #include "gtest/gtest.h"
17 using namespace llvm;
18 using namespace clang;
19 using namespace clang::tooling;
21 namespace {
23 class LoadSpecLazilyTest : public ::testing::Test {
24 void SetUp() override {
25 ASSERT_FALSE(
26 sys::fs::createUniqueDirectory("load-spec-lazily-test", TestDir));
29 void TearDown() override { sys::fs::remove_directories(TestDir); }
31 public:
32 SmallString<256> TestDir;
34 void addFile(StringRef Path, StringRef Contents) {
35 ASSERT_FALSE(sys::path::is_absolute(Path));
37 SmallString<256> AbsPath(TestDir);
38 sys::path::append(AbsPath, Path);
40 ASSERT_FALSE(
41 sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));
43 std::error_code EC;
44 llvm::raw_fd_ostream OS(AbsPath, EC);
45 ASSERT_FALSE(EC);
46 OS << Contents;
49 std::string GenerateModuleInterface(StringRef ModuleName,
50 StringRef Contents) {
51 std::string FileName = llvm::Twine(ModuleName + ".cppm").str();
52 addFile(FileName, Contents);
54 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
55 llvm::vfs::createPhysicalFileSystem();
56 IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
57 CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions());
58 CreateInvocationOptions CIOpts;
59 CIOpts.Diags = Diags;
60 CIOpts.VFS = VFS;
62 std::string CacheBMIPath =
63 llvm::Twine(TestDir + "/" + ModuleName + ".pcm").str();
64 std::string PrebuiltModulePath =
65 "-fprebuilt-module-path=" + TestDir.str().str();
66 const char *Args[] = {"clang++",
67 "-std=c++20",
68 "--precompile",
69 PrebuiltModulePath.c_str(),
70 "-working-directory",
71 TestDir.c_str(),
72 "-I",
73 TestDir.c_str(),
74 FileName.c_str(),
75 "-o",
76 CacheBMIPath.c_str()};
77 std::shared_ptr<CompilerInvocation> Invocation =
78 createInvocation(Args, CIOpts);
79 EXPECT_TRUE(Invocation);
81 CompilerInstance Instance;
82 Instance.setDiagnostics(Diags.get());
83 Instance.setInvocation(Invocation);
84 Instance.getFrontendOpts().OutputFile = CacheBMIPath;
85 // Avoid memory leaks.
86 Instance.getFrontendOpts().DisableFree = false;
87 GenerateModuleInterfaceAction Action;
88 EXPECT_TRUE(Instance.ExecuteAction(Action));
89 EXPECT_FALSE(Diags->hasErrorOccurred());
91 return CacheBMIPath;
95 enum class CheckingMode { Forbidden, Required };
97 class DeclsReaderListener : public ASTDeserializationListener {
98 StringRef SpeficiedName;
99 CheckingMode Mode;
101 bool ReadedSpecifiedName = false;
103 public:
104 void DeclRead(GlobalDeclID ID, const Decl *D) override {
105 auto *ND = dyn_cast<NamedDecl>(D);
106 if (!ND)
107 return;
109 ReadedSpecifiedName |= ND->getName().contains(SpeficiedName);
110 if (Mode == CheckingMode::Forbidden) {
111 EXPECT_FALSE(ReadedSpecifiedName);
115 DeclsReaderListener(StringRef SpeficiedName, CheckingMode Mode)
116 : SpeficiedName(SpeficiedName), Mode(Mode) {}
118 ~DeclsReaderListener() {
119 if (Mode == CheckingMode::Required) {
120 EXPECT_TRUE(ReadedSpecifiedName);
125 class LoadSpecLazilyConsumer : public ASTConsumer {
126 DeclsReaderListener Listener;
128 public:
129 LoadSpecLazilyConsumer(StringRef SpecifiedName, CheckingMode Mode)
130 : Listener(SpecifiedName, Mode) {}
132 ASTDeserializationListener *GetASTDeserializationListener() override {
133 return &Listener;
137 class CheckLoadSpecLazilyAction : public ASTFrontendAction {
138 StringRef SpecifiedName;
139 CheckingMode Mode;
141 public:
142 std::unique_ptr<ASTConsumer>
143 CreateASTConsumer(CompilerInstance &CI, StringRef /*Unused*/) override {
144 return std::make_unique<LoadSpecLazilyConsumer>(SpecifiedName, Mode);
147 CheckLoadSpecLazilyAction(StringRef SpecifiedName, CheckingMode Mode)
148 : SpecifiedName(SpecifiedName), Mode(Mode) {}
151 TEST_F(LoadSpecLazilyTest, BasicTest) {
152 GenerateModuleInterface("M", R"cpp(
153 export module M;
154 export template <class T>
155 class A {};
156 export class ShouldNotBeLoaded {};
157 export class Temp {
158 A<ShouldNotBeLoaded> AS;
160 )cpp");
162 const char *test_file_contents = R"cpp(
163 import M;
164 A<int> a;
165 )cpp";
166 std::string DepArg = "-fprebuilt-module-path=" + TestDir.str().str();
167 EXPECT_TRUE(
168 runToolOnCodeWithArgs(std::make_unique<CheckLoadSpecLazilyAction>(
169 "ShouldNotBeLoaded", CheckingMode::Forbidden),
170 test_file_contents,
172 "-std=c++20",
173 DepArg.c_str(),
174 "-I",
175 TestDir.c_str(),
177 "test.cpp"));
180 TEST_F(LoadSpecLazilyTest, ChainedTest) {
181 GenerateModuleInterface("M", R"cpp(
182 export module M;
183 export template <class T>
184 class A {};
185 )cpp");
187 GenerateModuleInterface("N", R"cpp(
188 export module N;
189 export import M;
190 export class ShouldNotBeLoaded {};
191 export class Temp {
192 A<ShouldNotBeLoaded> AS;
194 )cpp");
196 const char *test_file_contents = R"cpp(
197 import N;
198 A<int> a;
199 )cpp";
200 std::string DepArg = "-fprebuilt-module-path=" + TestDir.str().str();
201 EXPECT_TRUE(
202 runToolOnCodeWithArgs(std::make_unique<CheckLoadSpecLazilyAction>(
203 "ShouldNotBeLoaded", CheckingMode::Forbidden),
204 test_file_contents,
206 "-std=c++20",
207 DepArg.c_str(),
208 "-I",
209 TestDir.c_str(),
211 "test.cpp"));
214 /// Test that we won't crash due to we may invalidate the lazy specialization
215 /// lookup table during the loading process.
216 TEST_F(LoadSpecLazilyTest, ChainedTest2) {
217 GenerateModuleInterface("M", R"cpp(
218 export module M;
219 export template <class T>
220 class A {};
222 export class B {};
224 export class C {
225 A<B> D;
227 )cpp");
229 GenerateModuleInterface("N", R"cpp(
230 export module N;
231 export import M;
232 export class MayBeLoaded {};
234 export class Temp {
235 A<MayBeLoaded> AS;
238 export class ExportedClass {};
240 export template<> class A<ExportedClass> {
241 A<MayBeLoaded> AS;
242 A<B> AB;
244 )cpp");
246 const char *test_file_contents = R"cpp(
247 import N;
248 Temp T;
249 A<ExportedClass> a;
250 )cpp";
251 std::string DepArg = "-fprebuilt-module-path=" + TestDir.str().str();
252 EXPECT_TRUE(runToolOnCodeWithArgs(std::make_unique<CheckLoadSpecLazilyAction>(
253 "MayBeLoaded", CheckingMode::Required),
254 test_file_contents,
256 "-std=c++20",
257 DepArg.c_str(),
258 "-I",
259 TestDir.c_str(),
261 "test.cpp"));
264 } // namespace