static void clang_indexTranslationUnit_Impl(void *UserData) { IndexTranslationUnitInfo *ITUI = static_cast<IndexTranslationUnitInfo*>(UserData); CXTranslationUnit TU = ITUI->TU; CXClientData client_data = ITUI->client_data; IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; unsigned index_callbacks_size = ITUI->index_callbacks_size; unsigned index_options = ITUI->index_options; ITUI->result = 1; // init as error. if (!TU) return; if (!client_index_callbacks || index_callbacks_size == 0) return; CIndexer *CXXIdx = (CIndexer*)TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) setThreadBackgroundPriority(); IndexerCallbacks CB; memset(&CB, 0, sizeof(CB)); unsigned ClientCBSize = index_callbacks_size < sizeof(CB) ? index_callbacks_size : sizeof(CB); memcpy(&CB, client_index_callbacks, ClientCBSize); OwningPtr<IndexingContext> IndexCtx; IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext> IndexCtxCleanup(IndexCtx.get()); OwningPtr<IndexingConsumer> IndexConsumer; IndexConsumer.reset(new IndexingConsumer(*IndexCtx)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer> IndexConsumerCleanup(IndexConsumer.get()); ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData); if (!Unit) return; ASTUnit::ConcurrencyCheck Check(*Unit); FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) IndexCtx->enteredMainFile(0); else IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); IndexConsumer->Initialize(Unit->getASTContext()); indexPreprocessingRecord(*Unit, *IndexCtx); indexTranslationUnit(*Unit, *IndexCtx); indexDiagnostics(TU, *IndexCtx); ITUI->result = 0; }
static CXErrorCode clang_indexTranslationUnit_Impl( CXIndexAction idxAction, CXClientData client_data, IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, unsigned index_options, CXTranslationUnit TU) { // Check arguments. if (isNotUsableTU(TU)) { LOG_BAD_TU(TU); return CXError_InvalidArguments; } if (!client_index_callbacks || index_callbacks_size == 0) { return CXError_InvalidArguments; } CIndexer *CXXIdx = TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) setThreadBackgroundPriority(); IndexerCallbacks CB; memset(&CB, 0, sizeof(CB)); unsigned ClientCBSize = index_callbacks_size < sizeof(CB) ? index_callbacks_size : sizeof(CB); memcpy(&CB, client_index_callbacks, ClientCBSize); auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options, TU); ASTUnit *Unit = cxtu::getASTUnit(TU); if (!Unit) return CXError_Failure; ASTUnit::ConcurrencyCheck Check(*Unit); if (const FileEntry *PCHFile = Unit->getPCHFile()) DataConsumer->importedPCH(PCHFile); FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) DataConsumer->enteredMainFile(nullptr); else DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); DataConsumer->setASTContext(Unit->getASTContext()); DataConsumer->startedTranslationUnit(); indexPreprocessingRecord(*Unit, *DataConsumer); indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); DataConsumer->indexDiagnostics(); return CXError_Success; }
void ASTMergeAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); CI.getDiagnostics().getClient()->BeginSourceFile( CI.getASTContext().getLangOpts()); CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &CI.getASTContext()); IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { IntrusiveRefCntPtr<DiagnosticsEngine> Diags(new DiagnosticsEngine(DiagIDs, &CI.getDiagnosticOpts(), new ForwardingDiagnosticConsumer( *CI.getDiagnostics().getClient()), /*ShouldOwnClient=*/true)); ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, CI.getFileSystemOpts(), false); if (!Unit) continue; ASTImporter Importer(CI.getASTContext(), CI.getFileManager(), Unit->getASTContext(), Unit->getFileManager(), /*MinimalImport=*/false); TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); D != DEnd; ++D) { // Don't re-import __va_list_tag, __builtin_va_list. if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) if (IdentifierInfo *II = ND->getIdentifier()) if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) continue; Importer.Import(*D); } delete Unit; } AdaptedAction->ExecuteAction(); CI.getDiagnostics().getClient()->EndSourceFile(); }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. if (Input.getKind() == IK_AST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && "This action does not have AST file support!"); IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts()); if (!AST) goto failure; setCurrentInput(Input, AST); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); if (!CI.hasASTConsumer()) goto failure; return true; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); // IR files bypass the rest of initialization. if (Input.getKind() == IK_LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; return true; } // If the implicit PCH include is actually a directory, rather than // a single file, search for a suitable PCH file in that directory. if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { FileManager &FileMgr = CI.getFileManager(); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); StringRef PCHInclude = PPOpts.ImplicitPCHInclude; if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { llvm::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts())) { PPOpts.ImplicitPCHInclude = Dir->path(); Found = true; break; } } if (!Found) { CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; return true; } } } // Set up the preprocessor. CI.createPreprocessor(); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { CI.createASTContext(); OwningPtr<ASTConsumer> Consumer( CreateWrappedASTConsumer(CI, InputFile)); if (!Consumer) goto failure; CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. OwningPtr<ExternalASTSource> source; source.reset(ChainedIncludesSource::create(CI)); if (!source) goto failure; CI.setModuleManager(static_cast<ASTReader*>( &static_cast<ChainedIncludesSource*>(source.get())->getFinalReader())); CI.getASTContext().setExternalSource(source); } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = Consumer->GetASTDeserializationListener(); if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) DeserialListener = new DeserializedDeclsDumper(DeserialListener); if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, DeserialListener); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } CI.setASTConsumer(Consumer.take()); if (!CI.hasASTConsumer()) goto failure; } // Initialize built-in info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); } // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { OwningPtr<ExternalASTSource> Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.setASTContext(0); CI.setPreprocessor(0); CI.setSourceManager(0); CI.setFileManager(0); } if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); setCurrentInput(FrontendInputFile()); setCompilerInstance(0); return false; }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename, bool IsAST) { assert(!Instance && "Already processing a source file!"); assert(!Filename.empty() && "Unexpected empty filename!"); setCurrentFile(Filename); setCompilerInstance(&CI); // AST files follow a very different path, since they share objects via the // AST unit. if (IsAST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTSupport() && "This action does not have AST support!"); llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); std::string Error; ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, Diags); if (!AST) goto failure; setCurrentFile(Filename, AST); // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; /// Create the AST consumer. CI.setASTConsumer(CreateASTConsumer(CI, Filename)); if (!CI.hasASTConsumer()) goto failure; return true; } // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; /// Create the AST context and consumer unless this is a preprocessor only /// action. if (!usesPreprocessorOnly()) { CI.createASTContext(); CI.setASTConsumer(CreateASTConsumer(CI, Filename)); if (!CI.hasASTConsumer()) goto failure; /// Use PCH? if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { assert(hasPCHSupport() && "This action does not have PCH support!"); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude); if (!CI.getASTContext().getExternalSource()) goto failure; } } // Initialize builtin info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOptions().NoBuiltin); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.takeASTContext(); CI.takePreprocessor(); CI.takeSourceManager(); CI.takeFileManager(); } CI.getDiagnosticClient().EndSourceFile(); setCurrentFile(""); setCompilerInstance(0); return false; }
static void clang_indexTranslationUnit_Impl(void *UserData) { IndexTranslationUnitInfo *ITUI = static_cast<IndexTranslationUnitInfo*>(UserData); CXTranslationUnit TU = ITUI->TU; CXClientData client_data = ITUI->client_data; IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; unsigned index_callbacks_size = ITUI->index_callbacks_size; unsigned index_options = ITUI->index_options; // Set up the initial return value. ITUI->result = CXError_Failure; // Check arguments. if (isNotUsableTU(TU)) { LOG_BAD_TU(TU); ITUI->result = CXError_InvalidArguments; return; } if (!client_index_callbacks || index_callbacks_size == 0) { ITUI->result = CXError_InvalidArguments; return; } CIndexer *CXXIdx = TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) setThreadBackgroundPriority(); IndexerCallbacks CB; memset(&CB, 0, sizeof(CB)); unsigned ClientCBSize = index_callbacks_size < sizeof(CB) ? index_callbacks_size : sizeof(CB); memcpy(&CB, client_index_callbacks, ClientCBSize); std::unique_ptr<IndexingContext> IndexCtx; IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext> IndexCtxCleanup(IndexCtx.get()); std::unique_ptr<IndexingConsumer> IndexConsumer; IndexConsumer.reset(new IndexingConsumer(*IndexCtx, nullptr)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer> IndexConsumerCleanup(IndexConsumer.get()); ASTUnit *Unit = cxtu::getASTUnit(TU); if (!Unit) return; ASTUnit::ConcurrencyCheck Check(*Unit); if (const FileEntry *PCHFile = Unit->getPCHFile()) IndexCtx->importedPCH(PCHFile); FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) IndexCtx->enteredMainFile(nullptr); else IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); IndexConsumer->Initialize(Unit->getASTContext()); indexPreprocessingRecord(*Unit, *IndexCtx); indexTranslationUnit(*Unit, *IndexCtx); indexDiagnostics(TU, *IndexCtx); ITUI->result = CXError_Success; }
static CXCodeCompleteResults * clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, unsigned complete_line, unsigned complete_column, ArrayRef<CXUnsavedFile> unsaved_files, unsigned options) { bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments; bool SkipPreamble = options & CXCodeComplete_SkipPreamble; bool IncludeFixIts = options & CXCodeComplete_IncludeCompletionsWithFixIts; #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime(); #endif #endif bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr; if (cxtu::isNotUsableTU(TU)) { LOG_BAD_TU(TU); return nullptr; } ASTUnit *AST = cxtu::getASTUnit(TU); if (!AST) return nullptr; CIndexer *CXXIdx = TU->CIdx; if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing)) setThreadBackgroundPriority(); ASTUnit::ConcurrencyCheck Check(*AST); // Perform the remapping of source files. SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles; for (auto &UF : unsaved_files) { std::unique_ptr<llvm::MemoryBuffer> MB = llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release())); } if (EnableLogging) { // FIXME: Add logging. } // Parse the resulting source file to find code-completion results. AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults( &AST->getFileManager()); Results->Results = nullptr; Results->NumResults = 0; // Create a code-completion consumer to capture the results. CodeCompleteOptions Opts; Opts.IncludeBriefComments = IncludeBriefComments; Opts.LoadExternal = !SkipPreamble; Opts.IncludeFixIts = IncludeFixIts; CaptureCompletionResults Capture(Opts, *Results, &TU); // Perform completion. std::vector<const char *> CArgs; for (const auto &Arg : TU->Arguments) CArgs.push_back(Arg.c_str()); std::string CompletionInvocation = llvm::formatv("-code-completion-at={0}:{1}:{2}", complete_filename, complete_line, complete_column) .str(); LibclangInvocationReporter InvocationReporter( *CXXIdx, LibclangInvocationReporter::OperationKind::CompletionOperation, TU->ParsingOptions, CArgs, CompletionInvocation, unsaved_files); AST->CodeComplete(complete_filename, complete_line, complete_column, RemappedFiles, (options & CXCodeComplete_IncludeMacros), (options & CXCodeComplete_IncludeCodePatterns), IncludeBriefComments, Capture, CXXIdx->getPCHContainerOperations(), *Results->Diag, Results->LangOpts, *Results->SourceMgr, *Results->FileMgr, Results->Diagnostics, Results->TemporaryBuffers); Results->DiagnosticsWrappers.resize(Results->Diagnostics.size()); // Keep a reference to the allocator used for cached global completions, so // that we can be sure that the memory used by our code completion strings // doesn't get freed due to subsequent reparses (while the code completion // results are still active). Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator(); #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime(); SmallString<256> LogResult; llvm::raw_svector_ostream os(LogResult); // Figure out the language and whether or not it uses PCH. const char *lang = 0; bool usesPCH = false; for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); I != E; ++I) { if (*I == 0) continue; if (strcmp(*I, "-x") == 0) { if (I + 1 != E) { lang = *(++I); continue; } } else if (strcmp(*I, "-include") == 0) { if (I+1 != E) { const char *arg = *(++I); SmallString<512> pchName; { llvm::raw_svector_ostream os(pchName); os << arg << ".pth"; } pchName.push_back('\0'); struct stat stat_results; if (stat(pchName.str().c_str(), &stat_results) == 0) usesPCH = true; continue; } } } os << "{ "; os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime()); os << ", \"numRes\": " << Results->NumResults; os << ", \"diags\": " << Results->Diagnostics.size(); os << ", \"pch\": " << (usesPCH ? "true" : "false"); os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"'; const char *name = getlogin(); os << ", \"user\": \"" << (name ? name : "unknown") << '"'; os << ", \"clangVer\": \"" << getClangFullVersion() << '"'; os << " }"; StringRef res = os.str(); if (res.size() > 0) { do { // Setup the UDP socket. struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT); if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER, &servaddr.sin_addr) <= 0) break; int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) break; sendto(sockfd, res.data(), res.size(), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); close(sockfd); } while (false); } #endif #endif return Results; }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename, InputKind InputKind) { assert(!Instance && "Already processing a source file!"); assert(!Filename.empty() && "Unexpected empty filename!"); setCurrentFile(Filename, InputKind); setCompilerInstance(&CI); if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. if (InputKind == IK_AST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && "This action does not have AST file support!"); llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); std::string Error; ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags, CI.getFileSystemOpts()); if (!AST) goto failure; setCurrentFile(Filename, InputKind, AST); // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; /// Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, Filename)); if (!CI.hasASTConsumer()) goto failure; return true; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); // IR files bypass the rest of initialization. if (InputKind == IK_LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; return true; } // Set up the preprocessor. CI.createPreprocessor(); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); // Initialize the action. if (!BeginSourceFileAction(CI, Filename)) goto failure; /// Create the AST context and consumer unless this is a preprocessor only /// action. if (!usesPreprocessorOnly()) { CI.createASTContext(); llvm::OwningPtr<ASTConsumer> Consumer( CreateWrappedASTConsumer(CI, Filename)); if (!Consumer) goto failure; CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. llvm::OwningPtr<ExternalASTSource> source; source.reset(ChainedIncludesSource::create(CI)); if (!source) goto failure; CI.getASTContext().setExternalSource(source); } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = CI.getInvocation().getFrontendOpts().ChainedPCH ? Consumer->GetASTDeserializationListener() : 0; if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) DeserialListener = new DeserializedDeclsDumper(DeserialListener); if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, DeserialListener); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, CI.getPreprocessorOpts().DisableStatCache, DeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } CI.setASTConsumer(Consumer.take()); if (!CI.hasASTConsumer()) goto failure; } // Initialize builtin info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOptions()); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.setASTContext(0); CI.setPreprocessor(0); CI.setSourceManager(0); CI.setFileManager(0); } CI.getDiagnosticClient().EndSourceFile(); setCurrentFile("", IK_None); setCompilerInstance(0); return false; }