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/Frontend/CompilerInstance.h" 11 #include "clang/Frontend/FrontendActions.h" 12 #include "clang/AST/ASTContext.h" 13 #include "clang/AST/ASTDiagnostic.h" 14 #include "clang/AST/ASTImporter.h" 15 16 using namespace clang; 17 18 ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, 19 llvm::StringRef InFile) { 20 return AdaptedAction->CreateASTConsumer(CI, InFile); 21 } 22 23 bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI, 24 llvm::StringRef Filename) { 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->setCurrentFile(getCurrentFile(), takeCurrentASTUnit()); 29 AdaptedAction->setCompilerInstance(&CI); 30 return AdaptedAction->BeginSourceFileAction(CI, Filename); 31 } 32 33 void ASTMergeAction::ExecuteAction() { 34 CompilerInstance &CI = getCompilerInstance(); 35 CI.getDiagnostics().getClient()->BeginSourceFile( 36 CI.getASTContext().getLangOptions()); 37 CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 38 &CI.getASTContext()); 39 for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { 40 Diagnostic ASTDiags(CI.getDiagnostics().getClient()); 41 42 ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], ASTDiags, 43 false, true); 44 if (!Unit) 45 continue; 46 47 ASTDiags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 48 &Unit->getASTContext()); 49 ASTImporter Importer(CI.getASTContext(), 50 CI.getFileManager(), 51 CI.getDiagnostics(), 52 Unit->getASTContext(), 53 Unit->getFileManager(), 54 ASTDiags); 55 56 TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); 57 for (DeclContext::decl_iterator D = TU->decls_begin(), 58 DEnd = TU->decls_end(); 59 D != DEnd; ++D) { 60 // FIXME: We only merge variables whose names start with x and functions 61 // whose names start with 'f'. Why would anyone want anything else? 62 if (VarDecl *VD = dyn_cast<VarDecl>(*D)) { 63 if (VD->getIdentifier() && 64 *VD->getIdentifier()->getNameStart() == 'x') { 65 Decl *Merged = Importer.Import(VD); 66 (void)Merged; 67 } 68 } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) { 69 if (FD->getIdentifier() && 70 *FD->getIdentifier()->getNameStart() == 'f') { 71 Decl *Merged = Importer.Import(FD); 72 (void)Merged; 73 } 74 } 75 } 76 77 delete Unit; 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(FrontendAction *AdaptedAction, 89 std::string *ASTFiles, unsigned NumASTFiles) 90 : AdaptedAction(AdaptedAction), ASTFiles(ASTFiles, ASTFiles + NumASTFiles) { 91 assert(AdaptedAction && "ASTMergeAction needs an action to adapt"); 92 } 93 94 ASTMergeAction::~ASTMergeAction() { 95 delete AdaptedAction; 96 } 97 98 bool ASTMergeAction::usesPreprocessorOnly() const { 99 return AdaptedAction->usesPreprocessorOnly(); 100 } 101 102 bool ASTMergeAction::usesCompleteTranslationUnit() { 103 return AdaptedAction->usesCompleteTranslationUnit(); 104 } 105 106 bool ASTMergeAction::hasPCHSupport() const { 107 return AdaptedAction->hasPCHSupport(); 108 } 109 110 bool ASTMergeAction::hasASTSupport() const { 111 return AdaptedAction->hasASTSupport(); 112 } 113 114 bool ASTMergeAction::hasCodeCompletionSupport() const { 115 return AdaptedAction->hasCodeCompletionSupport(); 116 } 117