2013-02-27 15:28:38 +00:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vasil.georgiev.vasilev@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.
2013-02-27 15:28:38 +00:00
//------------------------------------------------------------------------------
# include "AutoSynthesizer.h"
# include "cling/Interpreter/Transaction.h"
# include "clang/AST/ASTContext.h"
# include "clang/AST/RecursiveASTVisitor.h"
# include "clang/Sema/Sema.h"
using namespace clang ;
namespace cling {
class AutoFixer : public RecursiveASTVisitor < AutoFixer > {
private :
Sema * m_Sema ;
2013-10-11 16:23:01 +02:00
DeclRefExpr * m_FoundDRE ;
llvm : : DenseSet < NamedDecl * > m_HandledDecls ;
2013-02-27 15:28:38 +00:00
private :
public :
2013-10-11 16:23:01 +02:00
AutoFixer ( Sema * S ) : m_Sema ( S ) , m_FoundDRE ( 0 ) { }
2013-02-27 15:28:38 +00:00
void Fix ( CompoundStmt * CS ) {
2013-10-11 16:23:01 +02:00
if ( ! CS - > size ( ) )
return ;
typedef llvm : : SmallVector < Stmt * , 32 > Statements ;
Statements Stmts ;
Stmts . append ( CS - > body_begin ( ) , CS - > body_end ( ) ) ;
2013-10-14 09:58:39 +02:00
for ( Statements : : iterator I = Stmts . begin ( ) ; I ! = Stmts . end ( ) ; + + I ) {
2013-10-11 16:23:01 +02:00
if ( ! TraverseStmt ( * I ) & & ! m_HandledDecls . count ( m_FoundDRE - > getDecl ( ) ) ) {
2014-08-03 21:05:42 -05:00
Sema : : DeclGroupPtrTy VDPtrTy
2013-10-11 16:23:01 +02:00
= m_Sema - > ConvertDeclToDeclGroup ( m_FoundDRE - > getDecl ( ) ) ;
2014-08-03 21:05:42 -05:00
StmtResult DS = m_Sema - > ActOnDeclStmt ( VDPtrTy ,
m_FoundDRE - > getLocStart ( ) ,
2013-10-11 16:23:01 +02:00
m_FoundDRE - > getLocEnd ( ) ) ;
2013-02-27 15:28:38 +00:00
assert ( ! DS . isInvalid ( ) & & " Invalid DeclStmt. " ) ;
2013-12-05 20:57:51 +01:00
I = Stmts . insert ( I , DS . take ( ) ) ;
2013-10-11 16:23:01 +02:00
m_HandledDecls . insert ( m_FoundDRE - > getDecl ( ) ) ;
2013-02-27 15:28:38 +00:00
}
}
2013-10-11 16:23:01 +02:00
CS - > setStmts ( m_Sema - > getASTContext ( ) , Stmts . data ( ) , Stmts . size ( ) ) ;
}
bool VisitDeclRefExpr ( DeclRefExpr * DRE ) {
const Decl * D = DRE - > getDecl ( ) ;
if ( const AnnotateAttr * A = D - > getAttr < AnnotateAttr > ( ) )
if ( A - > getAnnotation ( ) . equals ( " __Auto " ) ) {
m_FoundDRE = DRE ;
return false ; // we abort on the first found candidate.
}
2013-02-27 15:28:38 +00:00
return true ; // returning false will abort the in-depth traversal.
}
} ;
} // end namespace cling
2014-08-03 21:05:42 -05:00
namespace cling {
2013-02-27 15:28:38 +00:00
AutoSynthesizer : : AutoSynthesizer ( clang : : Sema * S )
: TransactionTransformer ( S ) {
2013-10-11 16:23:01 +02:00
// TODO: We would like to keep that local without keeping track of all
// decls that were handled in the AutoFixer. This can be done by removing
// the __Auto attribute, but for now I am still hesitant to do it. Having
// the __Auto attribute is very useful for debugging because it localize the
// the problem if exists.
m_AutoFixer . reset ( new AutoFixer ( S ) ) ;
2013-02-27 15:28:38 +00:00
}
// pin the vtable here.
2014-08-03 21:05:42 -05:00
AutoSynthesizer : : ~ AutoSynthesizer ( )
2013-02-27 15:28:38 +00:00
{ }
void AutoSynthesizer : : Transform ( ) {
2013-11-25 14:26:15 +01:00
const Transaction * T = getTransaction ( ) ;
for ( Transaction : : const_iterator I = T - > decls_begin ( ) , E = T - > decls_end ( ) ;
I ! = E ; + + I ) {
// Copy DCI; it might get relocated below.
Transaction : : DelayCallInfo DCI = * I ;
2014-08-03 21:05:42 -05:00
for ( DeclGroupRef : : const_iterator J = DCI . m_DGR . begin ( ) ,
2013-11-25 14:26:15 +01:00
JE = DCI . m_DGR . end ( ) ; J ! = JE ; + + J )
2013-02-27 15:28:38 +00:00
if ( ( * J ) - > hasBody ( ) )
2013-10-11 16:23:01 +02:00
m_AutoFixer - > Fix ( cast < CompoundStmt > ( ( * J ) - > getBody ( ) ) ) ;
2013-03-11 13:11:15 +00:00
}
2013-02-27 15:28:38 +00:00
}
} // end namespace cling