From 54e655b3f8dc1d005655d9138880f3823d58224f Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Mon, 16 Nov 2020 12:56:11 +0000 Subject: [PATCH] Reland "Move the test compiler setup in a common place. NFCI" Original commit message: " Move the test compiler setup in a common place. NFCI This patch reduces the copy paste in the unittest/CodeGen folder by moving the common compiler setup phase in a header file. Differential revision: https://reviews.llvm.org/D91061 " This patch includes a fix for the memory leaks pointed out by @vitalybuka --- clang/unittests/CodeGen/BufferSourceTest.cpp | 54 ++----- clang/unittests/CodeGen/CodeGenExternalTest.cpp | 47 ++---- .../CodeGen/IncrementalProcessingTest.cpp | 52 +++---- clang/unittests/CodeGen/TBAAMetadataTest.cpp | 169 +++++++-------------- clang/unittests/CodeGen/TestCompiler.h | 111 ++++++++++++++ 5 files changed, 207 insertions(+), 226 deletions(-) create mode 100644 clang/unittests/CodeGen/TestCompiler.h diff --git a/clang/unittests/CodeGen/BufferSourceTest.cpp b/clang/unittests/CodeGen/BufferSourceTest.cpp index c1c2bf8..3ed688a 100644 --- a/clang/unittests/CodeGen/BufferSourceTest.cpp +++ b/clang/unittests/CodeGen/BufferSourceTest.cpp @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTConsumer.h" +#include "TestCompiler.h" + #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/TargetInfo.h" @@ -26,10 +27,11 @@ using namespace clang; namespace { -// Emitting constructors for global objects involves looking -// at the source file name. This makes sure that we don't crash -// if the source file is a memory buffer. -const char TestProgram[] = +TEST(BufferSourceTest, EmitCXXGlobalInitFunc) { + // Emitting constructors for global objects involves looking + // at the source file name. This makes sure that we don't crash + // if the source file is a memory buffer. + const char TestProgram[] = "class EmitCXXGlobalInitFunc " "{ " "public: " @@ -37,43 +39,13 @@ const char TestProgram[] = "}; " "EmitCXXGlobalInitFunc test; "; -TEST(BufferSourceTest, EmitCXXGlobalInitFunc) { - LLVMContext Context; - CompilerInstance compiler; - - compiler.createDiagnostics(); - compiler.getLangOpts().CPlusPlus = 1; - compiler.getLangOpts().CPlusPlus11 = 1; - - compiler.getTargetOpts().Triple = llvm::Triple::normalize( - llvm::sys::getProcessTriple()); - compiler.setTarget(clang::TargetInfo::CreateTargetInfo( - compiler.getDiagnostics(), - std::make_shared( - compiler.getTargetOpts()))); - - compiler.createFileManager(); - compiler.createSourceManager(compiler.getFileManager()); - compiler.createPreprocessor(clang::TU_Prefix); - - compiler.createASTContext(); - - compiler.setASTConsumer(std::unique_ptr( - CreateLLVMCodeGen( - compiler.getDiagnostics(), - "EmitCXXGlobalInitFuncTest", - compiler.getHeaderSearchOpts(), - compiler.getPreprocessorOpts(), - compiler.getCodeGenOpts(), - Context))); - - compiler.createSema(clang::TU_Prefix, nullptr); - - clang::SourceManager &sm = compiler.getSourceManager(); - sm.setMainFileID(sm.createFileID( - llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TestCompiler Compiler(LO); + Compiler.init(TestProgram); - clang::ParseAST(compiler.getSema(), false, false); + clang::ParseAST(Compiler.compiler.getSema(), false, false); } } // end anonymous namespace diff --git a/clang/unittests/CodeGen/CodeGenExternalTest.cpp b/clang/unittests/CodeGen/CodeGenExternalTest.cpp index 255b8c3..4358a9f 100644 --- a/clang/unittests/CodeGen/CodeGenExternalTest.cpp +++ b/clang/unittests/CodeGen/CodeGenExternalTest.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "TestCompiler.h" + #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/GlobalDecl.h" @@ -257,45 +259,18 @@ static void test_codegen_fns(MyASTConsumer *my) { } TEST(CodeGenExternalTest, CodeGenExternalTest) { - LLVMContext Context; - CompilerInstance compiler; - - compiler.createDiagnostics(); - compiler.getLangOpts().CPlusPlus = 1; - compiler.getLangOpts().CPlusPlus11 = 1; - - compiler.getTargetOpts().Triple = llvm::Triple::normalize( - llvm::sys::getProcessTriple()); - compiler.setTarget(clang::TargetInfo::CreateTargetInfo( - compiler.getDiagnostics(), - std::make_shared( - compiler.getTargetOpts()))); - - compiler.createFileManager(); - compiler.createSourceManager(compiler.getFileManager()); - compiler.createPreprocessor(clang::TU_Prefix); - - compiler.createASTContext(); - - - compiler.setASTConsumer(std::unique_ptr( - new MyASTConsumer(std::unique_ptr( - CreateLLVMCodeGen(compiler.getDiagnostics(), - "MemoryTypesTest", - compiler.getHeaderSearchOpts(), - compiler.getPreprocessorOpts(), - compiler.getCodeGenOpts(), - Context))))); - - compiler.createSema(clang::TU_Prefix, nullptr); + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TestCompiler Compiler(LO); + auto CustomASTConsumer + = std::make_unique(std::move(Compiler.CG)); - clang::SourceManager &sm = compiler.getSourceManager(); - sm.setMainFileID(sm.createFileID( - llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); + Compiler.init(TestProgram, std::move(CustomASTConsumer)); - clang::ParseAST(compiler.getSema(), false, false); + clang::ParseAST(Compiler.compiler.getSema(), false, false); - ASSERT_TRUE(test_codegen_fns_ran); + ASSERT_TRUE(test_codegen_fns_ran); } } // end anonymous namespace diff --git a/clang/unittests/CodeGen/IncrementalProcessingTest.cpp b/clang/unittests/CodeGen/IncrementalProcessingTest.cpp index 045ed9b..fed8ecd 100644 --- a/clang/unittests/CodeGen/IncrementalProcessingTest.cpp +++ b/clang/unittests/CodeGen/IncrementalProcessingTest.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "TestCompiler.h" + #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -108,52 +110,32 @@ const Function* getGlobalInit(llvm::Module& M) { } TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) { - LLVMContext Context; - CompilerInstance compiler; - - compiler.createDiagnostics(); - compiler.getLangOpts().CPlusPlus = 1; - compiler.getLangOpts().CPlusPlus11 = 1; - - compiler.getTargetOpts().Triple = llvm::Triple::normalize( - llvm::sys::getProcessTriple()); - compiler.setTarget(clang::TargetInfo::CreateTargetInfo( - compiler.getDiagnostics(), - std::make_shared( - compiler.getTargetOpts()))); - - compiler.createFileManager(); - compiler.createSourceManager(compiler.getFileManager()); - compiler.createPreprocessor(clang::TU_Prefix); - compiler.getPreprocessor().enableIncrementalProcessing(); - - compiler.createASTContext(); - - CodeGenerator* CG = - CreateLLVMCodeGen( - compiler.getDiagnostics(), - "main-module", - compiler.getHeaderSearchOpts(), - compiler.getPreprocessorOpts(), - compiler.getCodeGenOpts(), - Context); - compiler.setASTConsumer(std::unique_ptr(CG)); - compiler.createSema(clang::TU_Prefix, nullptr); - Sema& S = compiler.getSema(); + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TestCompiler Compiler(LO); + clang::CompilerInstance &CI = Compiler.compiler; + CI.getPreprocessor().enableIncrementalProcessing(); + CI.setASTConsumer(std::move(Compiler.CG)); + clang::CodeGenerator& CG = + static_cast(CI.getASTConsumer()); + CI.createSema(clang::TU_Prefix, nullptr); + + Sema& S = CI.getSema(); std::unique_ptr ParseOP(new Parser(S.getPreprocessor(), S, /*SkipFunctionBodies*/ false)); Parser &P = *ParseOP.get(); std::array, 3> M; - M[0] = IncrementalParseAST(compiler, P, *CG, nullptr); + M[0] = IncrementalParseAST(CI, P, CG, nullptr); ASSERT_TRUE(M[0]); - M[1] = IncrementalParseAST(compiler, P, *CG, TestProgram1); + M[1] = IncrementalParseAST(CI, P, CG, TestProgram1); ASSERT_TRUE(M[1]); ASSERT_TRUE(M[1]->getFunction("funcForProg1")); - M[2] = IncrementalParseAST(compiler, P, *CG, TestProgram2); + M[2] = IncrementalParseAST(CI, P, CG, TestProgram2); ASSERT_TRUE(M[2]); ASSERT_TRUE(M[2]->getFunction("funcForProg2")); // First code should not end up in second module: diff --git a/clang/unittests/CodeGen/TBAAMetadataTest.cpp b/clang/unittests/CodeGen/TBAAMetadataTest.cpp index feea864..149a8e074 100644 --- a/clang/unittests/CodeGen/TBAAMetadataTest.cpp +++ b/clang/unittests/CodeGen/TBAAMetadataTest.cpp @@ -7,18 +7,12 @@ //===----------------------------------------------------------------------===// #include "IRMatchers.h" +#include "TestCompiler.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Parse/ParseAST.h" -#include "llvm/ADT/Triple.h" #include "llvm/IR/Constants.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" #include @@ -27,82 +21,17 @@ using namespace llvm; namespace { -struct TestCompiler { - LLVMContext Context; - clang::CompilerInstance compiler; - clang::CodeGenerator *CG = nullptr; - llvm::Module *M = nullptr; - unsigned PtrSize = 0; - - void init(const char *TestProgram) { - compiler.createDiagnostics(); - compiler.getCodeGenOpts().StructPathTBAA = 1; - compiler.getCodeGenOpts().OptimizationLevel = 1; - - std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple()); - llvm::Triple Tr(TrStr); - Tr.setOS(Triple::Linux); - Tr.setVendor(Triple::VendorType::UnknownVendor); - Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment); - compiler.getTargetOpts().Triple = Tr.getTriple(); - compiler.setTarget(clang::TargetInfo::CreateTargetInfo( - compiler.getDiagnostics(), - std::make_shared(compiler.getTargetOpts()))); - - const clang::TargetInfo &TInfo = compiler.getTarget(); - PtrSize = TInfo.getPointerWidth(0) / 8; - - compiler.createFileManager(); - compiler.createSourceManager(compiler.getFileManager()); - compiler.createPreprocessor(clang::TU_Prefix); - - compiler.createASTContext(); - - CG = CreateLLVMCodeGen( - compiler.getDiagnostics(), - "main-module", - compiler.getHeaderSearchOpts(), - compiler.getPreprocessorOpts(), - compiler.getCodeGenOpts(), - Context); - compiler.setASTConsumer(std::unique_ptr(CG)); - - compiler.createSema(clang::TU_Prefix, nullptr); - - clang::SourceManager &sm = compiler.getSourceManager(); - sm.setMainFileID(sm.createFileID( - llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); - } - - const BasicBlock *compile() { - clang::ParseAST(compiler.getSema(), false, false); - M = CG->GetModule(); - - // Do not expect more than one function definition. - auto FuncPtr = M->begin(); - for (; FuncPtr != M->end(); ++FuncPtr) - if (!FuncPtr->isDeclaration()) - break; - assert(FuncPtr != M->end()); - const llvm::Function &Func = *FuncPtr; - ++FuncPtr; - for (; FuncPtr != M->end(); ++FuncPtr) - if (!FuncPtr->isDeclaration()) - break; - assert(FuncPtr == M->end()); - - // The function must consist of single basic block. - auto BBPtr = Func.begin(); - assert(Func.begin() != Func.end()); - const BasicBlock &BB = *BBPtr; - ++BBPtr; - assert(BBPtr == Func.end()); - - return &BB; +struct TBAATestCompiler : public TestCompiler { + TBAATestCompiler(clang::LangOptions LO, clang::CodeGenOptions CGO) + : TestCompiler(LO, CGO) {} + static clang::CodeGenOptions getCommonCodeGenOpts() { + clang::CodeGenOptions CGOpts; + CGOpts.StructPathTBAA = 1; + CGOpts.OptimizationLevel = 1; + return CGOpts; } }; - auto OmnipotentCharC = MMTuple( MMString("omnipotent char"), MMTuple( @@ -132,8 +61,8 @@ TEST(TBAAMetadataTest, BasicTypes) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().C11 = 1; + clang::LangOptions LO; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -228,8 +157,9 @@ TEST(TBAAMetadataTest, CFields) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().C11 = 1; + clang::LangOptions LO; + LO.C11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -349,8 +279,9 @@ TEST(TBAAMetadataTest, CTypedefFields) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().C11 = 1; + clang::LangOptions LO; + LO.C11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -441,8 +372,9 @@ TEST(TBAAMetadataTest, CTypedefFields2) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().C11 = 1; + clang::LangOptions LO; + LO.C11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -534,8 +466,9 @@ TEST(TBAAMetadataTest, CTypedefFields3) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().C11 = 1; + clang::LangOptions LO; + LO.C11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -635,9 +568,10 @@ TEST(TBAAMetadataTest, CXXFields) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -757,9 +691,10 @@ TEST(TBAAMetadataTest, CXXTypedefFields) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -857,9 +792,10 @@ TEST(TBAAMetadataTest, StructureFields) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -938,9 +874,10 @@ TEST(TBAAMetadataTest, ArrayFields) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -1016,9 +953,10 @@ TEST(TBAAMetadataTest, BaseClass) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -1094,9 +1032,10 @@ TEST(TBAAMetadataTest, PolymorphicClass) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -1170,9 +1109,10 @@ TEST(TBAAMetadataTest, VirtualBase) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); @@ -1255,9 +1195,10 @@ TEST(TBAAMetadataTest, TemplSpec) { } )**"; - TestCompiler Compiler; - Compiler.compiler.getLangOpts().CPlusPlus = 1; - Compiler.compiler.getLangOpts().CPlusPlus11 = 1; + clang::LangOptions LO; + LO.CPlusPlus = 1; + LO.CPlusPlus11 = 1; + TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h new file mode 100644 index 0000000..c2fd8ac --- /dev/null +++ b/clang/unittests/CodeGen/TestCompiler.h @@ -0,0 +1,111 @@ +//=== unittests/CodeGen/TestCompiler.h - Match on the LLVM IR ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H +#define CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H + + +#include "clang/AST/ASTConsumer.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Parse/ParseAST.h" + +#include "llvm/IR/Constants.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Host.h" + +namespace llvm { + +struct TestCompiler { + LLVMContext Context; + clang::CompilerInstance compiler; + std::unique_ptr CG; + llvm::Module *M = nullptr; + unsigned PtrSize = 0; + + TestCompiler(clang::LangOptions LO, + clang::CodeGenOptions CGO = clang::CodeGenOptions()) { + compiler.getLangOpts() = LO; + compiler.getCodeGenOpts() = CGO; + compiler.createDiagnostics(); + + std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple()); + llvm::Triple Tr(TrStr); + Tr.setOS(Triple::Linux); + Tr.setVendor(Triple::VendorType::UnknownVendor); + Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment); + compiler.getTargetOpts().Triple = Tr.getTriple(); + compiler.setTarget(clang::TargetInfo::CreateTargetInfo( + compiler.getDiagnostics(), + std::make_shared(compiler.getTargetOpts()))); + + const clang::TargetInfo &TInfo = compiler.getTarget(); + PtrSize = TInfo.getPointerWidth(0) / 8; + + compiler.createFileManager(); + compiler.createSourceManager(compiler.getFileManager()); + compiler.createPreprocessor(clang::TU_Prefix); + + compiler.createASTContext(); + + CG.reset(CreateLLVMCodeGen(compiler.getDiagnostics(), + "main-module", + compiler.getHeaderSearchOpts(), + compiler.getPreprocessorOpts(), + compiler.getCodeGenOpts(), + Context)); + } + + void init(const char *TestProgram, + std::unique_ptr Consumer = nullptr) { + if (!Consumer) + Consumer = std::move(CG); + + compiler.setASTConsumer(std::move(Consumer)); + + compiler.createSema(clang::TU_Prefix, nullptr); + + clang::SourceManager &sm = compiler.getSourceManager(); + sm.setMainFileID(sm.createFileID( + llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User)); + } + + const BasicBlock *compile() { + clang::ParseAST(compiler.getSema(), false, false); + M = + static_cast(compiler.getASTConsumer()).GetModule(); + + // Do not expect more than one function definition. + auto FuncPtr = M->begin(); + for (; FuncPtr != M->end(); ++FuncPtr) + if (!FuncPtr->isDeclaration()) + break; + assert(FuncPtr != M->end()); + const llvm::Function &Func = *FuncPtr; + ++FuncPtr; + for (; FuncPtr != M->end(); ++FuncPtr) + if (!FuncPtr->isDeclaration()) + break; + assert(FuncPtr == M->end()); + + // The function must consist of single basic block. + auto BBPtr = Func.begin(); + assert(Func.begin() != Func.end()); + const BasicBlock &BB = *BBPtr; + ++BBPtr; + assert(BBPtr == Func.end()); + + return &BB; + } +}; + +} // namespace llvm +#endif // CLANG_UNITTESTS_CODEGEN_TESTCOMPILER_H -- 2.7.4