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