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