1 | //===- unittests/Frontend/CodeGenActionTest.cpp --- FrontendAction tests --===// |
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 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Unit tests for CodeGenAction. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "clang/CodeGen/CodeGenAction.h" |
14 | #include "clang/Basic/LangStandard.h" |
15 | #include "clang/CodeGen/BackendUtil.h" |
16 | #include "clang/Frontend/CompilerInstance.h" |
17 | #include "clang/Lex/PreprocessorOptions.h" |
18 | #include "llvm/Support/FormatVariadic.h" |
19 | #include "gtest/gtest.h" |
20 | |
21 | using namespace llvm; |
22 | using namespace clang; |
23 | using namespace clang::frontend; |
24 | |
25 | namespace { |
26 | |
27 | |
28 | class NullCodeGenAction : public CodeGenAction { |
29 | public: |
30 | NullCodeGenAction(llvm::LLVMContext *_VMContext = nullptr) |
31 | : CodeGenAction(Backend_EmitMCNull, _VMContext) {} |
32 | |
33 | // The action does not call methods of ATContext. |
34 | void ExecuteAction() override { |
35 | CompilerInstance &CI = getCompilerInstance(); |
36 | if (!CI.hasPreprocessor()) |
37 | return; |
38 | if (!CI.hasSema()) |
39 | CI.createSema(TUKind: getTranslationUnitKind(), CompletionConsumer: nullptr); |
40 | } |
41 | }; |
42 | |
43 | |
44 | TEST(CodeGenTest, TestNullCodeGen) { |
45 | auto Invocation = std::make_shared<CompilerInvocation>(); |
46 | Invocation->getPreprocessorOpts().addRemappedFile( |
47 | From: "test.cc" , |
48 | To: MemoryBuffer::getMemBuffer(InputData: "" ).release()); |
49 | Invocation->getFrontendOpts().Inputs.push_back( |
50 | Elt: FrontendInputFile("test.cc" , Language::CXX)); |
51 | Invocation->getFrontendOpts().ProgramAction = EmitLLVM; |
52 | Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu" ; |
53 | CompilerInstance Compiler; |
54 | Compiler.setInvocation(std::move(Invocation)); |
55 | Compiler.createDiagnostics(); |
56 | EXPECT_TRUE(Compiler.hasDiagnostics()); |
57 | |
58 | std::unique_ptr<FrontendAction> Act(new NullCodeGenAction); |
59 | bool Success = Compiler.ExecuteAction(Act&: *Act); |
60 | EXPECT_TRUE(Success); |
61 | } |
62 | |
63 | TEST(CodeGenTest, CodeGenFromIRMemBuffer) { |
64 | auto Invocation = std::make_shared<CompilerInvocation>(); |
65 | std::unique_ptr<MemoryBuffer> MemBuffer = |
66 | MemoryBuffer::getMemBuffer(InputData: "" , BufferName: "test.ll" ); |
67 | Invocation->getFrontendOpts().Inputs.push_back( |
68 | Elt: FrontendInputFile(*MemBuffer, Language::LLVM_IR)); |
69 | Invocation->getFrontendOpts().ProgramAction = frontend::EmitLLVMOnly; |
70 | Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu" ; |
71 | CompilerInstance Compiler; |
72 | Compiler.setInvocation(std::move(Invocation)); |
73 | Compiler.createDiagnostics(); |
74 | EXPECT_TRUE(Compiler.hasDiagnostics()); |
75 | |
76 | EmitLLVMOnlyAction Action; |
77 | bool Success = Compiler.ExecuteAction(Act&: Action); |
78 | EXPECT_TRUE(Success); |
79 | } |
80 | |
81 | TEST(CodeGenTest, DebugInfoCWDCodeGen) { |
82 | // Check that debug info is accessing the current working directory from the |
83 | // VFS instead of calling \p llvm::sys::fs::current_path() directly. |
84 | |
85 | auto Sept = llvm::sys::path::get_separator(); |
86 | auto VFS = std::make_unique<llvm::vfs::InMemoryFileSystem>(); |
87 | VFS->setCurrentWorkingDirectory( |
88 | std::string(llvm::formatv(Fmt: "{0}in-memory-fs-cwd" , Vals&: Sept))); |
89 | std::string TestPath = |
90 | std::string(llvm::formatv(Fmt: "{0}in-memory-fs-cwd{0}test.cpp" , Vals&: Sept)); |
91 | VFS->addFile(Path: TestPath, ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: "int x;\n" )); |
92 | |
93 | auto Invocation = std::make_shared<CompilerInvocation>(); |
94 | Invocation->getFrontendOpts().Inputs.push_back( |
95 | Elt: FrontendInputFile("test.cpp" , Language::CXX)); |
96 | Invocation->getFrontendOpts().ProgramAction = EmitLLVM; |
97 | Invocation->getTargetOpts().Triple = "x86_64-unknown-linux-gnu" ; |
98 | Invocation->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); |
99 | CompilerInstance Compiler; |
100 | |
101 | SmallString<256> IRBuffer; |
102 | Compiler.setOutputStream(std::make_unique<raw_svector_ostream>(args&: IRBuffer)); |
103 | Compiler.setInvocation(std::move(Invocation)); |
104 | Compiler.createDiagnostics(); |
105 | Compiler.createFileManager(VFS: std::move(VFS)); |
106 | |
107 | EmitLLVMAction Action; |
108 | bool Success = Compiler.ExecuteAction(Act&: Action); |
109 | EXPECT_TRUE(Success); |
110 | |
111 | SmallString<128> RealCWD; |
112 | llvm::sys::fs::current_path(result&: RealCWD); |
113 | EXPECT_TRUE(!RealCWD.empty()); |
114 | EXPECT_FALSE(IRBuffer.str().contains(RealCWD)); |
115 | EXPECT_TRUE(IRBuffer.str().contains("in-memory-fs-cwd" )); |
116 | } |
117 | } |
118 | |