xref: /llvm-project/clang/unittests/Frontend/CodeGenActionTest.cpp (revision a1153cd6fedd4c906a9840987934ca4712e34cb2)
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(getTranslationUnitKind(), nullptr);
40   }
41 };
42 
43 
44 TEST(CodeGenTest, TestNullCodeGen) {
45   auto Invocation = std::make_shared<CompilerInvocation>();
46   Invocation->getPreprocessorOpts().addRemappedFile(
47       "test.cc",
48       MemoryBuffer::getMemBuffer("").release());
49   Invocation->getFrontendOpts().Inputs.push_back(
50       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);
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("", "test.ll");
67   Invocation->getFrontendOpts().Inputs.push_back(
68       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(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("{0}in-memory-fs-cwd", Sept)));
89   std::string TestPath =
90       std::string(llvm::formatv("{0}in-memory-fs-cwd{0}test.cpp", Sept));
91   VFS->addFile(TestPath, 0, llvm::MemoryBuffer::getMemBuffer("int x;\n"));
92 
93   auto Invocation = std::make_shared<CompilerInvocation>();
94   Invocation->getFrontendOpts().Inputs.push_back(
95       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>(IRBuffer));
103   Compiler.setInvocation(std::move(Invocation));
104   Compiler.createDiagnostics();
105   Compiler.createFileManager(std::move(VFS));
106 
107   EmitLLVMAction Action;
108   bool Success = Compiler.ExecuteAction(Action);
109   EXPECT_TRUE(Success);
110 
111   SmallString<128> RealCWD;
112   llvm::sys::fs::current_path(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