2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Axel Naumann <axel@cern.ch>
2014-01-07 14:08:37 +04:00
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
# include "IncrementalParser.h"
2014-03-27 20:30:09 +04:00
2016-09-15 21:55:14 +03:00
# include "ASTTransformer.h"
2013-02-27 19:28:38 +04:00
# include "AutoSynthesizer.h"
2015-02-11 23:58:21 +03:00
# include "BackendPasses.h"
2013-10-24 20:54:06 +04:00
# include "CheckEmptyTransactionTransformer.h"
2015-02-18 12:44:12 +03:00
# include "ClingPragmas.h"
2012-09-05 13:37:39 +04:00
# include "DeclCollector.h"
# include "DeclExtractor.h"
# include "DynamicLookup.h"
2018-03-20 18:50:02 +03:00
# include "IncrementalCUDADeviceCompiler.h"
2015-01-07 12:22:52 +03:00
# include "IncrementalExecutor.h"
2013-07-15 00:35:00 +04:00
# include "NullDerefProtectionTransformer.h"
2013-08-01 14:27:40 +04:00
# include "TransactionPool.h"
2016-09-15 21:55:14 +03:00
# include "ValueExtractionSynthesizer.h"
2012-09-05 13:37:39 +04:00
# include "ValuePrinterSynthesizer.h"
# include "cling/Interpreter/CIFactory.h"
# include "cling/Interpreter/Interpreter.h"
2012-10-02 14:30:25 +04:00
# include "cling/Interpreter/InterpreterCallbacks.h"
2012-10-02 14:34:22 +04:00
# include "cling/Interpreter/Transaction.h"
2017-01-28 04:41:30 +03:00
# include "cling/Utils/Diagnostics.h"
2016-09-10 22:04:39 +03:00
# include "cling/Utils/Output.h"
2012-09-05 13:37:39 +04:00
# include "clang/AST/ASTContext.h"
2016-09-15 21:55:14 +03:00
# include "clang/AST/Attr.h"
2012-09-05 13:37:39 +04:00
# include "clang/AST/Decl.h"
# include "clang/AST/DeclGroup.h"
2013-03-01 19:15:31 +04:00
# include "clang/AST/RecursiveASTVisitor.h"
2017-01-09 18:32:49 +03:00
# include "clang/Basic/Diagnostic.h"
2012-09-05 13:37:39 +04:00
# include "clang/Basic/FileManager.h"
# include "clang/CodeGen/ModuleBuilder.h"
# include "clang/Frontend/CompilerInstance.h"
2018-07-26 13:39:04 +03:00
# include "clang/Frontend/FrontendDiagnostic.h"
# include "clang/Frontend/FrontendPluginRegistry.h"
# include "clang/Frontend/MultiplexConsumer.h"
2016-09-15 21:55:14 +03:00
# include "clang/Lex/Preprocessor.h"
2017-05-18 16:16:30 +03:00
# include "clang/Lex/PreprocessorOptions.h"
2016-09-15 21:55:14 +03:00
# include "clang/Parse/Parser.h"
2014-12-02 19:43:18 +03:00
# include "clang/Sema/Sema.h"
2015-01-23 12:49:18 +03:00
# include "clang/Sema/SemaDiagnostic.h"
2012-09-05 13:37:39 +04:00
# include "clang/Serialization/ASTWriter.h"
2018-05-29 17:53:24 +03:00
# include "clang/Serialization/ASTReader.h"
# include "llvm/Support/Path.h"
2012-09-05 13:37:39 +04:00
2013-04-24 20:28:08 +04:00
# include "llvm/IR/LLVMContext.h"
# include "llvm/IR/Module.h"
2012-09-05 13:37:39 +04:00
# include "llvm/Support/CrashRecoveryContext.h"
# include "llvm/Support/MemoryBuffer.h"
2016-09-15 21:55:14 +03:00
# include <stdio.h>
2014-10-14 10:58:40 +04:00
2012-09-05 13:37:39 +04:00
using namespace clang ;
2014-10-14 10:58:40 +04:00
namespace {
2016-07-05 10:37:26 +03:00
2014-10-14 10:58:40 +04:00
///\brief Check the compile-time C++ ABI version vs the run-time ABI version,
/// a mismatch could cause havoc. Reports if ABI versions differ.
2017-02-22 23:35:36 +03:00
static bool CheckABICompatibility ( cling : : Interpreter & Interp ) {
2016-10-05 00:06:20 +03:00
# if defined(__GLIBCXX__)
# define CLING_CXXABI_VERS std::to_string(__GLIBCXX__)
const char * CLING_CXXABI_NAME = " __GLIBCXX__ " ;
2018-04-10 16:32:28 +03:00
static constexpr bool CLING_CXXABI_BACKWARDCOMP = true ;
2016-10-05 00:06:20 +03:00
# elif defined(_LIBCPP_VERSION)
2018-04-10 16:32:28 +03:00
# define CLING_CXXABI_VERS std::to_string(_LIBCPP_ABI_VERSION)
const char * CLING_CXXABI_NAME = " _LIBCPP_ABI_VERSION " ;
static constexpr bool CLING_CXXABI_BACKWARDCOMP = false ;
2016-10-05 00:06:20 +03:00
# elif defined(_CRT_MSVCP_CURRENT)
# define CLING_CXXABI_VERS _CRT_MSVCP_CURRENT
const char * CLING_CXXABI_NAME = " _CRT_MSVCP_CURRENT " ;
2018-04-10 16:32:28 +03:00
static constexpr bool CLING_CXXABI_BACKWARDCOMP = false ;
2016-10-05 00:06:20 +03:00
# else
# error "Unknown platform for ABI check";
# endif
2017-02-22 23:31:26 +03:00
const std : : string CurABI = Interp . getMacroValue ( CLING_CXXABI_NAME ) ;
if ( CurABI = = CLING_CXXABI_VERS )
return true ;
2018-04-17 09:25:46 +03:00
if ( CurABI . empty ( ) ) {
cling : : errs ( ) < <
" Warning in cling::IncrementalParser::CheckABICompatibility(): \n "
" Failed to extract C++ standard library version. \n " ;
}
2018-04-10 16:32:28 +03:00
if ( CLING_CXXABI_BACKWARDCOMP & & CurABI < CLING_CXXABI_VERS ) {
// Backward compatible ABIs allow us to interpret old headers
// against a newer stdlib.so.
return true ;
}
2014-10-14 10:58:40 +04:00
2016-09-10 22:04:39 +03:00
cling : : errs ( ) < <
2016-07-05 10:37:26 +03:00
" Warning in cling::IncrementalParser::CheckABICompatibility(): \n "
2018-04-17 09:25:46 +03:00
" Possible C++ standard library mismatch, compiled with "
2016-10-05 00:06:20 +03:00
< < CLING_CXXABI_NAME < < " ' " < < CLING_CXXABI_VERS < < " ' \n "
2016-07-05 10:37:26 +03:00
" Extraction of runtime standard library version was: ' "
< < CurABI < < " ' \n " ;
2016-10-05 00:06:20 +03:00
2016-07-05 10:37:26 +03:00
return false ;
2014-10-14 10:58:40 +04:00
}
2017-01-09 18:32:49 +03:00
2017-01-28 04:41:30 +03:00
class FilteringDiagConsumer : public cling : : utils : : DiagnosticsOverride {
std : : stack < bool > m_IgnorePromptDiags ;
2017-01-09 18:32:49 +03:00
2017-01-12 12:54:13 +03:00
void SyncDiagCountWithTarget ( ) {
2017-01-28 04:41:30 +03:00
NumWarnings = m_PrevClient . getNumWarnings ( ) ;
NumErrors = m_PrevClient . getNumErrors ( ) ;
2017-01-12 12:54:13 +03:00
}
2017-01-09 18:32:49 +03:00
void BeginSourceFile ( const LangOptions & LangOpts ,
const Preprocessor * PP = nullptr ) override {
2017-01-28 04:41:30 +03:00
m_PrevClient . BeginSourceFile ( LangOpts , PP ) ;
2017-01-09 18:32:49 +03:00
}
void EndSourceFile ( ) override {
2017-01-28 04:41:30 +03:00
m_PrevClient . EndSourceFile ( ) ;
2017-01-12 12:54:13 +03:00
SyncDiagCountWithTarget ( ) ;
2017-01-09 18:32:49 +03:00
}
2018-05-29 17:53:24 +03:00
2017-01-09 18:32:49 +03:00
void finish ( ) override {
2017-01-28 04:41:30 +03:00
m_PrevClient . finish ( ) ;
2017-01-12 12:54:13 +03:00
SyncDiagCountWithTarget ( ) ;
2017-01-09 18:32:49 +03:00
}
void clear ( ) override {
2017-01-28 04:41:30 +03:00
m_PrevClient . clear ( ) ;
2017-01-12 12:54:13 +03:00
SyncDiagCountWithTarget ( ) ;
2017-01-09 18:32:49 +03:00
}
2017-01-28 04:41:30 +03:00
bool IncludeInDiagnosticCounts ( ) const override {
return m_PrevClient . IncludeInDiagnosticCounts ( ) ;
}
2017-01-09 18:32:49 +03:00
void HandleDiagnostic ( DiagnosticsEngine : : Level DiagLevel ,
const Diagnostic & Info ) override {
if ( Ignoring ( ) ) {
if ( Info . getID ( ) = = diag : : warn_unused_expr
| | Info . getID ( ) = = diag : : warn_unused_call
2017-01-10 15:58:24 +03:00
| | Info . getID ( ) = = diag : : warn_unused_comparison )
2017-01-09 18:32:49 +03:00
return ; // ignore!
if ( Info . getID ( ) = = diag : : warn_falloff_nonvoid_function ) {
DiagLevel = DiagnosticsEngine : : Error ;
2017-01-10 15:58:24 +03:00
}
if ( Info . getID ( ) = = diag : : ext_return_has_expr ) {
// An error that we need to suppress.
2017-01-09 18:32:49 +03:00
auto Diags = const_cast < DiagnosticsEngine * > ( Info . getDiags ( ) ) ;
2017-01-10 15:58:24 +03:00
assert ( Diags - > hasErrorOccurred ( ) & & " Expected ErrorOccurred " ) ;
2017-01-28 04:41:30 +03:00
if ( m_PrevClient . getNumErrors ( ) = = 0 ) { // first error
2017-01-10 15:58:24 +03:00
Diags - > Reset ( true /*soft - only counts, not mappings*/ ) ;
} // else we had other errors, too.
return ; // ignore!
2017-01-09 18:32:49 +03:00
}
}
2017-01-28 04:41:30 +03:00
m_PrevClient . HandleDiagnostic ( DiagLevel , Info ) ;
2017-01-12 12:54:13 +03:00
SyncDiagCountWithTarget ( ) ;
2017-01-09 18:32:49 +03:00
}
bool Ignoring ( ) const {
2017-01-28 04:41:30 +03:00
return ! m_IgnorePromptDiags . empty ( ) & & m_IgnorePromptDiags . top ( ) ;
2017-01-09 18:32:49 +03:00
}
2017-01-28 04:41:30 +03:00
public :
FilteringDiagConsumer ( DiagnosticsEngine & Diags , bool Own ) :
DiagnosticsOverride ( Diags , Own ) {
}
struct RAAI {
FilteringDiagConsumer & m_Client ;
RAAI ( DiagnosticConsumer & F , bool Ignore ) :
m_Client ( static_cast < FilteringDiagConsumer & > ( F ) ) {
m_Client . m_IgnorePromptDiags . push ( Ignore ) ;
}
~ RAAI ( ) { m_Client . m_IgnorePromptDiags . pop ( ) ; }
} ;
2017-01-09 18:32:49 +03:00
} ;
2014-10-14 10:58:40 +04:00
} // unnamed namespace
2018-07-26 13:39:04 +03:00
static void HandlePlugins ( CompilerInstance & CI ,
std : : vector < std : : unique_ptr < ASTConsumer > > & Consumers ) {
// Copied from Frontend/FrontendAction.cpp.
// FIXME: Remove when we switch to a tools-based cling driver.
// If the FrontendPluginRegistry has plugins before loading any shared library
// this means we have linked our plugins. This is useful when cling runs in
// embedded mode (in a shared library). This is the only feasible way to have
// plugins if cling is in a single shared library which is dlopen-ed with
// RTLD_LOCAL. In that situation plugins can still find the cling, clang and
// llvm symbols opened with local visibility.
2018-11-16 12:30:57 +03:00
if ( FrontendPluginRegistry : : begin ( ) = = FrontendPluginRegistry : : end ( ) ) {
2018-07-26 13:39:04 +03:00
for ( const std : : string & Path : CI . getFrontendOpts ( ) . Plugins ) {
std : : string Err ;
if ( llvm : : sys : : DynamicLibrary : : LoadLibraryPermanently ( Path . c_str ( ) , & Err ) )
CI . getDiagnostics ( ) . Report ( clang : : diag : : err_fe_unable_to_load_plugin )
< < Path < < Err ;
2018-11-16 12:30:57 +03:00
}
// If we are not statically linked, we should register the pragmas ourselves
// because the dlopen happens after creating the clang::Preprocessor which
// calls RegisterBuiltinPragmas.
// FIXME: This can be avoided by refactoring our routine and moving it to
// the CIFactory. This requires an abstraction which allows us to
// conditionally create MultiplexingConsumers.
// Copied from Lex/Pragma.cpp
// Pragmas added by plugins
for ( PragmaHandlerRegistry : : iterator it = PragmaHandlerRegistry : : begin ( ) ,
ie = PragmaHandlerRegistry : : end ( ) ; it ! = ie ; + + it )
CI . getPreprocessor ( ) . AddPragmaHandler ( it - > instantiate ( ) . release ( ) ) ;
2018-07-26 13:39:04 +03:00
}
for ( auto it = clang : : FrontendPluginRegistry : : begin ( ) ,
ie = clang : : FrontendPluginRegistry : : end ( ) ;
it ! = ie ; + + it ) {
std : : unique_ptr < clang : : PluginASTAction > P ( it - > instantiate ( ) ) ;
PluginASTAction : : ActionType PluginActionType = P - > getActionType ( ) ;
assert ( PluginActionType ! = clang : : PluginASTAction : : ReplaceAction ) ;
if ( P - > ParseArgs ( CI , CI . getFrontendOpts ( ) . PluginArgs [ it - > getName ( ) ] ) ) {
std : : unique_ptr < ASTConsumer > PluginConsumer
= P - > CreateASTConsumer ( CI , /*InputFile*/ " " ) ;
if ( PluginActionType = = clang : : PluginASTAction : : AddBeforeMainAction )
Consumers . insert ( Consumers . begin ( ) , std : : move ( PluginConsumer ) ) ;
else
Consumers . push_back ( std : : move ( PluginConsumer ) ) ;
}
}
}
2012-09-05 13:37:39 +04:00
namespace cling {
2019-05-24 10:41:17 +03:00
IncrementalParser : : IncrementalParser ( Interpreter * interp , const char * llvmdir ,
const ModuleFileExtensions & moduleExtensions )
2018-07-26 13:39:04 +03:00
: m_Interpreter ( interp ) {
2017-09-10 12:59:51 +03:00
std : : unique_ptr < cling : : DeclCollector > consumer ;
consumer . reset ( m_Consumer = new cling : : DeclCollector ( ) ) ;
m_CI . reset ( CIFactory : : createCI ( " " , interp - > getOptions ( ) , llvmdir ,
2019-05-24 10:41:17 +03:00
std : : move ( consumer ) , moduleExtensions ) ) ;
2012-09-05 13:37:39 +04:00
2016-07-02 07:20:48 +03:00
if ( ! m_CI ) {
cling : : errs ( ) < < " Compiler instance could not be created. \n " ;
return ;
}
2016-07-22 01:29:10 +03:00
// Is the CompilerInstance being used to generate output only?
if ( m_Interpreter - > getOptions ( ) . CompilerOpts . HasOutput )
return ;
2012-09-05 13:37:39 +04:00
2016-07-02 07:20:48 +03:00
if ( ! m_Consumer ) {
cling : : errs ( ) < < " No AST consumer available. \n " ;
return ;
}
2017-01-09 18:32:49 +03:00
2018-07-26 13:39:04 +03:00
std : : vector < std : : unique_ptr < ASTConsumer > > Consumers ;
HandlePlugins ( * m_CI , Consumers ) ;
std : : unique_ptr < ASTConsumer > WrappedConsumer ;
2017-01-09 18:32:49 +03:00
DiagnosticsEngine & Diag = m_CI - > getDiagnostics ( ) ;
2016-08-08 23:29:06 +03:00
if ( m_CI - > getFrontendOpts ( ) . ProgramAction ! = frontend : : ParseSyntaxOnly ) {
2018-07-26 13:39:04 +03:00
auto CG
= std : : unique_ptr < clang : : CodeGenerator > ( CreateLLVMCodeGen ( Diag ,
makeModuleName ( ) ,
m_CI - > getHeaderSearchOpts ( ) ,
m_CI - > getPreprocessorOpts ( ) ,
m_CI - > getCodeGenOpts ( ) ,
* m_Interpreter - > getLLVMContext ( ) )
) ;
m_CodeGen = CG . get ( ) ;
assert ( m_CodeGen ) ;
if ( ! Consumers . empty ( ) ) {
Consumers . push_back ( std : : move ( CG ) ) ;
WrappedConsumer . reset ( new MultiplexConsumer ( std : : move ( Consumers ) ) ) ;
}
else
WrappedConsumer = std : : move ( CG ) ;
2012-09-05 13:37:39 +04:00
}
2017-06-15 23:32:02 +03:00
// Initialize the DeclCollector and add callbacks keeping track of macros.
2018-07-26 13:39:04 +03:00
m_Consumer - > Setup ( this , std : : move ( WrappedConsumer ) , m_CI - > getPreprocessor ( ) ) ;
2017-06-15 23:32:02 +03:00
2017-01-28 04:41:30 +03:00
m_DiagConsumer . reset ( new FilteringDiagConsumer ( Diag , false ) ) ;
2017-01-09 18:32:49 +03:00
2013-08-22 16:11:12 +04:00
initializeVirtualFile ( ) ;
2018-05-29 17:53:24 +03:00
if ( m_CI - > getFrontendOpts ( ) . ProgramAction ! = frontend : : ParseSyntaxOnly & &
m_Interpreter - > getOptions ( ) . CompilerOpts . CUDA ) {
// Create temporary folder for all files, which the CUDA device compiler
// will generate.
llvm : : SmallString < 256 > TmpPath ;
llvm : : StringRef sep = llvm : : sys : : path : : get_separator ( ) . data ( ) ;
llvm : : sys : : path : : system_temp_directory ( false , TmpPath ) ;
TmpPath . append ( sep . data ( ) ) ;
TmpPath . append ( " cling-%%%% " ) ;
TmpPath . append ( sep . data ( ) ) ;
llvm : : SmallString < 256 > TmpFolder ;
llvm : : sys : : fs : : createUniqueFile ( TmpPath . c_str ( ) , TmpFolder ) ;
llvm : : sys : : fs : : create_directory ( TmpFolder ) ;
// The CUDA fatbin file is the connection beetween the CUDA device
// compiler and the CodeGen of cling. The file will every time reused.
if ( getCI ( ) - > getCodeGenOpts ( ) . CudaGpuBinaryFileNames . empty ( ) )
getCI ( ) - > getCodeGenOpts ( ) . CudaGpuBinaryFileNames . push_back (
std : : string ( TmpFolder . c_str ( ) ) + " cling.fatbin " ) ;
m_CUDACompiler . reset (
new IncrementalCUDADeviceCompiler ( TmpFolder . c_str ( ) ,
m_CI - > getCodeGenOpts ( ) . OptimizationLevel ,
m_Interpreter - > getOptions ( ) ,
* m_CI ) ) ;
}
2013-03-11 17:11:15 +04:00
}
2013-06-26 22:51:05 +04:00
2016-07-02 07:20:48 +03:00
bool
2015-03-18 11:38:35 +03:00
IncrementalParser : : Initialize ( llvm : : SmallVectorImpl < ParseResultTransaction > &
2016-01-07 19:19:20 +03:00
result , bool isChildInterpreter ) {
2016-06-27 02:43:40 +03:00
m_TransactionPool . reset ( new TransactionPool ) ;
2016-11-15 17:12:47 +03:00
if ( hasCodeGenerator ( ) )
2013-03-11 17:11:15 +04:00
getCodeGenerator ( ) - > Initialize ( getCI ( ) - > getASTContext ( ) ) ;
2013-05-23 13:05:02 +04:00
2017-04-07 18:05:26 +03:00
CompilationOptions CO = m_Interpreter - > makeDefaultCompilationOpts ( ) ;
2016-05-18 17:08:14 +03:00
Transaction * CurT = beginTransaction ( CO ) ;
Preprocessor & PP = m_CI - > getPreprocessor ( ) ;
2016-07-02 07:20:48 +03:00
DiagnosticsEngine & Diags = m_CI - > getSema ( ) . getDiagnostics ( ) ;
2016-05-18 17:08:14 +03:00
// Pull in PCH.
2013-05-23 16:44:52 +04:00
const std : : string & PCHFileName
2015-07-03 18:41:33 +03:00
= m_CI - > getInvocation ( ) . getPreprocessorOpts ( ) . ImplicitPCHInclude ;
2013-03-11 17:11:15 +04:00
if ( ! PCHFileName . empty ( ) ) {
2017-01-28 23:11:45 +03:00
Transaction * PchT = beginTransaction ( CO ) ;
DiagnosticErrorTrap Trap ( Diags ) ;
2013-03-11 17:11:15 +04:00
m_CI - > createPCHExternalASTSource ( PCHFileName ,
true /*DisablePCHValidation*/ ,
true /*AllowPCHWithCompilerErrors*/ ,
2014-06-06 12:19:14 +04:00
0 /*DeserializationListener*/ ,
true /*OwnsDeserializationListener*/ ) ;
2017-01-28 23:11:45 +03:00
result . push_back ( endTransaction ( PchT ) ) ;
if ( Trap . hasErrorOccurred ( ) ) {
result . push_back ( endTransaction ( CurT ) ) ;
return false ;
}
2013-03-11 17:11:15 +04:00
}
2012-09-05 13:37:39 +04:00
2015-02-18 12:44:12 +03:00
addClingPragmas ( * m_Interpreter ) ;
2016-05-18 17:08:14 +03:00
// Must happen after attaching the PCH, else PCH elements will end up
// being lexed.
PP . EnterMainSourceFile ( ) ;
Sema * TheSema = & m_CI - > getSema ( ) ;
2016-07-02 07:20:48 +03:00
m_Parser . reset ( new Parser ( PP , * TheSema , false /*skipFuncBodies*/ ) ) ;
2016-05-18 17:08:14 +03:00
// Initialize the parser after PP has entered the main source file.
2012-09-05 13:37:39 +04:00
m_Parser - > Initialize ( ) ;
2013-03-11 17:11:15 +04:00
ExternalASTSource * External = TheSema - > getASTContext ( ) . getExternalSource ( ) ;
if ( External )
External - > StartTranslationUnit ( m_Consumer ) ;
2013-04-27 03:52:55 +04:00
2016-11-09 19:53:50 +03:00
// Start parsing the "main file" to warm up lexing (enter caching lex mode
// for ParseInternal()'s call EnterSourceFile() to make sense.
2017-01-29 22:39:53 +03:00
while ( ! m_Parser - > ParseTopLevelDecl ( ) ) { }
2016-11-09 19:53:50 +03:00
2016-06-21 20:23:21 +03:00
// If I belong to the parent Interpreter, am using C++, and -noruntime
// wasn't given on command line, then #include <new> and check ABI
if ( ! isChildInterpreter & & m_CI - > getLangOpts ( ) . CPlusPlus & &
! m_Interpreter - > getOptions ( ) . NoRuntime ) {
2015-02-22 00:37:50 +03:00
// <new> is needed by the ValuePrinter so it's a good thing to include it.
// We need to include it to determine the version number of the standard
// library implementation.
ParseInternal ( " #include <new> " ) ;
// That's really C++ ABI compatibility. C has other problems ;-)
2017-02-22 23:35:36 +03:00
CheckABICompatibility ( * m_Interpreter ) ;
2015-02-22 00:37:50 +03:00
}
2014-10-14 10:58:40 +04:00
2014-03-24 00:08:48 +04:00
// DO NOT commit the transactions here: static initialization in these
// transactions requires gCling through local_cxa_atexit(), but that has not
// been defined yet!
2015-03-16 13:25:01 +03:00
ParseResultTransaction PRT = endTransaction ( CurT ) ;
2015-03-18 11:38:35 +03:00
result . push_back ( PRT ) ;
2016-07-02 07:20:48 +03:00
return true ;
}
bool IncrementalParser : : isValid ( bool initialized ) const {
return m_CI & & m_CI - > hasFileManager ( ) & & m_Consumer
& & ! m_VirtualFileID . isInvalid ( )
& & ( ! initialized | | ( m_TransactionPool & & m_Parser ) ) ;
2012-09-05 13:37:39 +04:00
}
2019-08-30 20:00:57 +03:00
namespace {
template < class T >
struct Reversed {
const T & m_orig ;
auto begin ( ) - > decltype ( m_orig . rbegin ( ) ) { return m_orig . rbegin ( ) ; }
auto end ( ) - > decltype ( m_orig . rend ( ) ) { return m_orig . rend ( ) ; }
} ;
template < class T >
Reversed < T > reverse ( const T & orig ) { return { orig } ; }
}
const Transaction * IncrementalParser : : getLastWrapperTransaction ( ) const {
if ( auto * T = getCurrentTransaction ( ) )
if ( T - > getWrapperFD ( ) )
return T ;
for ( auto T : reverse ( m_Transactions ) )
if ( T - > getWrapperFD ( ) )
return T ;
return nullptr ;
}
2014-05-14 16:29:44 +04:00
const Transaction * IncrementalParser : : getCurrentTransaction ( ) const {
return m_Consumer - > getTransaction ( ) ;
}
2014-04-01 18:44:59 +04:00
SourceLocation IncrementalParser : : getLastMemoryBufferEndLoc ( ) const {
const SourceManager & SM = getCI ( ) - > getSourceManager ( ) ;
SourceLocation Result = SM . getLocForStartOfFile ( m_VirtualFileID ) ;
return Result . getLocWithOffset ( m_MemoryBuffers . size ( ) + 1 ) ;
}
2012-09-05 13:37:39 +04:00
IncrementalParser : : ~ IncrementalParser ( ) {
2016-06-27 02:43:40 +03:00
Transaction * T = const_cast < Transaction * > ( getFirstTransaction ( ) ) ;
2012-11-20 17:21:00 +04:00
while ( T ) {
2013-09-15 22:18:49 +04:00
assert ( ( T - > getState ( ) = = Transaction : : kCommitted
2014-08-04 06:05:42 +04:00
| | T - > getState ( ) = = Transaction : : kRolledBackWithErrors
2013-11-27 17:28:40 +04:00
| | T - > getState ( ) = = Transaction : : kNumStates // reset from the pool
2013-06-17 14:45:18 +04:00
| | T - > getState ( ) = = Transaction : : kRolledBack )
& & " Not committed? " ) ;
2016-06-27 02:43:40 +03:00
const Transaction * nextT = T - > getNext ( ) ;
m_TransactionPool - > releaseTransaction ( T , false ) ;
T = const_cast < Transaction * > ( nextT ) ;
2012-11-20 17:21:00 +04:00
}
2012-09-05 13:37:39 +04:00
}
2015-02-18 16:05:30 +03:00
void IncrementalParser : : addTransaction ( Transaction * T ) {
if ( ! T - > isNestedTransaction ( ) & & T ! = getLastTransaction ( ) ) {
if ( getLastTransaction ( ) )
m_Transactions . back ( ) - > setNext ( T ) ;
m_Transactions . push_back ( T ) ;
}
}
2014-08-04 06:05:42 +04:00
Transaction * IncrementalParser : : beginTransaction ( const CompilationOptions &
2012-11-15 02:06:58 +04:00
Opts ) {
2012-09-05 13:37:39 +04:00
Transaction * OldCurT = m_Consumer - > getTransaction ( ) ;
2016-06-27 02:43:40 +03:00
Transaction * NewCurT = m_TransactionPool - > takeTransaction ( m_CI - > getSema ( ) ) ;
2013-07-06 15:04:31 +04:00
NewCurT - > setCompilationOpts ( Opts ) ;
2014-08-04 06:05:42 +04:00
// If we are in the middle of transaction and we see another begin
2012-09-05 13:37:39 +04:00
// transaction - it must be nested transaction.
2014-08-04 06:05:42 +04:00
if ( OldCurT & & OldCurT ! = NewCurT
2013-08-04 20:17:41 +04:00
& & ( OldCurT - > getState ( ) = = Transaction : : kCollecting
| | OldCurT - > getState ( ) = = Transaction : : kCompleted ) ) {
2013-07-06 15:04:31 +04:00
OldCurT - > addNestedTransaction ( NewCurT ) ; // takes the ownership
2012-09-05 13:37:39 +04:00
}
2013-04-24 10:55:38 +04:00
m_Consumer - > setTransaction ( NewCurT ) ;
2012-11-15 02:06:58 +04:00
return NewCurT ;
2012-09-05 13:37:39 +04:00
}
2015-03-16 13:25:01 +03:00
IncrementalParser : : ParseResultTransaction
IncrementalParser : : endTransaction ( Transaction * T ) {
2013-04-27 03:52:55 +04:00
assert ( T & & " Null transaction!? " ) ;
assert ( T - > getState ( ) = = Transaction : : kCollecting ) ;
2013-06-27 14:34:05 +04:00
# ifndef NDEBUG
if ( T - > hasNestedTransactions ( ) ) {
for ( Transaction : : const_nested_iterator I = T - > nested_begin ( ) ,
E = T - > nested_end ( ) ; I ! = E ; + + I )
assert ( ( * I ) - > isCompleted ( ) & & " Nested transaction not completed!? " ) ;
}
# endif
2013-04-27 03:52:55 +04:00
T - > setState ( Transaction : : kCompleted ) ;
2015-03-16 13:25:01 +03:00
2017-02-17 23:58:06 +03:00
DiagnosticsEngine & Diag = getCI ( ) - > getSema ( ) . getDiagnostics ( ) ;
2015-03-16 13:25:01 +03:00
//TODO: Make the enum orable.
EParseResult ParseResult = kSuccess ;
2017-02-17 23:58:06 +03:00
assert ( ( Diag . hasFatalErrorOccurred ( ) ? Diag . hasErrorOccurred ( ) : true )
& & " Diag.hasFatalErrorOccurred without Diag.hasErrorOccurred ! " ) ;
2017-02-03 01:31:36 +03:00
2017-02-17 23:58:06 +03:00
if ( Diag . hasErrorOccurred ( ) | | T - > getIssuedDiags ( ) = = Transaction : : kErrors ) {
2015-03-16 13:25:01 +03:00
T - > setIssuedDiags ( Transaction : : kErrors ) ;
ParseResult = kFailed ;
2017-02-17 23:58:06 +03:00
} else if ( Diag . getNumWarnings ( ) > 0 ) {
2015-03-16 22:53:42 +03:00
T - > setIssuedDiags ( Transaction : : kWarnings ) ;
ParseResult = kSuccessWithWarnings ;
2015-03-16 13:25:01 +03:00
}
2015-06-08 15:48:24 +03:00
// Empty transaction, send it back to the pool.
2013-07-06 15:04:31 +04:00
if ( T - > empty ( ) ) {
2014-08-04 06:05:42 +04:00
assert ( ( ! m_Consumer - > getTransaction ( )
2013-08-05 17:15:37 +04:00
| | ( m_Consumer - > getTransaction ( ) = = T ) )
2013-08-04 20:18:27 +04:00
& & " Cannot release different T " ) ;
2014-08-04 06:05:42 +04:00
// If a nested transaction the active one should be its parent
2013-08-04 20:18:27 +04:00
// from now on. FIXME: Merge conditional with commitTransaction
if ( T - > isNestedTransaction ( ) )
m_Consumer - > setTransaction ( T - > getParent ( ) ) ;
else
m_Consumer - > setTransaction ( ( Transaction * ) 0 ) ;
2013-07-06 15:04:31 +04:00
m_TransactionPool - > releaseTransaction ( T ) ;
2015-03-16 13:25:01 +03:00
return ParseResultTransaction ( nullptr , ParseResult ) ;
2013-10-24 20:54:06 +04:00
}
2013-07-06 15:04:31 +04:00
2015-02-18 16:05:30 +03:00
addTransaction ( T ) ;
2015-03-16 13:25:01 +03:00
return ParseResultTransaction ( T , ParseResult ) ;
2012-09-05 13:37:39 +04:00
}
2017-03-11 03:31:57 +03:00
std : : string IncrementalParser : : makeModuleName ( ) {
return std : : string ( " cling-module- " ) + std : : to_string ( m_ModuleNo + + ) ;
}
llvm : : Module * IncrementalParser : : StartModule ( ) {
return getCodeGenerator ( ) - > StartModule ( makeModuleName ( ) ,
* m_Interpreter - > getLLVMContext ( ) ,
getCI ( ) - > getCodeGenOpts ( ) ) ;
}
2017-01-29 22:39:53 +03:00
void IncrementalParser : : commitTransaction ( ParseResultTransaction & PRT ,
bool ClearDiagClient ) {
2015-03-18 11:38:35 +03:00
Transaction * T = PRT . getPointer ( ) ;
2015-05-28 12:44:26 +03:00
if ( ! T ) {
if ( PRT . getInt ( ) ! = kSuccess ) {
// Nothing has been emitted to Codegen, reset the Diags.
DiagnosticsEngine & Diags = getCI ( ) - > getSema ( ) . getDiagnostics ( ) ;
Diags . Reset ( /*soft=*/ true ) ;
2017-01-29 22:39:53 +03:00
if ( ClearDiagClient )
Diags . getClient ( ) - > clear ( ) ;
2015-05-28 12:44:26 +03:00
}
2015-03-18 11:38:35 +03:00
return ;
2015-05-28 12:44:26 +03:00
}
2015-03-18 11:38:35 +03:00
2012-11-15 02:06:58 +04:00
assert ( T - > isCompleted ( ) & & " Transaction not ended!? " ) ;
2013-04-09 19:30:16 +04:00
assert ( T - > getState ( ) ! = Transaction : : kCommitted
& & " Committing an already committed transaction. " ) ;
2015-03-16 22:08:37 +03:00
assert ( ( T - > getIssuedDiags ( ) = = Transaction : : kErrors | | ! T - > empty ( ) )
& & " Valid Transactions must not be empty; " ) ;
2012-09-05 13:37:39 +04:00
2013-06-25 11:19:15 +04:00
// If committing a nested transaction the active one should be its parent
// from now on.
2013-06-25 12:51:58 +04:00
if ( T - > isNestedTransaction ( ) )
2013-06-25 11:19:15 +04:00
m_Consumer - > setTransaction ( T - > getParent ( ) ) ;
2012-09-05 13:37:39 +04:00
// Check for errors...
2012-11-15 02:06:58 +04:00
if ( T - > getIssuedDiags ( ) = = Transaction : : kErrors ) {
2015-03-16 16:49:28 +03:00
// Make module visible to TransactionUnloader.
bool MustStartNewModule = false ;
if ( ! T - > isNestedTransaction ( ) & & hasCodeGenerator ( ) ) {
MustStartNewModule = true ;
std : : unique_ptr < llvm : : Module > M ( getCodeGenerator ( ) - > ReleaseModule ( ) ) ;
if ( M ) {
T - > setModule ( std : : move ( M ) ) ;
}
}
2015-05-28 12:44:26 +03:00
// Module has been released from Codegen, reset the Diags now.
DiagnosticsEngine & Diags = getCI ( ) - > getSema ( ) . getDiagnostics ( ) ;
Diags . Reset ( /*soft=*/ true ) ;
2017-01-29 22:39:53 +03:00
if ( ClearDiagClient )
Diags . getClient ( ) - > clear ( ) ;
2015-05-28 12:44:26 +03:00
2016-06-25 01:14:00 +03:00
PRT . setPointer ( nullptr ) ;
PRT . setInt ( kFailed ) ;
2016-06-23 20:38:57 +03:00
m_Interpreter - > unload ( * T ) ;
2015-03-16 16:49:28 +03:00
2017-03-11 03:31:57 +03:00
// Create a new module if necessary.
if ( MustStartNewModule )
StartModule ( ) ;
2012-09-05 13:37:39 +04:00
return ;
}
2012-11-15 02:06:58 +04:00
if ( T - > hasNestedTransactions ( ) ) {
2015-03-18 11:38:35 +03:00
Transaction * TopmostParent = T - > getTopmostParent ( ) ;
EParseResult PR = kSuccess ;
if ( TopmostParent - > getIssuedDiags ( ) = = Transaction : : kErrors )
PR = kFailed ;
else if ( TopmostParent - > getIssuedDiags ( ) = = Transaction : : kWarnings )
PR = kSuccessWithWarnings ;
2013-07-06 15:03:21 +04:00
for ( Transaction : : const_nested_iterator I = T - > nested_begin ( ) ,
2013-04-08 18:35:35 +04:00
E = T - > nested_end ( ) ; I ! = E ; + + I )
2016-06-25 01:14:00 +03:00
if ( ( * I ) - > getState ( ) ! = Transaction : : kCommitted ) {
ParseResultTransaction PRT ( * I , PR ) ;
commitTransaction ( PRT ) ;
}
2012-11-15 02:06:58 +04:00
}
2013-07-06 15:01:48 +04:00
// If there was an error coming from the transformers.
if ( T - > getIssuedDiags ( ) = = Transaction : : kErrors ) {
2016-06-23 20:38:57 +03:00
m_Interpreter - > unload ( * T ) ;
2013-06-25 12:51:58 +04:00
return ;
2013-07-06 15:01:48 +04:00
}
2012-09-05 13:37:39 +04:00
2013-06-13 16:53:58 +04:00
// Here we expect a template instantiation. We need to open the transaction
// that we are currently work with.
2013-07-06 15:04:31 +04:00
{
2014-04-16 13:59:36 +04:00
Transaction * prevConsumerT = m_Consumer - > getTransaction ( ) ;
m_Consumer - > setTransaction ( T ) ;
2017-04-07 18:06:23 +03:00
Transaction * nestedT = beginTransaction ( T - > getCompilationOpts ( ) ) ;
2013-07-06 15:04:31 +04:00
// Pull all template instantiations in that came from the consumers.
getCI ( ) - > getSema ( ) . PerformPendingInstantiations ( ) ;
2018-04-10 15:21:42 +03:00
# 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 ;
2018-04-10 18:51:39 +03:00
Tok . setKind ( tok : : eof ) ;
2018-04-10 15:21:42 +03:00
do {
getCI ( ) - > getSema ( ) . getPreprocessor ( ) . Lex ( Tok ) ;
} while ( Tok . isNot ( tok : : eof ) ) ;
# endif
2015-06-07 21:38:49 +03:00
ParseResultTransaction nestedPRT = endTransaction ( nestedT ) ;
commitTransaction ( nestedPRT ) ;
2014-04-16 13:59:36 +04:00
m_Consumer - > setTransaction ( prevConsumerT ) ;
2013-07-06 15:04:31 +04:00
}
2013-06-13 16:53:58 +04:00
m_Consumer - > HandleTranslationUnit ( getCI ( ) - > getASTContext ( ) ) ;
2013-04-10 19:15:49 +04:00
2013-06-25 12:51:58 +04:00
// The static initializers might run anything and can thus cause more
// decls that need to end up in a transaction. But this one is done
// with CodeGen...
2013-07-06 15:04:31 +04:00
if ( T - > getCompilationOpts ( ) . CodeGeneration & & hasCodeGenerator ( ) ) {
2014-04-16 13:59:36 +04:00
Transaction * prevConsumerT = m_Consumer - > getTransaction ( ) ;
m_Consumer - > setTransaction ( T ) ;
2013-07-06 15:04:31 +04:00
codeGenTransaction ( T ) ;
T - > setState ( Transaction : : kCommitted ) ;
2014-04-16 14:01:44 +04:00
if ( ! T - > getParent ( ) ) {
2015-02-03 23:32:09 +03:00
if ( m_Interpreter - > executeTransaction ( * T )
2014-04-16 14:01:44 +04:00
> = Interpreter : : kExeFirstError ) {
2017-03-21 08:00:27 +03:00
// Roll back on error in initializers.
// T maybe pointing to freed memory after this call:
// Interpreter::unload
// IncrementalParser::deregisterTransaction
// TransactionPool::releaseTransaction
2016-06-23 20:38:57 +03:00
m_Interpreter - > unload ( * T ) ;
2014-04-16 14:01:44 +04:00
return ;
}
2013-07-06 15:04:31 +04:00
}
2014-04-16 13:59:36 +04:00
m_Consumer - > setTransaction ( prevConsumerT ) ;
2013-07-06 15:04:31 +04:00
}
2013-06-25 12:51:58 +04:00
T - > setState ( Transaction : : kCommitted ) ;
2013-04-09 19:30:16 +04:00
2019-06-07 06:01:31 +03:00
{
Transaction * prevConsumerT = m_Consumer - > getTransaction ( ) ;
if ( InterpreterCallbacks * callbacks = m_Interpreter - > getCallbacks ( ) )
callbacks - > TransactionCommitted ( * T ) ;
m_Consumer - > setTransaction ( prevConsumerT ) ;
}
2012-09-05 13:37:39 +04:00
}
2015-03-16 13:23:01 +03:00
void IncrementalParser : : emitTransaction ( Transaction * T ) {
for ( auto DI = T - > decls_begin ( ) , DE = T - > decls_end ( ) ; DI ! = DE ; + + DI )
m_Consumer - > HandleTopLevelDecl ( DI - > m_DGR ) ;
}
2013-06-25 12:51:58 +04:00
void IncrementalParser : : codeGenTransaction ( Transaction * T ) {
// codegen the transaction
assert ( T - > getCompilationOpts ( ) . CodeGeneration & & " CodeGen turned off " ) ;
2013-07-31 11:04:30 +04:00
assert ( T - > getState ( ) = = Transaction : : kCompleted & & " Must be completed " ) ;
2013-06-25 12:51:58 +04:00
assert ( hasCodeGenerator ( ) & & " No CodeGen " ) ;
2013-08-04 20:39:41 +04:00
// Could trigger derserialization of decls.
Transaction * deserT = beginTransaction ( CompilationOptions ( ) ) ;
2013-08-07 16:26:15 +04:00
2015-01-07 12:22:52 +03:00
2015-02-04 17:34:59 +03:00
// Commit this transaction first - T might need symbols from it, so
// trigger emission of weak symbols by providing use.
2015-03-16 13:25:01 +03:00
ParseResultTransaction PRT = endTransaction ( deserT ) ;
2015-03-18 11:38:35 +03:00
commitTransaction ( PRT ) ;
2016-06-25 01:14:00 +03:00
deserT = PRT . getPointer ( ) ;
2015-02-04 17:34:59 +03:00
2015-01-07 12:22:52 +03:00
// This llvm::Module is done; finalize it and pass it to the execution
// engine.
if ( ! T - > isNestedTransaction ( ) & & hasCodeGenerator ( ) ) {
2015-03-16 17:43:40 +03:00
// The initializers are emitted to the symbol "_GLOBAL__sub_I_" + filename.
// Make that unique!
deserT = beginTransaction ( CompilationOptions ( ) ) ;
// Reset the module builder to clean up global initializers, c'tors, d'tors
2017-06-09 19:02:50 +03:00
getCodeGenerator ( ) - > HandleTranslationUnit ( getCI ( ) - > getASTContext ( ) ) ;
2016-06-25 01:14:00 +03:00
auto PRT = endTransaction ( deserT ) ;
commitTransaction ( PRT ) ;
deserT = PRT . getPointer ( ) ;
2015-03-16 17:43:40 +03:00
2015-01-15 17:13:14 +03:00
std : : unique_ptr < llvm : : Module > M ( getCodeGenerator ( ) - > ReleaseModule ( ) ) ;
2015-02-03 23:32:09 +03:00
2017-09-25 13:49:22 +03:00
if ( M )
2015-02-03 23:32:09 +03:00
T - > setModule ( std : : move ( M ) ) ;
2015-01-07 12:22:52 +03:00
2015-05-28 12:44:26 +03:00
if ( T - > getIssuedDiags ( ) ! = Transaction : : kNone ) {
// Module has been released from Codegen, reset the Diags now.
DiagnosticsEngine & Diags = getCI ( ) - > getSema ( ) . getDiagnostics ( ) ;
Diags . Reset ( /*soft=*/ true ) ;
Diags . getClient ( ) - > clear ( ) ;
}
2015-01-07 12:22:52 +03:00
// Create a new module.
2017-03-11 03:31:57 +03:00
StartModule ( ) ;
2015-01-07 12:22:52 +03:00
}
2013-06-25 12:51:58 +04:00
}
2016-06-23 20:38:57 +03:00
void IncrementalParser : : deregisterTransaction ( Transaction & T ) {
2016-09-13 09:46:43 +03:00
if ( & T = = m_Consumer - > getTransaction ( ) )
m_Consumer - > setTransaction ( T . getParent ( ) ) ;
2016-06-25 01:14:00 +03:00
if ( Transaction * Parent = T . getParent ( ) ) {
Parent - > removeNestedTransaction ( & T ) ;
T . setParent ( 0 ) ;
} else {
2015-02-18 14:38:05 +03:00
// Remove from the queue
2016-06-23 20:38:57 +03:00
assert ( & T = = m_Transactions . back ( ) & & " Out of order transaction removal " ) ;
2015-02-18 14:38:05 +03:00
m_Transactions . pop_back ( ) ;
2015-03-20 12:46:50 +03:00
if ( ! m_Transactions . empty ( ) )
m_Transactions . back ( ) - > setNext ( 0 ) ;
2015-02-18 14:38:05 +03:00
}
2016-06-25 01:14:00 +03:00
2016-06-23 20:38:57 +03:00
m_TransactionPool - > releaseTransaction ( & T ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-15 02:06:58 +04:00
std : : vector < const Transaction * > IncrementalParser : : getAllTransactions ( ) {
2013-08-18 12:48:11 +04:00
std : : vector < const Transaction * > result ( m_Transactions . size ( ) ) ;
2012-11-15 02:06:58 +04:00
const cling : : Transaction * T = getFirstTransaction ( ) ;
while ( T ) {
result . push_back ( T ) ;
T = T - > getNext ( ) ;
}
return result ;
}
2012-09-05 13:37:39 +04:00
// Each input line is contained in separate memory buffer. The SourceManager
// assigns sort-of invalid FileID for each buffer, i.e there is no FileEntry
// for the MemoryBuffer's FileID. That in turn is problem because invalid
// SourceLocations are given to the diagnostics. Thus the diagnostics cannot
// order the overloads, for example
//
// Our work-around is creating a virtual file, which doesn't exist on the disk
// with enormous size (no allocation is done). That file has valid FileEntry
// and so on... We use it for generating valid SourceLocations with valid
// offsets so that it doesn't cause any troubles to the diagnostics.
//
// +---------------------+
// | Main memory buffer |
// +---------------------+
// | Virtual file SLoc |
// | address space |<-----------------+
// | ... |<------------+ |
// | ... | | |
// | ... |<----+ | |
// | ... | | | |
// +~~~~~~~~~~~~~~~~~~~~~+ | | |
// | input_line_1 | ....+.......+..--+
// +---------------------+ | |
// | input_line_2 | ....+.....--+
// +---------------------+ |
// | ... | |
// +---------------------+ |
// | input_line_N | ..--+
// +---------------------+
//
2013-08-22 16:11:12 +04:00
void IncrementalParser : : initializeVirtualFile ( ) {
2012-09-05 13:37:39 +04:00
SourceManager & SM = getCI ( ) - > getSourceManager ( ) ;
2013-03-11 17:11:15 +04:00
m_VirtualFileID = SM . getMainFileID ( ) ;
2016-07-02 07:20:48 +03:00
if ( m_VirtualFileID . isInvalid ( ) )
cling : : errs ( ) < < " VirtualFileID could not be created. \n " ;
2012-09-05 13:37:39 +04:00
}
2015-03-16 13:25:01 +03:00
IncrementalParser : : ParseResultTransaction
IncrementalParser : : Compile ( llvm : : StringRef input ,
const CompilationOptions & Opts ) {
2012-11-20 07:26:52 +04:00
Transaction * CurT = beginTransaction ( Opts ) ;
EParseResult ParseRes = ParseInternal ( input ) ;
2012-09-05 13:37:39 +04:00
2015-06-04 12:58:39 +03:00
if ( ParseRes = = kSuccessWithWarnings )
CurT - > setIssuedDiags ( Transaction : : kWarnings ) ;
else if ( ParseRes = = kFailed )
CurT - > setIssuedDiags ( Transaction : : kErrors ) ;
2015-03-16 13:25:01 +03:00
ParseResultTransaction PRT = endTransaction ( CurT ) ;
2015-03-18 11:38:35 +03:00
commitTransaction ( PRT ) ;
2013-06-27 16:29:44 +04:00
2015-03-16 13:25:01 +03:00
return PRT ;
2012-09-05 13:37:39 +04:00
}
// 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 ( ) ;
2013-04-10 11:09:57 +04:00
2015-01-23 12:49:18 +03:00
const CompilationOptions & CO
= m_Consumer - > getTransaction ( ) - > getCompilationOpts ( ) ;
2012-09-05 13:37:39 +04:00
// 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 ( ) ) ;
}
2012-10-04 17:09:52 +04:00
assert ( PP . isIncrementalProcessingEnabled ( ) & & " Not in incremental mode!? " ) ;
2012-09-05 13:37:39 +04:00
PP . enableIncrementalProcessing ( ) ;
2017-06-22 21:45:51 +03:00
smallstream source_name ;
2012-09-05 13:37:39 +04:00
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
2015-01-15 17:13:14 +03:00
std : : unique_ptr < llvm : : MemoryBuffer >
MB ( llvm : : MemoryBuffer : : getNewUninitMemBuffer ( InputSize + 1 ,
source_name . str ( ) ) ) ;
2012-09-05 13:37:39 +04:00
char * MBStart = const_cast < char * > ( MB - > getBufferStart ( ) ) ;
memcpy ( MBStart , input . data ( ) , InputSize ) ;
2017-06-09 09:09:05 +03:00
MBStart [ InputSize ] = ' \n ' ;
2012-09-05 13:37:39 +04:00
SourceManager & SM = getCI ( ) - > getSourceManager ( ) ;
// Create SourceLocation, which will allow clang to order the overload
// candidates for example
2014-04-01 18:44:59 +04:00
SourceLocation NewLoc = getLastMemoryBufferEndLoc ( ) . getLocWithOffset ( 1 ) ;
2012-09-05 13:37:39 +04:00
2015-02-10 13:18:15 +03:00
llvm : : MemoryBuffer * MBNonOwn = MB . get ( ) ;
2016-06-23 19:09:06 +03:00
2016-07-07 11:47:58 +03:00
// Create FileID for the current buffer.
FileID FID ;
2017-05-18 18:36:41 +03:00
// 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 ) {
2016-07-07 11:47:58 +03:00
// 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*/ ) ;
2016-06-23 19:09:06 +03:00
}
2012-09-05 13:37:39 +04:00
2015-02-10 13:18:15 +03:00
m_MemoryBuffers . push_back ( std : : make_pair ( MBNonOwn , FID ) ) ;
2015-01-23 18:18:01 +03:00
2016-05-18 17:08:14 +03:00
// NewLoc only used for diags.
2012-09-05 13:37:39 +04:00
PP . EnterSourceFile ( FID , /*DirLookup*/ 0 , NewLoc ) ;
2013-12-03 18:31:31 +04:00
m_Consumer - > getTransaction ( ) - > setBufferFID ( FID ) ;
2012-09-05 13:37:39 +04:00
2015-01-23 12:49:18 +03:00
DiagnosticsEngine & Diags = getCI ( ) - > getDiagnostics ( ) ;
2017-01-28 04:41:30 +03:00
FilteringDiagConsumer : : RAAI RAAITmp ( * m_DiagConsumer , CO . IgnorePromptDiags ) ;
2015-01-23 12:49:18 +03:00
2016-07-05 09:28:44 +03:00
DiagnosticErrorTrap Trap ( Diags ) ;
2014-12-02 19:43:18 +03:00
Sema : : SavePendingInstantiationsRAII SavedPendingInstantiations ( S ) ;
2012-09-05 13:37:39 +04:00
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.
2016-07-05 09:28:44 +03:00
if ( Trap . hasErrorOccurred ( ) )
2015-03-17 12:54:04 +03:00
m_Consumer - > getTransaction ( ) - > setIssuedDiags ( Transaction : : kErrors ) ;
if ( ADecl )
2013-09-23 17:36:32 +04:00
m_Consumer - > HandleTopLevelDecl ( ADecl . get ( ) ) ;
2012-09-05 13:37:39 +04:00
} ;
2016-07-05 09:28:44 +03:00
// If never entered the while block, there's a chance an error occured
if ( Trap . hasErrorOccurred ( ) )
m_Consumer - > getTransaction ( ) - > setIssuedDiags ( Transaction : : kErrors ) ;
2012-09-05 13:37:39 +04:00
2016-06-23 19:09:06 +03:00
if ( CO . CodeCompletionOffset ! = - 1 ) {
2016-07-21 16:50:02 +03:00
assert ( ( int ) SM . getFileOffset ( PP . getCodeCompletionLoc ( ) )
= = CO . CodeCompletionOffset
& & " Completion point wrongly set! " ) ;
2016-07-07 11:47:58 +03:00
assert ( PP . isCodeCompletionReached ( )
& & " Code completion set but not reached! " ) ;
2016-07-22 16:53:33 +03:00
// Let's ignore this transaction:
2016-07-22 16:46:38 +03:00
m_Consumer - > getTransaction ( ) - > setIssuedDiags ( Transaction : : kErrors ) ;
2016-06-23 19:09:06 +03:00
return kSuccess ;
}
2015-02-17 11:49:47 +03:00
# ifdef LLVM_ON_WIN32
2015-02-13 18:48:02 +03:00
// 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 ;
2018-04-10 18:51:39 +03:00
Tok . setKind ( tok : : eof ) ;
2015-02-13 18:48:02 +03:00
do {
PP . Lex ( Tok ) ;
} while ( Tok . isNot ( tok : : eof ) ) ;
2015-02-17 11:49:47 +03:00
# endif
# ifndef NDEBUG
Token AssertTok ;
PP . Lex ( AssertTok ) ;
assert ( AssertTok . is ( tok : : eof ) & & " Lexer must be EOF when starting incremental parse! " ) ;
# endif
2015-02-13 18:48:02 +03:00
2015-03-17 12:54:04 +03:00
// 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 ) ) ;
2012-09-05 13:37:39 +04:00
}
2015-03-17 12:54:04 +03:00
if ( m_Consumer - > getTransaction ( ) - > getIssuedDiags ( ) = = Transaction : : kErrors )
2015-03-16 22:26:27 +03:00
return kFailed ;
2015-01-23 12:49:18 +03:00
else if ( Diags . getNumWarnings ( ) )
2015-03-16 22:26:27 +03:00
return kSuccessWithWarnings ;
2015-03-16 22:08:08 +03:00
2018-04-18 14:48:49 +03:00
if ( ! m_Interpreter - > isInSyntaxOnlyMode ( ) & & m_CI - > getLangOpts ( ) . CUDA )
2018-05-29 17:53:24 +03:00
m_CUDACompiler - > compileDeviceCode ( input , m_Consumer - > getTransaction ( ) ) ;
2018-03-27 18:19:50 +03:00
2015-03-16 22:26:27 +03:00
return kSuccess ;
2012-09-05 13:37:39 +04:00
}
2013-07-06 15:02:49 +04:00
void IncrementalParser : : printTransactionStructure ( ) const {
for ( size_t i = 0 , e = m_Transactions . size ( ) ; i < e ; + + i ) {
m_Transactions [ i ] - > printStructureBrief ( ) ;
}
}
2016-04-08 16:11:17 +03:00
void IncrementalParser : : SetTransformers ( bool isChildInterpreter ) {
2016-02-09 20:11:01 +03:00
// Add transformers to the IncrementalParser, which owns them
Sema * TheSema = & m_CI - > getSema ( ) ;
// Register the AST Transformers
typedef std : : unique_ptr < ASTTransformer > ASTTPtr_t ;
std : : vector < ASTTPtr_t > ASTTransformers ;
ASTTransformers . emplace_back ( new AutoSynthesizer ( TheSema ) ) ;
ASTTransformers . emplace_back ( new EvaluateTSynthesizer ( TheSema ) ) ;
2016-06-21 20:23:21 +03:00
if ( hasCodeGenerator ( ) & & ! m_Interpreter - > getOptions ( ) . NoRuntime ) {
2016-04-13 17:21:46 +03:00
// Don't protect against crashes if we cannot run anything.
// cling might also be in a PCH-generation mode; don't inject our Sema pointer
// into the PCH.
ASTTransformers . emplace_back ( new NullDerefProtectionTransformer ( m_Interpreter ) ) ;
}
2016-02-09 20:11:01 +03:00
typedef std : : unique_ptr < WrapperTransformer > WTPtr_t ;
std : : vector < WTPtr_t > WrapperTransformers ;
2016-06-21 20:23:21 +03:00
if ( ! m_Interpreter - > getOptions ( ) . NoRuntime )
WrapperTransformers . emplace_back ( new ValuePrinterSynthesizer ( TheSema ) ) ;
2016-02-09 20:11:01 +03:00
WrapperTransformers . emplace_back ( new DeclExtractor ( TheSema ) ) ;
2016-06-21 20:23:21 +03:00
if ( ! m_Interpreter - > getOptions ( ) . NoRuntime )
WrapperTransformers . emplace_back ( new ValueExtractionSynthesizer ( TheSema ,
isChildInterpreter ) ) ;
2016-02-09 20:11:01 +03:00
WrapperTransformers . emplace_back ( new CheckEmptyTransactionTransformer ( TheSema ) ) ;
m_Consumer - > SetTransformers ( std : : move ( ASTTransformers ) ,
std : : move ( WrapperTransformers ) ) ;
}
2013-08-26 19:59:33 +04:00
2012-09-05 13:37:39 +04:00
} // namespace cling