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