2014-07-12 22:23:55 +04:00
# include "llvm/ADT/SmallVector.h"
# include "llvm/Support/Path.h"
# include "clang/Sema/Sema.h"
# include "clang/Basic/Diagnostic.h"
# include "clang/AST/AST.h"
2014-08-05 23:35:25 +04:00
# include "clang/AST/RecursiveASTVisitor.h"
2014-07-12 22:23:55 +04:00
# include "clang/Lex/Preprocessor.h"
2014-07-13 20:43:20 +04:00
# include "clang/Frontend/CompilerInstance.h"
2014-07-12 22:23:55 +04:00
2014-06-08 20:42:58 +04:00
# include "cling/Interpreter/Interpreter.h"
# include "cling/Interpreter/InterpreterCallbacks.h"
2014-06-08 01:52:32 +04:00
# include "cling/Interpreter/AutoloadCallback.h"
2014-07-13 20:43:20 +04:00
# include "cling/Interpreter/Transaction.h"
2014-07-12 22:23:55 +04:00
2014-06-08 01:52:32 +04:00
using namespace clang ;
namespace cling {
2014-07-12 22:23:55 +04:00
2014-06-08 01:52:32 +04:00
void AutoloadCallback : : report ( clang : : SourceLocation l , std : : string name , std : : string header ) {
Sema & sema = m_Interpreter - > getSema ( ) ;
unsigned id
= sema . getDiagnostics ( ) . getCustomDiagID ( DiagnosticsEngine : : Level : : Warning ,
" Note: '%0' can be found in %1 " ) ;
/* unsigned idn //TODO: To be enabled after we have a way to get the full path
= sema . getDiagnostics ( ) . getCustomDiagID ( DiagnosticsEngine : : Level : : Note ,
" Type : %0 , Full Path: %1 " ) */ ;
sema . Diags . Report ( l , id ) < < name < < header ;
}
2014-08-05 04:12:08 +04:00
bool AutoloadCallback : : LookupObject ( TagDecl * t ) {
if ( t - > hasAttr < AnnotateAttr > ( ) )
report ( t - > getLocation ( ) , t - > getNameAsString ( ) , t - > getAttr < AnnotateAttr > ( ) - > getAnnotation ( ) ) ;
return false ;
}
2014-07-12 22:23:55 +04:00
2014-08-05 23:35:25 +04:00
class DefaultArgRemover : public RecursiveASTVisitor < DefaultArgRemover > {
public :
void Remove ( Decl * D ) {
TraverseDecl ( D ) ;
2014-07-12 22:23:55 +04:00
}
2014-08-05 23:35:25 +04:00
bool VisitTemplateTypeParmDecl ( TemplateTypeParmDecl * D ) {
if ( D - > hasDefaultArgument ( ) )
D - > removeDefaultArgument ( ) ;
return true ;
}
bool VisitNonTypeTemplateParmDecl ( NonTypeTemplateParmDecl * D ) {
if ( D - > hasDefaultArgument ( ) )
D - > removeDefaultArgument ( ) ;
return true ;
2014-07-13 21:15:08 +04:00
}
2014-08-05 23:35:25 +04:00
bool VisitParmVarDecl ( ParmVarDecl * D ) {
if ( D - > hasDefaultArg ( ) )
D - > setDefaultArg ( nullptr ) ;
return true ;
}
} ;
2014-06-08 01:52:32 +04:00
2014-07-12 22:23:55 +04:00
void AutoloadCallback : : InclusionDirective ( clang : : SourceLocation HashLoc ,
const clang : : Token & IncludeTok ,
llvm : : StringRef FileName ,
bool IsAngled ,
clang : : CharSourceRange FilenameRange ,
const clang : : FileEntry * File ,
llvm : : StringRef SearchPath ,
llvm : : StringRef RelativePath ,
const clang : : Module * Imported ) {
2014-07-30 01:14:15 +04:00
assert ( File & & " Must have a valid File " ) ;
2014-07-13 20:43:20 +04:00
auto iterator = m_Map . find ( File - > getUID ( ) ) ;
if ( iterator = = m_Map . end ( ) )
2014-07-12 22:23:55 +04:00
return ; // nothing to do, file not referred in any annotation
if ( iterator - > second . Included )
return ; // nothing to do, file already included once
iterator - > second . Included = true ;
2014-08-05 23:35:25 +04:00
DefaultArgRemover defaultArgsCleaner ;
2014-07-12 22:23:55 +04:00
for ( clang : : Decl * decl : iterator - > second . Decls ) {
decl - > dropAttrs ( ) ;
2014-08-05 23:35:25 +04:00
defaultArgsCleaner . Remove ( decl ) ;
2014-07-12 22:23:55 +04:00
}
}
2014-06-08 01:52:32 +04:00
AutoloadCallback : : AutoloadCallback ( Interpreter * interp ) :
2014-07-12 22:23:55 +04:00
InterpreterCallbacks ( interp , true , false , true ) , m_Interpreter ( interp ) {
2014-07-22 20:30:30 +04:00
2014-06-08 01:52:32 +04:00
}
2014-08-05 23:37:15 +04:00
2014-07-13 20:43:20 +04:00
AutoloadCallback : : ~ AutoloadCallback ( ) {
}
2014-07-30 01:14:15 +04:00
void AutoloadCallback : : InsertIntoAutoloadingState ( clang : : Decl * decl ,
std : : string annotation ) {
2014-07-13 20:43:20 +04:00
2014-08-05 23:36:31 +04:00
assert ( annotation ! = " " & & " Empty annotation! " ) ;
2014-07-31 03:04:46 +04:00
2014-08-05 23:37:15 +04:00
clang : : Preprocessor & PP = m_Interpreter - > getCI ( ) - > getPreprocessor ( ) ;
const FileEntry * FE = 0 ;
SourceLocation fileNameLoc ;
bool isAngled = false ;
const DirectoryLookup * LookupFrom = 0 ;
const DirectoryLookup * CurDir = 0 ;
2014-07-13 20:43:20 +04:00
2014-08-05 23:37:15 +04:00
FE = PP . LookupFile ( fileNameLoc , annotation , isAngled , LookupFrom , CurDir ,
/*SearchPath*/ 0 , /*RelativePath*/ 0 ,
/*suggestedModule*/ 0 , /*SkipCache*/ false ,
/*OpenFile*/ false , /*CacheFail*/ false ) ;
2014-07-13 20:43:20 +04:00
2014-08-05 23:37:15 +04:00
assert ( FE & & " Must have a valid FileEntry " ) ;
2014-07-13 20:43:20 +04:00
2014-08-05 23:37:15 +04:00
auto & stateMap = m_Map ;
auto iterator = stateMap . find ( FE - > getUID ( ) ) ;
2014-07-13 20:43:20 +04:00
2014-08-05 23:37:15 +04:00
if ( iterator = = stateMap . end ( ) )
stateMap [ FE - > getUID ( ) ] = FileInfo ( ) ;
2014-07-13 20:43:20 +04:00
2014-08-05 23:37:15 +04:00
stateMap [ FE - > getUID ( ) ] . Decls . push_back ( decl ) ;
2014-07-13 20:43:20 +04:00
}
void AutoloadCallback : : HandleNamespace ( NamespaceDecl * NS ) {
std : : vector < clang : : Decl * > decls ;
for ( auto dit = NS - > decls_begin ( ) ; dit ! = NS - > decls_end ( ) ; + + dit )
decls . push_back ( * dit ) ;
HandleDeclVector ( decls ) ;
}
void AutoloadCallback : : HandleClassTemplate ( ClassTemplateDecl * CT ) {
CXXRecordDecl * cxxr = CT - > getTemplatedDecl ( ) ;
if ( cxxr - > hasAttr < AnnotateAttr > ( ) )
InsertIntoAutoloadingState ( CT , cxxr - > getAttr < AnnotateAttr > ( ) - > getAnnotation ( ) ) ;
}
2014-07-13 21:15:08 +04:00
void AutoloadCallback : : HandleFunction ( FunctionDecl * F ) {
if ( F - > hasAttr < AnnotateAttr > ( ) )
InsertIntoAutoloadingState ( F , F - > getAttr < AnnotateAttr > ( ) - > getAnnotation ( ) ) ;
}
2014-07-13 20:43:20 +04:00
void AutoloadCallback : : HandleDeclVector ( std : : vector < clang : : Decl * > Decls ) {
for ( auto decl : Decls ) {
if ( auto ct = llvm : : dyn_cast < ClassTemplateDecl > ( decl ) )
HandleClassTemplate ( ct ) ;
if ( auto ns = llvm : : dyn_cast < NamespaceDecl > ( decl ) )
HandleNamespace ( ns ) ;
2014-07-13 21:15:08 +04:00
if ( auto f = llvm : : dyn_cast < FunctionDecl > ( decl ) )
HandleFunction ( f ) ;
2014-07-13 20:43:20 +04:00
}
}
void AutoloadCallback : : TransactionCommitted ( const Transaction & T ) {
for ( Transaction : : const_iterator I = T . decls_begin ( ) , E = T . decls_end ( ) ;
I ! = E ; + + I ) {
Transaction : : DelayCallInfo DCI = * I ;
2014-08-05 23:48:19 +04:00
if ( DCI . m_Call ! = Transaction : : kCCIHandleTopLevelDecl )
continue ;
2014-07-13 20:43:20 +04:00
std : : vector < clang : : Decl * > decls ;
for ( DeclGroupRef : : iterator J = DCI . m_DGR . begin ( ) ,
JE = DCI . m_DGR . end ( ) ; J ! = JE ; + + J ) {
decls . push_back ( * J ) ;
}
HandleDeclVector ( decls ) ;
}
}
2014-06-08 01:52:32 +04:00
} //end namespace cling