2012-09-05 09:37:39 +00:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------
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"
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-04-24 16:28:08 +00:00
# include "llvm/Support/raw_ostream.h"
2012-09-05 09:37:39 +00:00
using namespace clang ;
namespace cling {
2013-07-06 12:18:59 +02:00
Transaction : : Transaction ( ) {
Initialize ( ) ;
}
Transaction : : Transaction ( const CompilationOptions & Opts ) {
Initialize ( ) ;
m_Opts = Opts ; // intentional copy.
}
void Transaction : : Initialize ( ) {
m_DeclQueue . reset ( 0 ) ;
m_NestedTransactions . reset ( 0 ) ;
m_Parent = 0 ;
m_State = kCollecting ;
m_IssuedDiags = kNone ;
m_Opts = CompilationOptions ( ) ;
m_Module = 0 ;
m_WrapperFD = 0 ;
m_Next = 0 ;
}
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 ) {
assert ( ( * m_NestedTransactions ) [ i ] - > getState ( ) = = kCommitted
& & " 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
}
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 ( ) ) ;
// Lazy create the container on first append.
if ( ! m_DeclQueue )
m_DeclQueue . reset ( new DeclQueue ( ) ) ;
nested - > setParent ( this ) ;
// Leave a marker in the parent transaction, where the nested transaction
// started.
DelayCallInfo marker ( clang : : DeclGroupRef ( ) , Transaction : : kCCINone ) ;
m_DeclQueue - > push_back ( marker ) ;
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-06-20 18:21:21 +02:00
for ( size_t i = 0 ; i < size ( ) ; + + i ) {
2013-07-06 12:28:52 +02:00
if ( ( * this ) [ i ] . m_DGR . isNull ( ) & & ( * this ) [ i ] . m_Call = = kCCINone ) {
+ + markerPos ;
if ( nestedPos = = markerPos ) {
erase ( i ) ;
break ;
}
2013-06-20 18:21:21 +02:00
}
}
}
void Transaction : : reset ( ) {
assert ( empty ( ) & & " The transaction must be empty. " ) ;
if ( Transaction * parent = getParent ( ) )
parent - > removeNestedTransaction ( this ) ;
m_Parent = 0 ;
m_State = kCollecting ;
m_IssuedDiags = kNone ;
m_Opts = CompilationOptions ( ) ;
//m_Module = 0; <- NOTE: we want to reuse the empty module
m_WrapperFD = 0 ;
m_Next = 0 ;
}
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-28 14:01:37 +02:00
# ifdef TEMPORARILY_DISABLED
2013-06-13 12:47:16 +02:00
assert ( getState ( ) = = kCollecting
& & " Cannot append declarations in current state. " ) ;
2013-06-28 14:01:37 +02:00
# endif
2013-06-13 14:53:58 +02:00
forceAppend ( DCI ) ;
}
void Transaction : : forceAppend ( DelayCallInfo DCI ) {
assert ( ! DCI . m_DGR . isNull ( ) & & " Appending null DGR?! " ) ;
2013-06-28 10:08:14 +02:00
assert ( getState ( ) ! = kCommitting & & " Must not be " ) ;
2013-06-21 15:39:28 +02:00
// Lazy create the container on first append.
if ( ! m_DeclQueue )
m_DeclQueue . reset ( new DeclQueue ( ) ) ;
2013-06-28 14:01:37 +02:00
# ifdef TEMPORARILY_DISABLED
2013-06-26 14:56:11 +02:00
# ifndef NDEBUG
2013-06-21 15:39:28 +02:00
// Check for duplicates
2013-06-27 14:54:40 +02:00
for ( size_t i = 0 , e = m_DeclQueue - > size ( ) ; i < e ; + + i ) {
DelayCallInfo & oldDCI ( ( * m_DeclQueue ) [ i ] ) ;
// It is possible to have duplicate calls to HandleVTable with the same
// declaration, because each time Sema believes a vtable is used it emits
// that callback.
// For reference (clang::CodeGen::CodeGenModule::EmitVTable).
if ( oldDCI . m_Call ! = kCCIHandleVTable )
assert ( oldDCI ! = DCI & & " Duplicates?! " ) ;
}
2013-06-28 14:01:37 +02:00
# endif
2013-06-21 15:39:28 +02:00
# endif
2013-03-28 14:48:13 +00:00
bool checkForWrapper = ! m_WrapperFD ;
assert ( checkForWrapper = true & & " Check for wrappers with asserts " ) ;
2013-04-09 08:47:47 +00:00
// register the wrapper if any.
2013-04-09 15:35:38 +00:00
if ( checkForWrapper & & ! DCI . m_DGR . isNull ( ) & & DCI . m_DGR . isSingleDecl ( ) ) {
2012-12-03 14:27:12 +00:00
if ( FunctionDecl * FD = dyn_cast < FunctionDecl > ( DCI . m_DGR . getSingleDecl ( ) ) )
2012-10-19 11:49:49 +00:00
if ( utils : : Analyze : : IsWrapper ( FD ) ) {
assert ( ! m_WrapperFD & & " Two wrappers in one transaction? " ) ;
m_WrapperFD = FD ;
}
}
2013-04-05 13:43:01 +00:00
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-04-24 09:57:30 +00:00
void Transaction : : erase ( size_t pos ) {
2013-04-24 15:04:09 +00:00
assert ( ! empty ( ) & & " Erasing from an empty transaction. " ) ;
2013-04-24 09:57:30 +00:00
m_DeclQueue - > erase ( decls_begin ( ) + pos ) ;
}
2012-11-21 02:26:05 +00:00
2012-09-05 09:37:39 +00:00
void Transaction : : dump ( ) const {
2012-10-24 07:34:53 +00:00
if ( ! size ( ) )
return ;
2012-10-08 10:38:52 +00:00
ASTContext & C = getFirstDecl ( ) . getSingleDecl ( ) - > getASTContext ( ) ;
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 {
2012-10-24 07:34:53 +00:00
if ( ! size ( ) )
return ;
2012-11-20 13:20:22 +00:00
ASTContext * C = 0 ;
2012-11-19 21:17:28 +00:00
if ( m_WrapperFD )
C = & ( m_WrapperFD - > getASTContext ( ) ) ;
if ( ! getFirstDecl ( ) . isNull ( ) )
C = & ( getFirstDecl ( ) . getSingleDecl ( ) - > getASTContext ( ) ) ;
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 " ;
2013-04-08 14:27:57 +00:00
( * m_NestedTransactions ) [ nestedT + + ] - > print ( Out , Policy , Indent ,
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
}
2012-12-03 14:27:12 +00:00
for ( DeclGroupRef : : const_iterator J = I - > m_DGR . begin ( ) ,
L = I - > m_DGR . end ( ) ; J ! = L ; + + J )
2012-10-14 14:36:40 +00:00
if ( * J )
( * J ) - > print ( Out , Policy , Indent , PrintInstantiation ) ;
else
Out < < " <<NULL DECL>> " ;
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-24 15:04:09 +00:00
" Committing " ,
2013-04-05 13:12:57 +00:00
" RolledBack " ,
" RolledBackWithErrors " ,
" Committed "
} ;
std : : string indent ( nindent , ' ' ) ;
llvm : : errs ( ) < < indent < < " Transaction @ " < < this < < " : \n " ;
2013-04-08 14:35:35 +00:00
for ( const_nested_iterator I = nested_begin ( ) , E = nested_end ( ) ;
I ! = E ; + + I ) {
2013-04-24 12:51:09 +00:00
( * I ) - > printStructure ( nindent + 3 ) ;
2013-04-05 13:12:57 +00:00
}
llvm : : errs ( ) < < indent < < " state: " < < stateNames [ getState ( ) ] < < " , "
2013-04-24 12:51:09 +00:00
< < size ( ) < < " decl groups, " ;
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-07-06 12:33:25 +02:00
void cling : : Transaction : : printStructureBrief ( size_t nindent /*=0*/ ) const {
std : : string indent ( nindent , ' ' ) ;
llvm : : errs ( ) < < indent < < " <T @ " < < this < < " empty= " < < empty ( ) < < " > \n " ;
for ( const_nested_iterator I = nested_begin ( ) , E = nested_end ( ) ;
I ! = E ; + + I ) {
llvm : : errs ( ) < < indent < < " ` " ;
( * I ) - > printStructureBrief ( nindent + 3 ) ;
}
}
2012-09-05 09:37:39 +00:00
} // end namespace cling