void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Stmt::EnableStatistics(); } // Also turn on collection of stats inside of the Sema object. bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); // Initialize the template instantiation observer chain. // FIXME: See note on "finalize" below. initialize(S.TemplateInstCallbacks, S); ASTConsumer *Consumer = &S.getASTConsumer(); std::unique_ptr<Parser> ParseOP( new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> CleanupPrettyStack(llvm::SavePrettyStackState()); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Parser> CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; AtEOF = P.ParseTopLevelDecl(ADecl)) { // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) return; } // Process any TopLevelDecls generated by #pragma weak. for (Decl *D : S.WeakTopLevelDecls()) Consumer->HandleTopLevelDecl(DeclGroupRef(D)); Consumer->HandleTranslationUnit(S.getASTContext()); // Finalize the template instantiation observer chain. // FIXME: This (and init.) should be done in the Sema class, but because // Sema does not have a reliable "Finalize" function (it has a // destructor, but it is not guaranteed to be called ("-disable-free")). // So, do the initialization above and do the finalization here: finalize(S.TemplateInstCallbacks, S); std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); } }
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Stmt::EnableStatistics(); } // Also turn on collection of stats inside of the Sema object. bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); ASTConsumer *Consumer = &S.getASTConsumer(); OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Parser> CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); S.Initialize(); // C11 6.9p1 says translation units must have at least one top-level // declaration. C++ doesn't have this restriction. We also don't want to // complain if we have a precompiled header, although technically if the PCH // is empty we should still emit the (pedantic) diagnostic. Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); if (P.ParseTopLevelDecl(ADecl)) { if (!External && !S.getLangOpts().CPlusPlus) P.Diag(diag::ext_empty_translation_unit); } else { do { // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) return; } while (!P.ParseTopLevelDecl(ADecl)); } // Process any TopLevelDecls generated by #pragma weak. for (SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(), E = S.WeakTopLevelDecls().end(); I != E; ++I) Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); Consumer->HandleTranslationUnit(S.getASTContext()); std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); } }
// Add the input to the memory buffer, parse it, and add it to the AST. IncrementalParser::EParseResult IncrementalParser::ParseInternal(llvm::StringRef input) { if (input.empty()) return IncrementalParser::kSuccess; Sema& S = getCI()->getSema(); const CompilationOptions& CO = m_Consumer->getTransaction()->getCompilationOpts(); assert(!(S.getLangOpts().Modules && CO.CodeGenerationForModule) && "CodeGenerationForModule to be removed once PCMs are available!"); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S); Preprocessor& PP = m_CI->getPreprocessor(); if (!PP.getCurrentLexer()) { PP.EnterSourceFile(m_CI->getSourceManager().getMainFileID(), 0, SourceLocation()); } assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?"); PP.enableIncrementalProcessing(); smallstream source_name; source_name << "input_line_" << (m_MemoryBuffers.size() + 1); // Create an uninitialized memory buffer, copy code in and append "\n" size_t InputSize = input.size(); // don't include trailing 0 // MemBuffer size should *not* include terminating zero std::unique_ptr<llvm::MemoryBuffer> MB(llvm::MemoryBuffer::getNewUninitMemBuffer(InputSize + 1, source_name.str())); char* MBStart = const_cast<char*>(MB->getBufferStart()); memcpy(MBStart, input.data(), InputSize); MBStart[InputSize] = '\n'; SourceManager& SM = getCI()->getSourceManager(); // Create SourceLocation, which will allow clang to order the overload // candidates for example SourceLocation NewLoc = getLastMemoryBufferEndLoc().getLocWithOffset(1); llvm::MemoryBuffer* MBNonOwn = MB.get(); // Create FileID for the current buffer. FileID FID; // Create FileEntry and FileID for the current buffer. // Enabling the completion point only works on FileEntries. const clang::FileEntry* FE = SM.getFileManager().getVirtualFile(source_name.str(), InputSize, 0 /* mod time*/); SM.overrideFileContents(FE, std::move(MB)); FID = SM.createFileID(FE, NewLoc, SrcMgr::C_User); if (CO.CodeCompletionOffset != -1) { // The completion point is set one a 1-based line/column numbering. // It relies on the implementation to account for the wrapper extra line. PP.SetCodeCompletionPoint(FE, 1/* start point 1-based line*/, CO.CodeCompletionOffset+1/* 1-based column*/); } m_MemoryBuffers.push_back(std::make_pair(MBNonOwn, FID)); // NewLoc only used for diags. PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc); m_Consumer->getTransaction()->setBufferFID(FID); DiagnosticsEngine& Diags = getCI()->getDiagnostics(); FilteringDiagConsumer::RAAI RAAITmp(*m_DiagConsumer, CO.IgnorePromptDiags); DiagnosticErrorTrap Trap(Diags); Sema::SavePendingInstantiationsRAII SavedPendingInstantiations(S); Parser::DeclGroupPtrTy ADecl; while (!m_Parser->ParseTopLevelDecl(ADecl)) { // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (Trap.hasErrorOccurred()) m_Consumer->getTransaction()->setIssuedDiags(Transaction::kErrors); if (ADecl) m_Consumer->HandleTopLevelDecl(ADecl.get()); }; // If never entered the while block, there's a chance an error occured if (Trap.hasErrorOccurred()) m_Consumer->getTransaction()->setIssuedDiags(Transaction::kErrors); if (CO.CodeCompletionOffset != -1) { assert((int)SM.getFileOffset(PP.getCodeCompletionLoc()) == CO.CodeCompletionOffset && "Completion point wrongly set!"); assert(PP.isCodeCompletionReached() && "Code completion set but not reached!"); // Let's ignore this transaction: m_Consumer->getTransaction()->setIssuedDiags(Transaction::kErrors); return kSuccess; } #ifdef LLVM_ON_WIN32 // Microsoft-specific: // Late parsed templates can leave unswallowed "macro"-like tokens. // They will seriously confuse the Parser when entering the next // source file. So lex until we are EOF. Token Tok; do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); #endif #ifndef NDEBUG Token AssertTok; PP.Lex(AssertTok); assert(AssertTok.is(tok::eof) && "Lexer must be EOF when starting incremental parse!"); #endif // Process any TopLevelDecls generated by #pragma weak. for (llvm::SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(), E = S.WeakTopLevelDecls().end(); I != E; ++I) { m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); } if (m_Consumer->getTransaction()->getIssuedDiags() == Transaction::kErrors) return kFailed; else if (Diags.getNumWarnings()) return kSuccessWithWarnings; return kSuccess; }