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