10b57cec5SDimitry Andric //===-- ASTMerge.cpp - AST Merging Frontend Action --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric #include "clang/Frontend/ASTUnit.h" 90b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 100b57cec5SDimitry Andric #include "clang/AST/ASTDiagnostic.h" 110b57cec5SDimitry Andric #include "clang/AST/ASTImporter.h" 120b57cec5SDimitry Andric #include "clang/AST/ASTImporterSharedState.h" 130b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 140b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 150b57cec5SDimitry Andric #include "clang/Frontend/FrontendActions.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace clang; 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 200b57cec5SDimitry Andric ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 210b57cec5SDimitry Andric return AdaptedAction->CreateASTConsumer(CI, InFile); 220b57cec5SDimitry Andric } 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI) { 250b57cec5SDimitry Andric // FIXME: This is a hack. We need a better way to communicate the 260b57cec5SDimitry Andric // AST file, compiler instance, and file name than member variables 270b57cec5SDimitry Andric // of FrontendAction. 280b57cec5SDimitry Andric AdaptedAction->setCurrentInput(getCurrentInput(), takeCurrentASTUnit()); 290b57cec5SDimitry Andric AdaptedAction->setCompilerInstance(&CI); 300b57cec5SDimitry Andric return AdaptedAction->BeginSourceFileAction(CI); 310b57cec5SDimitry Andric } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric void ASTMergeAction::ExecuteAction() { 340b57cec5SDimitry Andric CompilerInstance &CI = getCompilerInstance(); 350b57cec5SDimitry Andric CI.getDiagnostics().getClient()->BeginSourceFile( 360b57cec5SDimitry Andric CI.getASTContext().getLangOpts()); 370b57cec5SDimitry Andric CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 380b57cec5SDimitry Andric &CI.getASTContext()); 390b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticIDs> 400b57cec5SDimitry Andric DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); 410b57cec5SDimitry Andric auto SharedState = std::make_shared<ASTImporterSharedState>( 420b57cec5SDimitry Andric *CI.getASTContext().getTranslationUnitDecl()); 430b57cec5SDimitry Andric for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { 440b57cec5SDimitry Andric IntrusiveRefCntPtr<DiagnosticsEngine> 450b57cec5SDimitry Andric Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(), 460b57cec5SDimitry Andric new ForwardingDiagnosticConsumer( 470b57cec5SDimitry Andric *CI.getDiagnostics().getClient()), 480b57cec5SDimitry Andric /*ShouldOwnClient=*/true)); 490b57cec5SDimitry Andric std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile( 500b57cec5SDimitry Andric ASTFiles[I], CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags, 51*5f757f3fSDimitry Andric CI.getFileSystemOpts(), CI.getHeaderSearchOptsPtr()); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric if (!Unit) 540b57cec5SDimitry Andric continue; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric ASTImporter Importer(CI.getASTContext(), CI.getFileManager(), 570b57cec5SDimitry Andric Unit->getASTContext(), Unit->getFileManager(), 580b57cec5SDimitry Andric /*MinimalImport=*/false, SharedState); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); 610b57cec5SDimitry Andric for (auto *D : TU->decls()) { 620b57cec5SDimitry Andric // Don't re-import __va_list_tag, __builtin_va_list. 630b57cec5SDimitry Andric if (const auto *ND = dyn_cast<NamedDecl>(D)) 640b57cec5SDimitry Andric if (IdentifierInfo *II = ND->getIdentifier()) 650b57cec5SDimitry Andric if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) 660b57cec5SDimitry Andric continue; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric llvm::Expected<Decl *> ToDOrError = Importer.Import(D); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric if (ToDOrError) { 710b57cec5SDimitry Andric DeclGroupRef DGR(*ToDOrError); 720b57cec5SDimitry Andric CI.getASTConsumer().HandleTopLevelDecl(DGR); 730b57cec5SDimitry Andric } else { 740b57cec5SDimitry Andric llvm::consumeError(ToDOrError.takeError()); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric AdaptedAction->ExecuteAction(); 800b57cec5SDimitry Andric CI.getDiagnostics().getClient()->EndSourceFile(); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric void ASTMergeAction::EndSourceFileAction() { 840b57cec5SDimitry Andric return AdaptedAction->EndSourceFileAction(); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric ASTMergeAction::ASTMergeAction(std::unique_ptr<FrontendAction> adaptedAction, 880b57cec5SDimitry Andric ArrayRef<std::string> ASTFiles) 890b57cec5SDimitry Andric : AdaptedAction(std::move(adaptedAction)), ASTFiles(ASTFiles.begin(), ASTFiles.end()) { 900b57cec5SDimitry Andric assert(AdaptedAction && "ASTMergeAction needs an action to adapt"); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric ASTMergeAction::~ASTMergeAction() { 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric bool ASTMergeAction::usesPreprocessorOnly() const { 970b57cec5SDimitry Andric return AdaptedAction->usesPreprocessorOnly(); 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric TranslationUnitKind ASTMergeAction::getTranslationUnitKind() { 1010b57cec5SDimitry Andric return AdaptedAction->getTranslationUnitKind(); 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric bool ASTMergeAction::hasPCHSupport() const { 1050b57cec5SDimitry Andric return AdaptedAction->hasPCHSupport(); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric bool ASTMergeAction::hasASTFileSupport() const { 1090b57cec5SDimitry Andric return AdaptedAction->hasASTFileSupport(); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric bool ASTMergeAction::hasCodeCompletionSupport() const { 1130b57cec5SDimitry Andric return AdaptedAction->hasCodeCompletionSupport(); 1140b57cec5SDimitry Andric } 115