2012-09-05 09:37:39 +00:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
2014-08-06 15:05:09 +02:00
// author: Vassil Vassilev <vvasilev@cern.ch>
2014-01-07 11:08:37 +01: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 09:37:39 +00:00
//------------------------------------------------------------------------------
2012-10-02 10:30:25 +00:00
# include "cling/Interpreter/Transaction.h"
2012-09-05 09:37:39 +00:00
2012-10-19 11:49:49 +00:00
# include "cling/Utils/AST.h"
2015-02-10 11:17:02 +01:00
# include "IncrementalExecutor.h"
2012-10-19 11:49:49 +00:00
2012-10-01 11:47:27 +00:00
# include "clang/AST/ASTContext.h"
2012-09-05 09:37:39 +00:00
# include "clang/AST/DeclBase.h"
2012-10-01 11:47:27 +00:00
# include "clang/AST/PrettyPrinter.h"
2013-10-25 15:22:45 +02:00
# include "clang/Lex/MacroInfo.h"
2014-03-28 14:53:34 +01:00
# include "clang/Lex/Preprocessor.h"
# include "clang/Sema/Sema.h"
2015-02-03 21:32:09 +01:00
# include "llvm/IR/Module.h"
2014-03-28 14:53:34 +01:00
# include "llvm/Support/raw_ostream.h"
2012-09-05 09:37:39 +00:00
using namespace clang ;
namespace cling {
2014-03-28 14:53:34 +01:00
Transaction : : Transaction ( Sema & S ) : m_Sema ( S ) {
Initialize ( S ) ;
2013-07-06 12:18:59 +02:00
}
2014-03-28 14:53:34 +01:00
Transaction : : Transaction ( const CompilationOptions & Opts , Sema & S )
: m_Sema ( S ) {
Initialize ( S ) ;
2013-07-06 12:18:59 +02:00
m_Opts = Opts ; // intentional copy.
}
2014-03-28 14:53:34 +01:00
void Transaction : : Initialize ( Sema & S ) {
2013-07-06 12:18:59 +02:00
m_NestedTransactions . reset ( 0 ) ;
2014-03-28 14:53:34 +01:00
m_Parent = 0 ;
2013-07-06 12:18:59 +02:00
m_State = kCollecting ;
m_IssuedDiags = kNone ;
m_Opts = CompilationOptions ( ) ;
2014-08-03 21:05:42 -05:00
m_Module = 0 ;
2015-06-08 14:46:51 +02:00
m_ExeUnload = { ( void * ) ( size_t ) - 1 } ;
2013-07-06 12:18:59 +02:00
m_WrapperFD = 0 ;
m_Next = 0 ;
2014-03-28 14:53:34 +01:00
//m_Sema = S;
2013-12-03 15:31:31 +01:00
m_BufferFID = FileID ( ) ; // sets it to invalid.
2015-02-10 11:17:02 +01:00
m_Exe = 0 ;
2013-07-06 12:18:59 +02:00
}
2012-09-05 09:37:39 +00:00
Transaction : : ~ Transaction ( ) {
2013-04-08 14:27:57 +00:00
if ( hasNestedTransactions ( ) )
2013-06-13 12:45:15 +02:00
for ( size_t i = 0 ; i < m_NestedTransactions - > size ( ) ; + + i ) {
2014-08-03 21:05:42 -05:00
assert ( ( ( * m_NestedTransactions ) [ i ] - > getState ( ) = = kCommitted
2013-11-27 13:58:37 +01:00
| | ( * m_NestedTransactions ) [ i ] - > getState ( ) = = kRolledBack )
2013-06-13 12:45:15 +02:00
& & " All nested transactions must be committed! " ) ;
2013-04-08 14:27:57 +00:00
delete ( * m_NestedTransactions ) [ i ] ;
2013-06-13 12:45:15 +02:00
}
2012-09-05 09:37:39 +00:00
}
2014-08-03 15:27:33 +02:00
NamedDecl * Transaction : : containsNamedDecl ( llvm : : StringRef name ) const {
for ( auto I = decls_begin ( ) , E = decls_end ( ) ; I < E ; + + I )
for ( auto DI : I - > m_DGR ) {
if ( NamedDecl * ND = dyn_cast < NamedDecl > ( DI ) )
if ( name . equals ( ND - > getNameAsString ( ) ) )
return ND ;
}
return 0 ;
}
2013-07-06 12:16:35 +02:00
void Transaction : : addNestedTransaction ( Transaction * nested ) {
// Create lazily the list
if ( ! m_NestedTransactions )
m_NestedTransactions . reset ( new NestedTransactions ( ) ) ;
nested - > setParent ( this ) ;
// Leave a marker in the parent transaction, where the nested transaction
// started.
DelayCallInfo marker ( clang : : DeclGroupRef ( ) , Transaction : : kCCINone ) ;
2013-07-06 12:53:54 +02:00
m_DeclQueue . push_back ( marker ) ;
2013-07-06 12:16:35 +02:00
m_NestedTransactions - > push_back ( nested ) ;
}
2013-06-20 18:21:21 +02:00
void Transaction : : removeNestedTransaction ( Transaction * nested ) {
assert ( hasNestedTransactions ( ) & & " Does not contain nested transactions " ) ;
int nestedPos = - 1 ;
for ( size_t i = 0 ; i < m_NestedTransactions - > size ( ) ; + + i )
if ( ( * m_NestedTransactions ) [ i ] = = nested ) {
nestedPos = i ;
break ;
}
assert ( nestedPos > - 1 & & " Not found!? " ) ;
m_NestedTransactions - > erase ( m_NestedTransactions - > begin ( ) + nestedPos ) ;
// We need to remove the marker too.
2013-07-06 12:28:52 +02:00
int markerPos = - 1 ;
2013-11-25 14:26:15 +01:00
for ( iterator I = decls_begin ( ) , E = decls_end ( ) ; I ! = E ; + + I ) {
if ( I - > m_DGR . isNull ( ) & & I - > m_Call = = kCCINone ) {
2013-07-06 12:28:52 +02:00
+ + markerPos ;
if ( nestedPos = = markerPos ) {
2013-11-25 14:26:15 +01:00
erase ( I ) ; // Safe because of the break stmt.
2013-07-06 12:28:52 +02:00
break ;
}
2013-06-20 18:21:21 +02:00
}
}
2013-07-06 12:53:54 +02:00
if ( ! m_NestedTransactions - > size ( ) )
m_NestedTransactions . reset ( 0 ) ;
2013-06-20 18:21:21 +02:00
}
2012-12-03 14:27:12 +00:00
void Transaction : : append ( DelayCallInfo DCI ) {
2013-06-12 14:48:47 +02:00
assert ( ! DCI . m_DGR . isNull ( ) & & " Appending null DGR?! " ) ;
2013-06-13 12:47:16 +02:00
assert ( getState ( ) = = kCollecting
& & " Cannot append declarations in current state. " ) ;
2013-06-13 14:53:58 +02:00
forceAppend ( DCI ) ;
}
void Transaction : : forceAppend ( DelayCallInfo DCI ) {
assert ( ! DCI . m_DGR . isNull ( ) & & " Appending null DGR?! " ) ;
2013-07-31 09:04:30 +02:00
assert ( ( getState ( ) = = kCollecting | | getState ( ) = = kCompleted )
& & " Must not be " ) ;
2013-06-21 15:39:28 +02:00
2013-09-10 12:41:41 +02:00
bool checkForWrapper = ! m_WrapperFD ;
2013-06-26 14:56:11 +02:00
# ifndef NDEBUG
2013-06-21 15:39:28 +02:00
// Check for duplicates
2013-07-06 12:53:54 +02:00
for ( size_t i = 0 , e = m_DeclQueue . size ( ) ; i < e ; + + i ) {
DelayCallInfo & oldDCI ( m_DeclQueue [ i ] ) ;
2014-08-03 21:05:42 -05:00
// FIXME: This is possible bug in clang, which will instantiate one and
2013-08-08 14:50:44 +02:00
// the same CXXStaticMemberVar several times. This happens when there are
2014-08-03 21:05:42 -05:00
// two dependent expressions and the first uses another declaration from
2013-08-08 14:50:44 +02:00
// the redeclaration chain. This will force Sema in to instantiate the
// definition (usually the most recent decl in the chain) and then the
// second expression might referece the definition (which was already)
// instantiated, but Sema seems not to keep track of these kinds of
// instantiations, even though the points of instantiation are the same!
//
// This should be investigated further when we merge with newest clang.
// This is triggered by running the roottest: ./root/io/newstl
if ( oldDCI . m_Call = = kCCIHandleCXXStaticMemberVarInstantiation )
continue ;
2013-06-27 14:54:40 +02:00
// It is possible to have duplicate calls to HandleVTable with the same
// declaration, because each time Sema believes a vtable is used it emits
2014-08-03 21:05:42 -05:00
// that callback.
2013-06-27 14:54:40 +02:00
// For reference (clang::CodeGen::CodeGenModule::EmitVTable).
2016-06-13 13:50:48 +02:00
if ( oldDCI . m_Call ! = kCCIHandleVTable
& & oldDCI . m_Call ! = kCCIHandleCXXImplicitFunctionInstantiation )
2013-06-27 14:54:40 +02:00
assert ( oldDCI ! = DCI & & " Duplicates?! " ) ;
}
2013-09-10 12:41:41 +02:00
// We want to assert there is only one wrapper per transaction.
checkForWrapper = true ;
2013-06-21 15:39:28 +02:00
# endif
2014-08-03 21:05:42 -05:00
2013-04-09 08:47:47 +00:00
// register the wrapper if any.
2013-09-10 12:41:41 +02:00
if ( checkForWrapper & & ! DCI . m_DGR . isNull ( ) & & DCI . m_DGR . isSingleDecl ( ) ) {
2013-09-10 12:35:39 +02:00
if ( FunctionDecl * FD = dyn_cast < FunctionDecl > ( DCI . m_DGR . getSingleDecl ( ) ) ) {
2013-08-27 17:25:37 -05:00
if ( checkForWrapper & & utils : : Analyze : : IsWrapper ( FD ) ) {
2012-10-19 11:49:49 +00:00
assert ( ! m_WrapperFD & & " Two wrappers in one transaction? " ) ;
m_WrapperFD = FD ;
}
2013-08-27 17:25:37 -05:00
}
2012-10-19 11:49:49 +00:00
}
2014-08-03 21:05:42 -05:00
2013-08-02 16:20:54 +02:00
if ( comesFromASTReader ( DCI . m_DGR ) )
m_DeserializedDeclQueue . push_back ( DCI ) ;
else
m_DeclQueue . push_back ( DCI ) ;
2012-12-03 14:27:12 +00:00
}
void Transaction : : append ( clang : : DeclGroupRef DGR ) {
append ( DelayCallInfo ( DGR , kCCIHandleTopLevelDecl ) ) ;
2012-09-05 09:37:39 +00:00
}
2012-12-03 14:27:12 +00:00
void Transaction : : append ( Decl * D ) {
append ( DeclGroupRef ( D ) ) ;
2012-11-21 02:26:05 +00:00
}
2013-06-13 14:53:58 +02:00
void Transaction : : forceAppend ( Decl * D ) {
forceAppend ( DelayCallInfo ( DeclGroupRef ( D ) , kCCIHandleTopLevelDecl ) ) ;
}
2013-10-21 17:31:21 +02:00
2013-11-18 14:44:23 +01:00
void Transaction : : append ( MacroDirectiveInfo MDE ) {
assert ( MDE . m_II & & " Appending null IdentifierInfo?! " ) ;
assert ( MDE . m_MD & & " Appending null MacroDirective?! " ) ;
2013-10-21 17:31:21 +02:00
assert ( getState ( ) = = kCollecting
& & " Cannot append declarations in current state. " ) ;
# ifndef NDEBUG
// Check for duplicates
2013-11-18 14:44:23 +01:00
for ( size_t i = 0 , e = m_MacroDirectiveInfoQueue . size ( ) ; i < e ; + + i ) {
MacroDirectiveInfo & oldMacroDirectiveInfo ( m_MacroDirectiveInfoQueue [ i ] ) ;
assert ( oldMacroDirectiveInfo ! = MDE & & " Duplicates?! " ) ;
2013-10-21 17:31:21 +02:00
}
# endif
2013-11-18 14:44:23 +01:00
m_MacroDirectiveInfoQueue . push_back ( MDE ) ;
2013-10-29 10:43:48 +01:00
}
2014-02-20 15:10:46 +01:00
unsigned Transaction : : getUniqueID ( ) const {
return m_BufferFID . getHashValue ( ) ;
}
2013-10-24 11:46:42 -05:00
void Transaction : : erase ( iterator pos ) {
2013-04-24 15:04:09 +00:00
assert ( ! empty ( ) & & " Erasing from an empty transaction. " ) ;
2013-10-24 11:46:42 -05:00
if ( ! pos - > m_DGR . isNull ( ) & & m_WrapperFD = = * pos - > m_DGR . begin ( ) )
m_WrapperFD = 0 ;
2013-10-29 13:06:19 -05:00
m_DeclQueue . erase ( pos ) ;
2013-04-24 09:57:30 +00:00
}
2012-11-21 02:26:05 +00:00
2013-08-26 17:30:20 +02:00
void Transaction : : DelayCallInfo : : dump ( ) const {
PrintingPolicy Policy ( ( LangOptions ( ) ) ) ;
print ( llvm : : errs ( ) , Policy , /*Indent*/ 0 , /*PrintInstantiation*/ true ) ;
}
2014-08-03 21:05:42 -05:00
void Transaction : : DelayCallInfo : : print ( llvm : : raw_ostream & Out ,
2013-08-26 17:30:20 +02:00
const PrintingPolicy & Policy ,
2014-08-03 21:05:42 -05:00
unsigned Indent ,
bool PrintInstantiation ,
2013-08-28 11:12:44 +02:00
llvm : : StringRef prependInfo /*=""*/ ) const {
2013-08-26 17:30:20 +02:00
static const char * const stateNames [ Transaction : : kCCINumStates ] = {
" kCCINone " ,
" kCCIHandleTopLevelDecl " ,
" kCCIHandleInterestingDecl " ,
" kCCIHandleTagDeclDefinition " ,
" kCCIHandleVTable " ,
" kCCIHandleCXXImplicitFunctionInstantiation " ,
" kCCIHandleCXXStaticMemberVarInstantiation " ,
2014-02-08 14:50:13 +01:00
" kCCICompleteTentativeDefinition " ,
2013-08-26 17:30:20 +02:00
} ;
2014-08-03 21:05:42 -05:00
assert ( ( sizeof ( stateNames ) / sizeof ( void * ) ) = = Transaction : : kCCINumStates
2013-08-26 17:30:20 +02:00
& & " Missing states? " ) ;
2013-08-28 11:12:44 +02:00
if ( ! prependInfo . empty ( ) ) {
2013-08-26 17:30:20 +02:00
Out . changeColor ( llvm : : raw_ostream : : RED ) ;
Out < < prependInfo ;
Out . resetColor ( ) ;
Out < < " , " ;
}
Out . changeColor ( llvm : : raw_ostream : : BLUE ) ;
2014-08-03 21:05:42 -05:00
Out < < stateNames [ m_Call ] ;
2013-08-26 17:30:20 +02:00
Out . changeColor ( llvm : : raw_ostream : : GREEN ) ;
Out < < " <- " ;
Out . resetColor ( ) ;
2014-08-03 21:05:42 -05:00
for ( DeclGroupRef : : const_iterator I = m_DGR . begin ( ) , E = m_DGR . end ( ) ;
2013-08-30 10:39:06 +02:00
I ! = E ; + + I ) {
2013-08-26 17:30:20 +02:00
if ( * I )
( * I ) - > print ( Out , Policy , Indent , PrintInstantiation ) ;
else
Out < < " <<NULL DECL>> " ;
2013-08-30 10:39:06 +02:00
Out < < ' \n ' ;
}
2013-08-26 17:30:20 +02:00
}
2012-10-24 07:34:53 +00:00
2014-03-28 14:53:34 +01:00
void Transaction : : MacroDirectiveInfo : : dump ( const clang : : Preprocessor & PP ) const {
print ( llvm : : errs ( ) , PP ) ;
}
void Transaction : : MacroDirectiveInfo : : print ( llvm : : raw_ostream & Out ,
const clang : : Preprocessor & PP ) const {
PP . printMacro ( this - > m_II , this - > m_MD , Out ) ;
}
2013-08-26 17:30:20 +02:00
void Transaction : : dump ( ) const {
2014-03-28 14:53:34 +01:00
const ASTContext & C = m_Sema . getASTContext ( ) ;
2012-10-08 10:38:52 +00:00
PrintingPolicy Policy = C . getPrintingPolicy ( ) ;
2013-01-17 15:27:14 +00:00
print ( llvm : : errs ( ) , Policy , /*Indent*/ 0 , /*PrintInstantiation*/ true ) ;
2012-10-01 11:47:27 +00:00
}
void Transaction : : dumpPretty ( ) const {
2014-03-28 14:53:34 +01:00
const ASTContext & C = m_Sema . getASTContext ( ) ;
2013-08-23 09:35:11 +02:00
PrintingPolicy Policy ( C . getLangOpts ( ) ) ;
2013-01-17 15:27:14 +00:00
print ( llvm : : errs ( ) , Policy , /*Indent*/ 0 , /*PrintInstantiation*/ true ) ;
2012-10-01 11:47:27 +00:00
}
void Transaction : : print ( llvm : : raw_ostream & Out , const PrintingPolicy & Policy ,
unsigned Indent , bool PrintInstantiation ) const {
2012-09-05 09:37:39 +00:00
int nestedT = 0 ;
for ( const_iterator I = decls_begin ( ) , E = decls_end ( ) ; I ! = E ; + + I ) {
2012-12-03 14:27:12 +00:00
if ( I - > m_DGR . isNull ( ) ) {
2012-09-05 09:37:39 +00:00
assert ( hasNestedTransactions ( ) & & " DGR is null even if no nesting? " ) ;
// print the nested decl
2012-11-19 21:17:28 +00:00
Out < < " \n " ;
2012-10-01 11:47:27 +00:00
Out < < " +====================================================+ \n " ;
2012-11-19 21:17:28 +00:00
Out < < " Nested Transaction " < < nestedT < < " \n " ;
2012-10-01 11:47:27 +00:00
Out < < " +====================================================+ \n " ;
2014-03-28 14:53:34 +01:00
( * m_NestedTransactions ) [ nestedT + + ] - > print ( Out , Policy , Indent ,
2013-04-08 14:27:57 +00:00
PrintInstantiation ) ;
2012-11-19 21:17:28 +00:00
Out < < " \n " ;
2012-10-01 11:47:27 +00:00
Out < < " +====================================================+ \n " ;
2012-11-19 21:17:28 +00:00
Out < < " End Transaction " < < nestedT < < " \n " ;
2012-10-01 11:47:27 +00:00
Out < < " +====================================================+ \n " ;
2012-09-05 09:37:39 +00:00
}
2013-08-26 17:57:33 +02:00
I - > print ( Out , Policy , Indent , PrintInstantiation ) ;
}
// Print the deserialized decls if any.
2014-03-28 14:53:34 +01:00
for ( const_iterator I = deserialized_decls_begin ( ) ,
2013-08-26 17:57:33 +02:00
E = deserialized_decls_end ( ) ; I ! = E ; + + I ) {
assert ( ! I - > m_DGR . isNull ( ) & & " Must not contain null DGR. " ) ;
I - > print ( Out , Policy , Indent , PrintInstantiation , " Deserialized " ) ;
2012-09-05 09:37:39 +00:00
}
2014-03-28 14:53:34 +01:00
for ( Transaction : : const_reverse_macros_iterator MI = rmacros_begin ( ) ,
ME = rmacros_end ( ) ; MI ! = ME ; + + MI ) {
MI - > print ( Out , m_Sema . getPreprocessor ( ) ) ;
}
2012-09-05 09:37:39 +00:00
}
2013-04-05 13:12:57 +00:00
void Transaction : : printStructure ( size_t nindent ) const {
2013-04-24 15:04:09 +00:00
static const char * const stateNames [ kNumStates ] = {
2013-04-05 13:12:57 +00:00
" Collecting " ,
2013-04-24 12:51:09 +00:00
" kCompleted " ,
2013-04-05 13:12:57 +00:00
" RolledBack " ,
" RolledBackWithErrors " ,
" Committed "
} ;
2014-08-03 21:05:42 -05:00
assert ( ( sizeof ( stateNames ) / sizeof ( void * ) ) = = kNumStates
2013-08-26 17:23:30 +02:00
& & " Missing a state to print. " ) ;
2013-04-05 13:12:57 +00:00
std : : string indent ( nindent , ' ' ) ;
llvm : : errs ( ) < < indent < < " Transaction @ " < < this < < " : \n " ;
2014-08-03 21:05:42 -05:00
for ( const_nested_iterator I = nested_begin ( ) , E = nested_end ( ) ;
2013-04-08 14:35:35 +00:00
I ! = E ; + + I ) {
2013-04-24 12:51:09 +00:00
( * I ) - > printStructure ( nindent + 3 ) ;
2013-04-05 13:12:57 +00:00
}
2013-11-25 14:26:15 +01:00
llvm : : errs ( ) < < indent < < " state: " < < stateNames [ getState ( ) ]
< < " decl groups, " ;
2013-04-24 12:51:09 +00:00
if ( hasNestedTransactions ( ) )
llvm : : errs ( ) < < m_NestedTransactions - > size ( ) ;
else
llvm : : errs ( ) < < " 0 " ;
llvm : : errs ( ) < < " nested transactions \n "
2013-04-05 13:12:57 +00:00
< < indent < < " wrapper: " < < m_WrapperFD
< < " , parent: " < < m_Parent
< < " , next: " < < m_Next < < " \n " ;
}
2013-08-04 18:21:35 +02:00
void Transaction : : printStructureBrief ( size_t nindent /*=0*/ ) const {
2013-07-06 12:33:25 +02:00
std : : string indent ( nindent , ' ' ) ;
2014-08-03 21:05:42 -05:00
llvm : : errs ( ) < < indent < < " <cling::Transaction* " < < this
2013-08-04 18:21:35 +02:00
< < " isEmpty= " < < empty ( ) ;
2013-08-02 16:19:38 +02:00
llvm : : errs ( ) < < " isCommitted= " < < ( getState ( ) = = kCommitted ) ;
llvm : : errs ( ) < < " > \n " ;
2013-07-06 12:33:25 +02:00
2014-08-03 21:05:42 -05:00
for ( const_nested_iterator I = nested_begin ( ) , E = nested_end ( ) ;
2013-07-06 12:33:25 +02:00
I ! = E ; + + I ) {
llvm : : errs ( ) < < indent < < " ` " ;
( * I ) - > printStructureBrief ( nindent + 3 ) ;
}
}
2013-08-02 16:20:54 +02:00
bool Transaction : : comesFromASTReader ( DeclGroupRef DGR ) const {
assert ( ! DGR . isNull ( ) & & " DeclGroupRef is Null! " ) ;
if ( getCompilationOpts ( ) . CodeGenerationForModule )
return true ;
// Take the first/only decl in the group.
Decl * D = * DGR . begin ( ) ;
return D - > isFromASTFile ( ) ;
}
2012-09-05 09:37:39 +00:00
} // end namespace cling