1 //=== unittests/CodeGen/IncrementalProcessingTest.cpp - IncrementalCodeGen ===// 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 #include "clang/AST/ASTConsumer.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/RecursiveASTVisitor.h" 12 #include "clang/Basic/TargetInfo.h" 13 #include "clang/CodeGen/ModuleBuilder.h" 14 #include "clang/Frontend/CompilerInstance.h" 15 #include "clang/Interpreter/Interpreter.h" 16 #include "clang/Lex/Preprocessor.h" 17 #include "clang/Parse/Parser.h" 18 #include "clang/Sema/Sema.h" 19 #include "llvm/ADT/Triple.h" 20 #include "llvm/IR/LLVMContext.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/Support/Host.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 #include "gtest/gtest.h" 25 26 #include <memory> 27 28 using namespace llvm; 29 using namespace clang; 30 31 namespace { 32 33 // Incremental processing produces several modules, all using the same "main 34 // file". Make sure CodeGen can cope with that, e.g. for static initializers. 35 const char TestProgram1[] = "extern \"C\" int funcForProg1() { return 17; }\n" 36 "struct EmitCXXGlobalInitFunc1 {\n" 37 " EmitCXXGlobalInitFunc1() {}\n" 38 "} test1;"; 39 40 const char TestProgram2[] = "extern \"C\" int funcForProg2() { return 42; }\n" 41 "struct EmitCXXGlobalInitFunc2 {\n" 42 " EmitCXXGlobalInitFunc2() {}\n" 43 "} test2;"; 44 45 const Function *getGlobalInit(llvm::Module *M) { 46 for (const auto &Func : *M) 47 if (Func.hasName() && Func.getName().startswith("_GLOBAL__sub_I_")) 48 return &Func; 49 50 return nullptr; 51 } 52 53 TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) { 54 std::vector<const char *> ClangArgv = {"-Xclang", "-emit-llvm-only"}; 55 auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv)); 56 auto Interp = llvm::cantFail(Interpreter::create(std::move(CI))); 57 58 std::array<clang::PartialTranslationUnit *, 2> PTUs; 59 60 PTUs[0] = &llvm::cantFail(Interp->Parse(TestProgram1)); 61 ASSERT_TRUE(PTUs[0]->TheModule); 62 ASSERT_TRUE(PTUs[0]->TheModule->getFunction("funcForProg1")); 63 64 PTUs[1] = &llvm::cantFail(Interp->Parse(TestProgram2)); 65 ASSERT_TRUE(PTUs[1]->TheModule); 66 ASSERT_TRUE(PTUs[1]->TheModule->getFunction("funcForProg2")); 67 // First code should not end up in second module: 68 ASSERT_FALSE(PTUs[1]->TheModule->getFunction("funcForProg1")); 69 70 // Make sure global inits exist and are unique: 71 const Function *GlobalInit1 = getGlobalInit(PTUs[0]->TheModule.get()); 72 ASSERT_TRUE(GlobalInit1); 73 74 const Function *GlobalInit2 = getGlobalInit(PTUs[1]->TheModule.get()); 75 ASSERT_TRUE(GlobalInit2); 76 77 ASSERT_FALSE(GlobalInit1->getName() == GlobalInit2->getName()); 78 } 79 80 } // end anonymous namespace 81