diff options
Diffstat (limited to 'lib/CodeGen/ModuleBuilder.cpp')
| -rw-r--r-- | lib/CodeGen/ModuleBuilder.cpp | 66 | 
1 files changed, 52 insertions, 14 deletions
| diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index c5d18d3286a7..4f1a82e0248d 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -33,17 +33,41 @@ namespace {      std::unique_ptr<const llvm::DataLayout> TD;      ASTContext *Ctx;      const CodeGenOptions CodeGenOpts;  // Intentionally copied in. + +    unsigned HandlingTopLevelDecls; +    struct HandlingTopLevelDeclRAII { +      CodeGeneratorImpl &Self; +      HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self) : Self(Self) { +        ++Self.HandlingTopLevelDecls; +      } +      ~HandlingTopLevelDeclRAII() { +        if (--Self.HandlingTopLevelDecls == 0) +          Self.EmitDeferredDecls(); +      } +    }; + +    CoverageSourceInfo *CoverageInfo; +    protected:      std::unique_ptr<llvm::Module> M;      std::unique_ptr<CodeGen::CodeGenModule> Builder; +  private: +    SmallVector<CXXMethodDecl *, 8> DeferredInlineMethodDefinitions; +    public:      CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName, -                      const CodeGenOptions &CGO, llvm::LLVMContext& C) -      : Diags(diags), CodeGenOpts(CGO), +                      const CodeGenOptions &CGO, llvm::LLVMContext& C, +                      CoverageSourceInfo *CoverageInfo = nullptr) +      : Diags(diags), Ctx(nullptr), CodeGenOpts(CGO), HandlingTopLevelDecls(0), +        CoverageInfo(CoverageInfo),          M(new llvm::Module(ModuleName, C)) {} -    virtual ~CodeGeneratorImpl() {} +    virtual ~CodeGeneratorImpl() { +      // There should normally not be any leftover inline method definitions. +      assert(DeferredInlineMethodDefinitions.empty() || +             Diags.hasErrorOccurred()); +    }      llvm::Module* GetModule() override {        return M.get(); @@ -73,7 +97,7 @@ namespace {        M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());        TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));        Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD, -                                               Diags)); +                                               Diags, CoverageInfo));        for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i)          HandleDependentLibrary(CodeGenOpts.DependentLibraries[i]); @@ -90,18 +114,28 @@ namespace {        if (Diags.hasErrorOccurred())          return true; +      HandlingTopLevelDeclRAII HandlingDecl(*this); +        // Make sure to emit all elements of a Decl.        for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)          Builder->EmitTopLevelDecl(*I); -      // Emit any deferred inline method definitions. -      for (CXXMethodDecl *MD : DeferredInlineMethodDefinitions) -        Builder->EmitTopLevelDecl(MD); -      DeferredInlineMethodDefinitions.clear(); -        return true;      } +    void EmitDeferredDecls() { +      if (DeferredInlineMethodDefinitions.empty()) +        return; + +      // Emit any deferred inline method definitions. Note that more deferred +      // methods may be added during this loop, since ASTConsumer callbacks +      // can be invoked if AST inspection results in declarations being added. +      HandlingTopLevelDeclRAII HandlingDecl(*this); +      for (unsigned I = 0; I != DeferredInlineMethodDefinitions.size(); ++I) +        Builder->EmitTopLevelDecl(DeferredInlineMethodDefinitions[I]); +      DeferredInlineMethodDefinitions.clear(); +    } +      void HandleInlineMethodDefinition(CXXMethodDecl *D) override {        if (Diags.hasErrorOccurred())          return; @@ -117,6 +151,12 @@ namespace {        //     void foo() { bar(); }        //   } A;        DeferredInlineMethodDefinitions.push_back(D); + +      // Provide some coverage mapping even for methods that aren't emitted. +      // Don't do this for templated classes though, as they may not be +      // instantiable. +      if (!D->getParent()->getDescribedClassTemplate()) +        Builder->AddDeferredUnusedCoverageMapping(D);      }      /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl @@ -190,9 +230,6 @@ namespace {      void HandleDependentLibrary(llvm::StringRef Lib) override {        Builder->AddDependentLib(Lib);      } - -  private: -    std::vector<CXXMethodDecl *> DeferredInlineMethodDefinitions;    };  } @@ -202,6 +239,7 @@ CodeGenerator *clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags,                                          const std::string& ModuleName,                                          const CodeGenOptions &CGO,                                          const TargetOptions &/*TO*/, -                                        llvm::LLVMContext& C) { -  return new CodeGeneratorImpl(Diags, ModuleName, CGO, C); +                                        llvm::LLVMContext& C, +                                        CoverageSourceInfo *CoverageInfo) { +  return new CodeGeneratorImpl(Diags, ModuleName, CGO, C, CoverageInfo);  } | 
