1*0b57cec5SDimitry Andric //===-- ASTMerge.cpp - AST Merging Frontend Action --------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric #include "clang/Frontend/ASTUnit.h" 9*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 10*0b57cec5SDimitry Andric #include "clang/AST/ASTDiagnostic.h" 11*0b57cec5SDimitry Andric #include "clang/AST/ASTImporter.h" 12*0b57cec5SDimitry Andric #include "clang/AST/ASTImporterSharedState.h" 13*0b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 14*0b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 15*0b57cec5SDimitry Andric #include "clang/Frontend/FrontendActions.h" 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric using namespace clang; 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 20*0b57cec5SDimitry Andric ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 21*0b57cec5SDimitry Andric return AdaptedAction->CreateASTConsumer(CI, InFile); 22*0b57cec5SDimitry Andric } 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI) { 25*0b57cec5SDimitry Andric // FIXME: This is a hack. We need a better way to communicate the 26*0b57cec5SDimitry Andric // AST file, compiler instance, and file name than member variables 27*0b57cec5SDimitry Andric // of FrontendAction. 28*0b57cec5SDimitry Andric AdaptedAction->setCurrentInput(getCurrentInput(), takeCurrentASTUnit()); 29*0b57cec5SDimitry Andric AdaptedAction->setCompilerInstance(&CI); 30*0b57cec5SDimitry Andric return AdaptedAction->BeginSourceFileAction(CI); 31*0b57cec5SDimitry Andric } 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric void ASTMergeAction::ExecuteAction() { 34*0b57cec5SDimitry Andric CompilerInstance &CI = getCompilerInstance(); 35*0b57cec5SDimitry Andric CI.getDiagnostics().getClient()->BeginSourceFile( 36*0b57cec5SDimitry Andric CI.getASTContext().getLangOpts()); 37*0b57cec5SDimitry Andric CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 38*0b57cec5SDimitry Andric &CI.getASTContext()); 39*0b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticIDs> 40*0b57cec5SDimitry Andric DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); 41*0b57cec5SDimitry Andric auto SharedState = std::make_shared<ASTImporterSharedState>( 42*0b57cec5SDimitry Andric *CI.getASTContext().getTranslationUnitDecl()); 43*0b57cec5SDimitry Andric for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { 44*0b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> 45*0b57cec5SDimitry Andric Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(), 46*0b57cec5SDimitry Andric new ForwardingDiagnosticConsumer( 47*0b57cec5SDimitry Andric *CI.getDiagnostics().getClient()), 48*0b57cec5SDimitry Andric /*ShouldOwnClient=*/true)); 49*0b57cec5SDimitry Andric std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile( 50*0b57cec5SDimitry Andric ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags, 51*0b57cec5SDimitry Andric CI.getFileSystemOpts(), false); 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric if (!Unit) 54*0b57cec5SDimitry Andric continue; 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric ASTImporter Importer(CI.getASTContext(), CI.getFileManager(), 57*0b57cec5SDimitry Andric Unit->getASTContext(), Unit->getFileManager(), 58*0b57cec5SDimitry Andric /*MinimalImport=*/false, SharedState); 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); 61*0b57cec5SDimitry Andric for (auto *D : TU->decls()) { 62*0b57cec5SDimitry Andric // Don't re-import __va_list_tag, __builtin_va_list. 63*0b57cec5SDimitry Andric if (const auto *ND = dyn_cast<NamedDecl>(D)) 64*0b57cec5SDimitry Andric if (IdentifierInfo *II = ND->getIdentifier()) 65*0b57cec5SDimitry Andric if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) 66*0b57cec5SDimitry Andric continue; 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric llvm::Expected<Decl *> ToDOrError = Importer.Import(D); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric if (ToDOrError) { 71*0b57cec5SDimitry Andric DeclGroupRef DGR(*ToDOrError); 72*0b57cec5SDimitry Andric CI.getASTConsumer().HandleTopLevelDecl(DGR); 73*0b57cec5SDimitry Andric } else { 74*0b57cec5SDimitry Andric llvm::consumeError(ToDOrError.takeError()); 75*0b57cec5SDimitry Andric } 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric } 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric AdaptedAction->ExecuteAction(); 80*0b57cec5SDimitry Andric CI.getDiagnostics().getClient()->EndSourceFile(); 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric void ASTMergeAction::EndSourceFileAction() { 84*0b57cec5SDimitry Andric return AdaptedAction->EndSourceFileAction(); 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric ASTMergeAction::ASTMergeAction(std::unique_ptr<FrontendAction> adaptedAction, 88*0b57cec5SDimitry Andric ArrayRef<std::string> ASTFiles) 89*0b57cec5SDimitry Andric : AdaptedAction(std::move(adaptedAction)), ASTFiles(ASTFiles.begin(), ASTFiles.end()) { 90*0b57cec5SDimitry Andric assert(AdaptedAction && "ASTMergeAction needs an action to adapt"); 91*0b57cec5SDimitry Andric } 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric ASTMergeAction::~ASTMergeAction() { 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric bool ASTMergeAction::usesPreprocessorOnly() const { 97*0b57cec5SDimitry Andric return AdaptedAction->usesPreprocessorOnly(); 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric TranslationUnitKind ASTMergeAction::getTranslationUnitKind() { 101*0b57cec5SDimitry Andric return AdaptedAction->getTranslationUnitKind(); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric bool ASTMergeAction::hasPCHSupport() const { 105*0b57cec5SDimitry Andric return AdaptedAction->hasPCHSupport(); 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric bool ASTMergeAction::hasASTFileSupport() const { 109*0b57cec5SDimitry Andric return AdaptedAction->hasASTFileSupport(); 110*0b57cec5SDimitry Andric } 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric bool ASTMergeAction::hasCodeCompletionSupport() const { 113*0b57cec5SDimitry Andric return AdaptedAction->hasCodeCompletionSupport(); 114*0b57cec5SDimitry Andric } 115