// 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(); assert(!(S.getLangOpts().Modules && m_Consumer->getTransaction()->getCompilationOpts() .CodeGenerationForModule) && "CodeGenerationForModule should be removed once modules 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(); std::ostringstream 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 llvm::MemoryBuffer* MB = llvm::MemoryBuffer::getNewUninitMemBuffer(InputSize + 1, source_name.str()); char* MBStart = const_cast<char*>(MB->getBufferStart()); memcpy(MBStart, input.data(), InputSize); memcpy(MBStart + InputSize, "\n", 2); m_MemoryBuffers.push_back(MB); SourceManager& SM = getCI()->getSourceManager(); // Create SourceLocation, which will allow clang to order the overload // candidates for example SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID); NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffers.size() + 1); // Create FileID for the current buffer FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffers.back(), SrcMgr::C_User, /*LoadedID*/0, /*LoadedOffset*/0, NewLoc); PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc); 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 (ADecl) m_Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>()); }; // 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)); } DiagnosticsEngine& Diag = S.getDiagnostics(); if (Diag.hasErrorOccurred()) return IncrementalParser::kFailed; else if (Diag.getNumWarnings()) return IncrementalParser::kSuccessWithWarnings; return IncrementalParser::kSuccess; }
// 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; }