1//===-- ASTMerge.cpp - AST Merging Frontent 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/Frontend/ASTUnit.h" 10#include "clang/AST/ASTContext.h" 11#include "clang/AST/ASTDiagnostic.h" 12#include "clang/AST/ASTImporter.h" 13#include "clang/Basic/Diagnostic.h" 14#include "clang/Frontend/CompilerInstance.h" 15#include "clang/Frontend/FrontendActions.h" 16 17using namespace clang; 18 19ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, 20 StringRef InFile) { 21 return AdaptedAction->CreateASTConsumer(CI, InFile); 22} 23 24bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI, 25 StringRef Filename) { 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, Filename); 32} 33 34void ASTMergeAction::ExecuteAction() { 35 CompilerInstance &CI = getCompilerInstance(); 36 CI.getDiagnostics().getClient()->BeginSourceFile( 37 CI.getASTContext().getLangOpts()); 38 CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 39 &CI.getASTContext()); 40 IntrusiveRefCntPtr<DiagnosticIDs> 41 DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); 42 for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { 43 IntrusiveRefCntPtr<DiagnosticsEngine> 44 Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(), 45 new ForwardingDiagnosticConsumer( 46 *CI.getDiagnostics().getClient()), 47 /*ShouldOwnClient=*/true)); 48 ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, 49 CI.getFileSystemOpts(), false); 50 if (!Unit) 51 continue; 52 53 ASTImporter Importer(CI.getASTContext(), 54 CI.getFileManager(), 55 Unit->getASTContext(), 56 Unit->getFileManager(), 57 /*MinimalImport=*/false); 58 59 TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); 60 for (auto *D : TU->decls()) { 61 // Don't re-import __va_list_tag, __builtin_va_list. 62 if (const auto *ND = dyn_cast<NamedDecl>(D)) 63 if (IdentifierInfo *II = ND->getIdentifier()) 64 if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) 65 continue; 66 67 Importer.Import(D); 68 } 69 70 delete Unit; 71 } 72 73 AdaptedAction->ExecuteAction(); 74 CI.getDiagnostics().getClient()->EndSourceFile(); 75} 76 77void ASTMergeAction::EndSourceFileAction() { 78 return AdaptedAction->EndSourceFileAction(); 79} 80 81ASTMergeAction::ASTMergeAction(FrontendAction *AdaptedAction, 82 ArrayRef<std::string> ASTFiles) 83 : AdaptedAction(AdaptedAction), ASTFiles(ASTFiles.begin(), ASTFiles.end()) { 84 assert(AdaptedAction && "ASTMergeAction needs an action to adapt"); 85} 86 87ASTMergeAction::~ASTMergeAction() { 88 delete AdaptedAction; 89} 90 91bool ASTMergeAction::usesPreprocessorOnly() const { 92 return AdaptedAction->usesPreprocessorOnly(); 93} 94 95TranslationUnitKind ASTMergeAction::getTranslationUnitKind() { 96 return AdaptedAction->getTranslationUnitKind(); 97} 98 99bool ASTMergeAction::hasPCHSupport() const { 100 return AdaptedAction->hasPCHSupport(); 101} 102 103bool ASTMergeAction::hasASTFileSupport() const { 104 return AdaptedAction->hasASTFileSupport(); 105} 106 107bool ASTMergeAction::hasCodeCompletionSupport() const { 108 return AdaptedAction->hasCodeCompletionSupport(); 109} 110