2012-12-01 14:00:22 +00:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Timur Pocheptsov <Timur.Pocheptsov@cern.ch>
//------------------------------------------------------------------------------
2012-11-29 19:42:43 +00:00
# include "Display.h"
2012-11-28 16:38:02 +00:00
2012-12-01 14:04:29 +00:00
# include "cling/Interpreter/Interpreter.h"
# include "cling/Interpreter/LookupHelper.h"
# include "clang/AST/ASTContext.h"
# include "clang/AST/DeclBase.h"
# include "clang/AST/DeclCXX.h"
# include "clang/AST/DeclTemplate.h"
# include "clang/AST/PrettyPrinter.h"
# include "clang/AST/RecordLayout.h"
# include "clang/AST/Type.h"
2012-11-28 16:38:02 +00:00
# include "clang/Basic/IdentifierTable.h"
2012-12-01 14:04:29 +00:00
# include "clang/Basic/LangOptions.h"
2012-11-28 16:38:02 +00:00
# include "clang/Basic/SourceLocation.h"
# include "clang/Basic/SourceManager.h"
# include "clang/Basic/Specifiers.h"
2012-12-01 14:04:29 +00:00
# include "clang/Frontend/CompilerInstance.h"
2012-11-28 16:38:02 +00:00
# include "clang/Lex/MacroInfo.h"
2012-12-01 14:04:29 +00:00
# include "clang/Lex/Preprocessor.h"
2012-11-28 16:38:02 +00:00
2012-11-29 19:42:43 +00:00
# include "llvm/Support/Format.h"
2012-12-01 14:04:29 +00:00
# include "llvm/Support/FormattedStream.h"
2012-11-29 19:42:43 +00:00
# include "llvm/Support/PathV2.h"
# include <algorithm>
# include <cassert>
# include <cstring>
# include <cctype>
# include <limits>
# include <set>
2012-11-28 16:38:02 +00:00
2012-11-29 19:42:43 +00:00
using namespace clang ;
2012-11-28 16:38:02 +00:00
namespace cling {
namespace {
2012-11-29 19:42:43 +00:00
typedef DeclContext : : decl_iterator decl_iterator ;
typedef CXXRecordDecl : : base_class_const_iterator base_decl_iterator ;
2012-11-28 16:38:02 +00:00
//______________________________________________________________________________
template < class Decl >
2012-11-29 20:09:41 +00:00
bool HasUDT ( const Decl * decl )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
//Check the type of decl, if it's a CXXRecordDecl or array with base element type of CXXRecordDecl.
assert ( decl ! = 0 & & " HasUDT, 'decl' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
if ( const RecordType * const recordType = decl - > getType ( ) - > template getAs < RecordType > ( ) )
2012-11-29 19:48:39 +00:00
return cast_or_null < CXXRecordDecl > ( recordType - > getDecl ( ) - > getDefinition ( ) ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
if ( const ArrayType * const arrayType = decl - > getType ( ) - > getAsArrayTypeUnsafe ( ) ) {
if ( const Type * const elType = arrayType - > getBaseElementTypeUnsafe ( ) ) {
if ( const RecordType * const recordType = elType - > getAs < RecordType > ( ) )
2012-11-29 19:48:39 +00:00
return cast_or_null < CXXRecordDecl > ( recordType - > getDecl ( ) - > getDefinition ( ) ) ;
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
return false ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
int NumberOfElements ( const ArrayType * type )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( type ! = 0 & & " NumberOfElements, 'type' parameter is null " ) ;
2012-11-29 20:09:41 +00:00
if ( const ConstantArrayType * const arrayType = dyn_cast < ConstantArrayType > ( type ) ) {
2012-11-29 19:35:33 +00:00
//We can calculate only the size of constant size array.
2012-11-29 20:40:53 +00:00
//no conv. to int :(
const int nElements = int ( arrayType - > getSize ( ) . roundToDouble ( ) ) ;
2012-11-29 19:35:33 +00:00
if ( nElements < = 0 )
2012-11-28 16:38:02 +00:00
return 0 ;
2012-11-29 19:35:33 +00:00
2012-11-29 20:09:41 +00:00
if ( const Type * elementType = arrayType - > getElementType ( ) . getTypePtr ( ) ) {
if ( const ArrayType * subArrayType = elementType - > getAsArrayTypeUnsafe ( ) )
return nElements * NumberOfElements ( subArrayType ) ;
2012-11-29 19:35:33 +00:00
}
return nElements ;
} else
return 0 ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendClassDeclLocation ( const CompilerInstance * compiler , const CXXRecordDecl * classDecl ,
std : : string & textLine , bool verbose )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
//Location has a fixed format - from G__display_class.
assert ( compiler ! = 0 & & " AppendClassDeclLocation, 'compiler' parameter is null " ) ;
assert ( classDecl ! = 0 & & " AppendClassDeclLocation, 'classDecl' parameter is null " ) ;
2012-11-29 20:09:41 +00:00
const char * const emptyName = " " ;
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
if ( compiler - > hasSourceManager ( ) ) {
2012-11-29 19:42:43 +00:00
const SourceManager & sourceManager = compiler - > getSourceManager ( ) ;
PresumedLoc loc ( sourceManager . getPresumedLoc ( classDecl - > getLocation ( ) ) ) ;
2012-11-29 19:35:33 +00:00
if ( loc . isValid ( ) ) {
const std : : string baseName ( llvm : : sys : : path : : filename ( loc . getFilename ( ) ) . str ( ) ) ;
if ( ! verbose )
frss < < llvm : : format ( " %-25s%5d " , baseName . size ( ) ? baseName . c_str ( ) : " " , int ( loc . getLine ( ) ) ) ;
else
frss < < llvm : : format ( " FILE: %s LINE: %d " , baseName . size ( ) ? baseName . c_str ( ) : " " , int ( loc . getLine ( ) ) ) ;
} else
2012-11-28 16:38:02 +00:00
frss < < llvm : : format ( " %-30s " , emptyName ) ;
2012-11-29 19:35:33 +00:00
} else
frss < < llvm : : format ( " %-30s " , emptyName ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendMemberFunctionLocation ( const CompilerInstance * compiler , const Decl * decl ,
std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
//Location has a fixed format - from G__display_class.
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendMemberFunctionLocation, 'compiler' parameter is null " ) ;
assert ( decl ! = 0 & & " AppendMemberFunctionLocation, 'decl' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
//Location can be actually somewhere in a compiled code.
2012-11-29 20:09:41 +00:00
const char * const unknownLocation = " (compiled) " ;
2012-11-29 19:35:33 +00:00
frss < < llvm : : format ( " %-15s(NA):(NA) 0 " , unknownLocation ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendDeclLocation ( const CompilerInstance * compiler , const Decl * decl ,
std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendDeclLocation, 'compiler' parameter is null " ) ;
assert ( decl ! = 0 & & " AppendDeclLocation, 'decl' parameter is null " ) ;
2012-12-04 09:37:11 +00:00
static const char * const unknownLocation = " compiled " ;
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
if ( compiler - > hasSourceManager ( ) ) {
2012-11-29 20:09:41 +00:00
const SourceManager & sourceManager = compiler - > getSourceManager ( ) ;
2012-11-29 19:42:43 +00:00
PresumedLoc loc ( sourceManager . getPresumedLoc ( decl - > getLocation ( ) ) ) ;
2012-11-29 19:35:33 +00:00
if ( loc . isValid ( ) ) { //The format is from CINT.
const std : : string baseName ( llvm : : sys : : path : : filename ( loc . getFilename ( ) ) . str ( ) ) ;
frss < < llvm : : format ( " %-15s%4d " , baseName . size ( ) ? baseName . c_str ( ) : " " , int ( loc . getLine ( ) ) ) ;
} else
frss < < llvm : : format ( " %-15s " , unknownLocation ) ;
} else {
frss < < llvm : : format ( " %-15s " , unknownLocation ) ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendMacroLocation ( const CompilerInstance * compiler , const MacroInfo * macroInfo ,
std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendMacroLocation, 'compiler' parameter is null " ) ;
assert ( macroInfo ! = 0 & & " AppendMacroLocation, 'macroInfo' parameter is null " ) ;
//TODO: check what does location for macro definition really means -
2012-11-29 19:42:43 +00:00
//macro can be defined many times, what do we have in a TranslationUnit in this case?
2012-11-29 19:35:33 +00:00
//At the moment this function is similar to AppendDeclLocation.
2012-11-29 20:09:41 +00:00
const char * const unknownLocation = " (unknown) " ;
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
if ( compiler - > hasSourceManager ( ) ) {
2012-11-29 19:42:43 +00:00
const SourceManager & sourceManager = compiler - > getSourceManager ( ) ;
PresumedLoc loc ( sourceManager . getPresumedLoc ( macroInfo - > getDefinitionLoc ( ) ) ) ;
2012-11-29 19:35:33 +00:00
if ( loc . isValid ( ) ) { //The format is from CINT.
const std : : string baseName ( llvm : : sys : : path : : filename ( loc . getFilename ( ) ) . str ( ) ) ;
frss < < llvm : : format ( " %-15s%4d " , baseName . size ( ) ? baseName . c_str ( ) : " " , int ( loc . getLine ( ) ) ) ;
} else
frss < < llvm : : format ( " %-15s " , unknownLocation ) ;
} else
frss < < llvm : : format ( " %-15s " , unknownLocation ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendClassKeyword ( const CXXRecordDecl * classDecl , std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " AppendClassKeyword, 'classDecl' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
name + = classDecl - > getKindName ( ) ;
name + = ' ' ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendClassName ( const CXXRecordDecl * classDecl , std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " AppendClassName, 'classDecl' parameter is null " ) ;
2012-11-29 19:42:43 +00:00
const LangOptions langOpts ;
const PrintingPolicy printingPolicy ( langOpts ) ;
2012-11-29 19:35:33 +00:00
std : : string tmp ;
//Name for diagnostic will include template arguments if any.
classDecl - > getNameForDiagnostic ( tmp , printingPolicy , true ) ; //true == qualified name.
name + = tmp ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendMemberAccessSpecifier ( const Decl * memberDecl , std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( memberDecl ! = 0 & & " AppendMemberAccessSpecifier, 'memberDecl' parameter is 0 " ) ;
switch ( memberDecl - > getAccess ( ) ) {
2012-11-29 19:42:43 +00:00
case AS_private :
2012-11-29 19:35:33 +00:00
name + = " private: " ;
break ;
2012-11-29 19:42:43 +00:00
case AS_protected :
2012-11-29 19:35:33 +00:00
name + = " protected: " ;
break ;
2012-11-29 19:42:43 +00:00
case AS_public :
case AS_none : //Public or private?
2012-11-29 19:35:33 +00:00
name + = " public: " ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendConstructorSignature ( const CXXConstructorDecl * ctorDecl , std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( ctorDecl ! = 0 & & " AppendConstructorSignature, 'ctorDecl' parameter is null " ) ;
2012-11-29 19:42:43 +00:00
const QualType type = ctorDecl - > getType ( ) ;
2012-11-29 19:48:39 +00:00
assert ( isa < FunctionType > ( type ) = = true & & " AppendConstructorSignature, ctorDecl->getType is not a FunctionType " ) ;
2012-11-29 19:35:33 +00:00
2012-11-29 20:09:41 +00:00
const FunctionType * const aft = type - > getAs < FunctionType > ( ) ;
2012-11-29 20:40:53 +00:00
const FunctionProtoType * const ft = ctorDecl - > hasWrittenPrototype ( ) ?
dyn_cast < FunctionProtoType > ( aft ) : 0 ;
2012-11-29 19:35:33 +00:00
if ( ctorDecl - > isExplicit ( ) )
name + = " explicit " ;
name + = ctorDecl - > getNameInfo ( ) . getAsString ( ) ;
name + = " ( " ;
if ( ft ) {
llvm : : raw_string_ostream stream ( name ) ;
for ( unsigned i = 0 , e = ctorDecl - > getNumParams ( ) ; i ! = e ; + + i ) {
if ( i )
stream < < " , " ;
ctorDecl - > getParamDecl ( i ) - > print ( stream , 0 , false ) ; //or true?
}
if ( ft - > isVariadic ( ) ) {
if ( ctorDecl - > getNumParams ( ) )
stream < < " , " ;
stream < < " ... " ;
}
} else if ( ctorDecl - > doesThisDeclarationHaveABody ( ) & & ! ctorDecl - > hasPrototype ( ) ) {
for ( unsigned i = 0 , e = ctorDecl - > getNumParams ( ) ; i ! = e ; + + i ) {
if ( i )
name + = " , " ;
name + = ctorDecl - > getParamDecl ( i ) - > getNameAsString ( ) ;
}
}
name + = " ) " ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendMemberFunctionSignature ( const Decl * methodDecl , std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( methodDecl ! = 0 & & " AppendMemberFunctionSignature, 'methodDecl' parameter is null " ) ;
2012-11-29 20:40:53 +00:00
assert ( methodDecl - > getKind ( ) ! = Decl : : CXXConstructor & & " AppendMemberFunctionSignature, called for a ctor declaration " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream out ( name ) ;
2012-11-29 19:42:43 +00:00
const LangOptions langOpts ;
PrintingPolicy printingPolicy ( langOpts ) ;
2012-11-29 19:35:33 +00:00
printingPolicy . TerseOutput = true ; //Do not print the body of an inlined function.
printingPolicy . SuppressSpecifiers = false ; //Show 'static', 'inline', etc.
2012-11-28 16:38:02 +00:00
2012-11-29 20:40:53 +00:00
methodDecl - > print ( out , printingPolicy , 0 , false ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendObjectDeclaration ( const Decl * objDecl , const PrintingPolicy & policy ,
bool printInstantiation , std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( objDecl ! = 0 & & " AppendObjectDeclaration, 'objDecl' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream out ( name ) ;
objDecl - > print ( out , policy , 0 , printInstantiation ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendBaseClassSpecifiers ( base_decl_iterator base , std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
if ( base - > isVirtual ( ) )
textLine + = " virtual " ;
switch ( base - > getAccessSpecifier ( ) ) {
2012-11-29 19:42:43 +00:00
case AS_private :
2012-11-29 19:35:33 +00:00
textLine + = " private " ;
break ;
2012-11-29 19:42:43 +00:00
case AS_protected :
2012-11-29 19:35:33 +00:00
textLine + = " protected " ;
break ;
2012-11-29 19:42:43 +00:00
case AS_public :
case AS_none : //TODO - check this.
2012-11-29 19:35:33 +00:00
textLine + = " public " ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendClassSize ( const CompilerInstance * compiler , const RecordDecl * decl ,
std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendClassSize, 'compiler' parameter is null " ) ;
assert ( decl ! = 0 & & " AppendClassSize, 'decl' parameter is null " ) ;
2012-11-29 19:48:39 +00:00
if ( dyn_cast < ClassTemplatePartialSpecializationDecl > ( decl ) ) {
2012-11-29 19:35:33 +00:00
textLine + = " SIZE: (NA) " ;
return ;
}
2012-11-29 20:09:41 +00:00
const ASTRecordLayout & layout = compiler - > getASTContext ( ) . getASTRecordLayout ( decl ) ;
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
frss < < llvm : : format ( " SIZE: %d " , int ( layout . getSize ( ) . getQuantity ( ) ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
template < class Decl >
2012-11-29 20:09:41 +00:00
void AppendUDTSize ( const CompilerInstance * compiler , const Decl * decl , std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendUDTSize, 'compiler' parameter is null " ) ;
assert ( decl ! = 0 & & " AppendUDTSize, 'decl' parameter is null " ) ;
std : : string formatted ;
{
llvm : : raw_string_ostream rss ( formatted ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
2012-11-29 20:09:41 +00:00
if ( const RecordType * const recordType = decl - > getType ( ) - > template getAs < RecordType > ( ) ) {
if ( const RecordDecl * const recordDecl = cast_or_null < RecordDecl > ( recordType - > getDecl ( ) - > getDefinition ( ) ) ) {
const ASTRecordLayout & layout = compiler - > getASTContext ( ) . getASTRecordLayout ( recordDecl ) ;
2012-11-29 19:35:33 +00:00
frss < < llvm : : format ( " %d " , int ( layout . getSize ( ) . getQuantity ( ) ) ) ;
}
2012-11-29 20:09:41 +00:00
} else if ( const ArrayType * const arrayType = decl - > getType ( ) - > getAsArrayTypeUnsafe ( ) ) {
if ( const Type * const elementType = arrayType - > getBaseElementTypeUnsafe ( ) ) {
if ( const CXXRecordDecl * const recordDecl = elementType - > getAsCXXRecordDecl ( ) ) {
const ASTRecordLayout & layout = compiler - > getASTContext ( ) . getASTRecordLayout ( recordDecl ) ;
2012-11-29 19:35:33 +00:00
const int baseElementSize = int ( layout . getSize ( ) . getQuantity ( ) ) ;
const int nElements = NumberOfElements ( arrayType ) ;
if ( nElements > 0 )
frss < < llvm : : format ( " %d " , nElements * baseElementSize ) ;
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
}
}
formatted . length ( ) ? textLine + = formatted : textLine + = " NA " ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void AppendBaseClassOffset ( const CompilerInstance * compiler , const CXXRecordDecl * completeClass ,
const CXXRecordDecl * baseClass , bool isVirtual , std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendBaseClassOffset, 'compiler' parameter is null " ) ;
assert ( completeClass ! = 0 & & " AppendBaseClassOffset, 'completeClass' parameter is null " ) ;
assert ( baseClass ! = 0 & & " AppendBaseClassOffset, 'baseClass' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
const ASTRecordLayout & layout = compiler - > getASTContext ( ) . getASTRecordLayout ( completeClass ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
if ( isVirtual ) //format is from G__display_classinheritance.
frss < < llvm : : format ( " 0x%-8x " , int ( layout . getVBaseClassOffset ( baseClass ) . getQuantity ( ) ) ) ;
else
frss < < llvm : : format ( " 0x%-8x " , int ( layout . getBaseClassOffset ( baseClass ) . getQuantity ( ) ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void AppendDataMemberOffset ( const CompilerInstance * compiler , const CXXRecordDecl * classDecl ,
const FieldDecl * fieldDecl , std : : string & textLine )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " AppendDataMemberOffset, 'compiler' parameter is null " ) ;
assert ( classDecl ! = 0 & & " AppendDataMemberOffset, 'classDecl' parameter is null " ) ;
assert ( fieldDecl ! = 0 & & " AppendDataMemberOffset, 'fieldDecl' parameter is null " ) ;
2012-11-29 20:09:41 +00:00
const ASTRecordLayout & layout = compiler - > getASTContext ( ) . getASTRecordLayout ( classDecl ) ;
2012-11-29 19:35:33 +00:00
std : : string formatted ;
//
llvm : : raw_string_ostream rss ( textLine ) ;
llvm : : formatted_raw_ostream frss ( rss ) ;
2012-11-29 20:40:53 +00:00
frss < < llvm : : format ( " 0x%-8x " , int ( layout . getFieldOffset ( fieldDecl - > getFieldIndex ( ) )
/ std : : numeric_limits < unsigned char > : : digits ) ) ;
2012-11-28 16:38:02 +00:00
}
//
//This is a primitive class which does nothing except fprintf for the moment,
//but this can change later.
class FILEPrintHelper {
public :
2012-11-29 20:09:41 +00:00
FILEPrintHelper ( llvm : : raw_ostream & stream ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
void Print ( const char * msg ) const ;
2012-11-28 16:38:02 +00:00
private :
2012-11-29 20:09:41 +00:00
llvm : : raw_ostream & fStream ;
2012-11-28 16:38:02 +00:00
} ;
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
FILEPrintHelper : : FILEPrintHelper ( llvm : : raw_ostream & stream )
2012-11-29 19:35:33 +00:00
: fStream ( stream )
2012-11-28 16:38:02 +00:00
{
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void FILEPrintHelper : : Print ( const char * msg ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( msg ! = 0 & & " Print, 'msg' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
fStream < < msg ;
fStream . flush ( ) ;
2012-11-28 16:38:02 +00:00
}
//
//Aux. class to traverse translation-unit-declaration/class-declaration.
//
class ClassPrinter {
private :
2012-11-29 19:35:33 +00:00
enum {
kBaseTreeShift = 3 ,
kMemberTypeShift = 3
} ;
2012-11-28 16:38:02 +00:00
public :
2012-11-29 20:09:41 +00:00
ClassPrinter ( llvm : : raw_ostream & stream , const class cling : : Interpreter * interpreter ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
void DisplayAllClasses ( ) const ;
2012-11-29 20:09:41 +00:00
void DisplayClass ( const std : : string & className ) const ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
void SetVerbose ( bool verbose ) ;
2012-11-28 16:38:02 +00:00
private :
2012-11-29 19:35:33 +00:00
//These are declarations, which can contain nested class declarations,
//I have separate function for the case I want to treat them in different ways.
//Can be only one processDecl actually.
void ProcessDecl ( decl_iterator decl ) const ;
void ProcessBlockDecl ( decl_iterator decl ) const ;
void ProcessFunctionDecl ( decl_iterator decl ) const ;
void ProcessNamespaceDecl ( decl_iterator decl ) const ;
void ProcessLinkageSpecDecl ( decl_iterator decl ) const ;
void ProcessClassDecl ( decl_iterator decl ) const ;
template < class Decl >
2012-11-29 20:09:41 +00:00
void ProcessTypeOfMember ( const Decl * decl , unsigned nSpaces ) const
2012-11-29 19:35:33 +00:00
{
//Extract the type of declaration and process it.
assert ( decl ! = 0 & & " ProcessTypeOfMember, 'decl' parameter is null " ) ;
2012-11-29 20:09:41 +00:00
if ( const RecordType * const recordType = decl - > getType ( ) - > template getAs < RecordType > ( ) ) {
if ( const CXXRecordDecl * const classDecl = cast_or_null < CXXRecordDecl > ( recordType - > getDecl ( ) - > getDefinition ( ) ) )
2012-11-29 19:35:33 +00:00
DisplayDataMembers ( classDecl , nSpaces ) ;
2012-11-29 20:09:41 +00:00
} else if ( const ArrayType * const arrayType = decl - > getType ( ) - > getAsArrayTypeUnsafe ( ) ) {
if ( const Type * const elType = arrayType - > getBaseElementTypeUnsafe ( ) ) {
if ( const RecordType * const recordType = elType - > getAs < RecordType > ( ) ) {
if ( const CXXRecordDecl * classDecl = cast_or_null < CXXRecordDecl > ( recordType - > getDecl ( ) - > getDefinition ( ) ) )
2012-11-28 16:38:02 +00:00
DisplayDataMembers ( classDecl , nSpaces ) ;
2012-11-29 19:35:33 +00:00
}
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
void DisplayClassDecl ( const CXXRecordDecl * classDecl ) const ;
void DisplayBasesAsList ( const CXXRecordDecl * classDecl ) const ;
void DisplayBasesAsTree ( const CXXRecordDecl * classDecl , unsigned nSpaces ) const ;
void DisplayMemberFunctions ( const CXXRecordDecl * classDecl ) const ;
void DisplayDataMembers ( const CXXRecordDecl * classDecl , unsigned nSpaces ) const ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
FILEPrintHelper fOut ;
2012-11-29 20:09:41 +00:00
const cling : : Interpreter * fInterpreter ;
2012-11-29 19:35:33 +00:00
bool fVerbose ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
mutable std : : set < const Decl * > fSeenDecls ;
2012-11-28 16:38:02 +00:00
} ;
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
ClassPrinter : : ClassPrinter ( llvm : : raw_ostream & stream , const cling : : Interpreter * interpreter )
2012-11-29 19:35:33 +00:00
: fOut ( stream ) ,
2012-11-29 20:09:41 +00:00
fInterpreter ( interpreter ) ,
fVerbose ( false )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( interpreter ! = 0 & & " ClassPrinter, 'compiler' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : DisplayAllClasses ( ) const
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " DisplayAllClasses, fCompiler is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
const CompilerInstance * const compiler = fInterpreter - > getCI ( ) ;
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " DisplayAllClasses, compiler instance is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
const TranslationUnitDecl * const tuDecl = compiler - > getASTContext ( ) . getTranslationUnitDecl ( ) ;
2012-11-29 19:35:33 +00:00
assert ( tuDecl ! = 0 & & " DisplayAllClasses, translation unit is empty " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
fSeenDecls . clear ( ) ;
2012-11-28 16:38:02 +00:00
2012-12-06 06:57:39 +00:00
fOut . Print ( " List of classes " ) ;
2012-11-29 19:35:33 +00:00
for ( decl_iterator decl = tuDecl - > decls_begin ( ) ; decl ! = tuDecl - > decls_end ( ) ; + + decl )
ProcessDecl ( decl ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void ClassPrinter : : DisplayClass ( const std : : string & className ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " DisplayClass, fCompiler is null " ) ;
fSeenDecls . clear ( ) ;
const cling : : LookupHelper & lookupHelper = fInterpreter - > getLookupHelper ( ) ;
2012-11-29 20:09:41 +00:00
if ( const Decl * const decl = lookupHelper . findScope ( className ) ) {
if ( const CXXRecordDecl * const classDecl = dyn_cast < CXXRecordDecl > ( decl ) ) {
2012-11-29 19:35:33 +00:00
if ( classDecl - > hasDefinition ( ) )
DisplayClassDecl ( classDecl ) ;
2012-12-06 05:15:07 +00:00
else
fOut . Print ( ( " The class " + className +
" does not have any definition available \n " ) . c_str ( ) ) ;
} else
fOut . Print ( ( " A " + std : : string ( decl - > getDeclKindName ( ) ) + " declaration "
" was found for " + className + " \n " ) . c_str ( ) ) ;
2012-12-05 16:09:15 +00:00
} else
2012-12-05 16:36:42 +00:00
fOut . Print ( ( " Class " + className + " not found \n " ) . c_str ( ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : SetVerbose ( bool verbose )
{
2012-11-29 19:35:33 +00:00
fVerbose = verbose ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : ProcessDecl ( decl_iterator decl ) const
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " ProcessDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessDecl, 'decl' parameter is not a valid iterator " ) ;
switch ( decl - > getKind ( ) ) {
2012-11-29 19:42:43 +00:00
case Decl : : Namespace :
2012-11-29 19:35:33 +00:00
ProcessNamespaceDecl ( decl ) ;
break ;
2012-11-29 19:42:43 +00:00
case Decl : : Block :
2012-11-29 19:35:33 +00:00
ProcessBlockDecl ( decl ) ;
break ;
2012-11-29 19:42:43 +00:00
case Decl : : Function :
case Decl : : CXXMethod :
case Decl : : CXXConstructor :
case Decl : : CXXConversion :
case Decl : : CXXDestructor :
2012-11-29 19:35:33 +00:00
ProcessFunctionDecl ( decl ) ;
break ;
2012-11-29 19:42:43 +00:00
case Decl : : LinkageSpec :
2012-11-29 19:35:33 +00:00
ProcessLinkageSpecDecl ( decl ) ;
break ;
2012-11-29 19:42:43 +00:00
case Decl : : CXXRecord :
case Decl : : ClassTemplateSpecialization :
case Decl : : ClassTemplatePartialSpecialization :
2012-11-29 19:35:33 +00:00
ProcessClassDecl ( decl ) ;
break ;
default :
2012-11-29 19:48:39 +00:00
if ( dyn_cast < FunctionDecl > ( * decl ) )
2012-11-29 19:42:43 +00:00
//decl->getKind() != Decl::Function, but decl has type, inherited from FunctionDecl.
2012-11-28 16:38:02 +00:00
ProcessFunctionDecl ( decl ) ;
2012-11-29 19:35:33 +00:00
break ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : ProcessBlockDecl ( decl_iterator decl ) const
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " ProcessBlockDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessBlockDecl, 'decl' parameter is not a valid iterator " ) ;
2012-11-29 19:42:43 +00:00
assert ( decl - > getKind ( ) = = Decl : : Block & & " ProcessBlockDecl, decl->getKind() != BlockDecl " ) ;
2012-11-29 19:35:33 +00:00
//Block can contain nested (arbitrary deep) class declarations.
//Though, I'm not sure if have block in our code.
2012-11-29 20:09:41 +00:00
const BlockDecl * const blockDecl = dyn_cast < BlockDecl > ( * decl ) ;
2012-11-29 19:35:33 +00:00
assert ( blockDecl ! = 0 & & " ProcessBlockDecl, internal error - decl is not a BlockDecl " ) ;
for ( decl_iterator it = blockDecl - > decls_begin ( ) ; it ! = blockDecl - > decls_end ( ) ; + + it )
ProcessDecl ( it ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : ProcessFunctionDecl ( decl_iterator decl ) const
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " ProcessFunctionDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessFunctionDecl, 'decl' parameter is not a valid iterator " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
//Function can contain class declarations, we have to check this.
2012-11-29 20:09:41 +00:00
const FunctionDecl * const functionDecl = dyn_cast < FunctionDecl > ( * decl ) ;
2012-11-29 19:35:33 +00:00
assert ( functionDecl ! = 0 & & " ProcessFunctionDecl, internal error - decl is not a FunctionDecl " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
for ( decl_iterator it = functionDecl - > decls_begin ( ) ; it ! = functionDecl - > decls_end ( ) ; + + it )
ProcessDecl ( it ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : ProcessNamespaceDecl ( decl_iterator decl ) const
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " ProcessNamespaceDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessNamespaceDecl, 'decl' parameter is not a valid iterator " ) ;
2012-11-29 19:42:43 +00:00
assert ( decl - > getKind ( ) = = Decl : : Namespace & & " ProcessNamespaceDecl, decl->getKind() != Namespace " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
//Namespace can contain nested (arbitrary deep) class declarations.
2012-11-29 20:09:41 +00:00
const NamespaceDecl * const namespaceDecl = dyn_cast < NamespaceDecl > ( * decl ) ;
2012-11-29 19:35:33 +00:00
assert ( namespaceDecl ! = 0 & & " ProcessNamespaceDecl, 'decl' parameter is not a NamespaceDecl " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
for ( decl_iterator it = namespaceDecl - > decls_begin ( ) ; it ! = namespaceDecl - > decls_end ( ) ; + + it )
ProcessDecl ( it ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : ProcessLinkageSpecDecl ( decl_iterator decl ) const
{
2012-11-29 19:35:33 +00:00
//Just in case asserts were deleted from ctor:
assert ( fInterpreter ! = 0 & & " ProcessLinkageSpecDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessLinkageSpecDecl, 'decl' parameter is not a valid iterator " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
const LinkageSpecDecl * const linkageSpec = dyn_cast < LinkageSpecDecl > ( * decl ) ;
2012-11-29 20:40:53 +00:00
assert ( linkageSpec ! = 0 & & " ProcessLinkageSpecDecl, decl is not a LinkageSpecDecl " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
for ( decl_iterator it = linkageSpec - > decls_begin ( ) ; it ! = linkageSpec - > decls_end ( ) ; + + it )
ProcessDecl ( it ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void ClassPrinter : : ProcessClassDecl ( decl_iterator decl ) const
{
2012-11-29 19:35:33 +00:00
assert ( fInterpreter ! = 0 & & " ProcessClassDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessClassDecl, 'decl' parameter is not a valid iterator " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
const CXXRecordDecl * const classDecl = dyn_cast < CXXRecordDecl > ( * decl ) ;
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " ProcessClassDecl, internal error, declaration is not a CXXRecordDecl " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
if ( ! classDecl - > hasDefinition ( ) )
return ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
DisplayClassDecl ( classDecl ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
//Now we have to check nested scopes for class declarations.
for ( decl_iterator decl = classDecl - > decls_begin ( ) ; decl ! = classDecl - > decls_end ( ) ; + + decl )
ProcessDecl ( decl ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void ClassPrinter : : DisplayClassDecl ( const CXXRecordDecl * classDecl ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " DisplayClassDecl, 'classDecl' parameter is null " ) ;
assert ( fInterpreter ! = 0 & & " DisplayClassDecl, fInterpreter is null " ) ;
classDecl = classDecl - > getDefinition ( ) ;
assert ( classDecl ! = 0 & & " DisplayClassDecl, invalid decl - no definition " ) ;
if ( fSeenDecls . find ( classDecl ) ! = fSeenDecls . end ( ) )
return ;
else
fSeenDecls . insert ( classDecl ) ;
if ( ! fVerbose ) {
//Print: source file, line number, class-keyword, qualifies class name, base classes.
std : : string classInfo ;
AppendClassDeclLocation ( fInterpreter - > getCI ( ) , classDecl , classInfo , false ) ;
classInfo + = ' ' ;
AppendClassKeyword ( classDecl , classInfo ) ;
classInfo + = ' ' ;
AppendClassName ( classDecl , classInfo ) ;
classInfo + = ' ' ;
//
fOut . Print ( classInfo . c_str ( ) ) ;
DisplayBasesAsList ( classDecl ) ;
fOut . Print ( " \n " ) ;
} else {
2012-11-29 20:40:53 +00:00
//Hehe, this line was stolen from CINT.
fOut . Print ( " =========================================================================== \n " ) ;
2012-11-29 19:35:33 +00:00
std : : string classInfo ;
AppendClassKeyword ( classDecl , classInfo ) ;
AppendClassName ( classDecl , classInfo ) ;
fOut . Print ( classInfo . c_str ( ) ) ;
fOut . Print ( " \n " ) ;
classInfo . clear ( ) ;
AppendClassSize ( fInterpreter - > getCI ( ) , classDecl , classInfo ) ;
classInfo + = ' ' ;
AppendClassDeclLocation ( fInterpreter - > getCI ( ) , classDecl , classInfo , true ) ;
fOut . Print ( classInfo . c_str ( ) ) ;
fOut . Print ( " \n " ) ;
if ( classDecl - > bases_begin ( ) ! = classDecl - > bases_end ( ) )
fOut . Print ( " Base classes: -------------------------------------------------------- \n " ) ;
DisplayBasesAsTree ( classDecl , 0 ) ;
//now list all members.
fOut . Print ( " List of member variables -------------------------------------------------- \n " ) ;
DisplayDataMembers ( classDecl , 0 ) ;
fOut . Print ( " List of member functions :--------------------------------------------------- \n " ) ;
2012-11-29 20:40:53 +00:00
//CINT has a format like %-15s blah-blah.
fOut . Print ( " filename line:size busy function type and name \n " ) ;
2012-11-29 19:35:33 +00:00
DisplayMemberFunctions ( classDecl ) ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void ClassPrinter : : DisplayBasesAsList ( const CXXRecordDecl * classDecl ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( fInterpreter ! = 0 & & " DisplayBasesAsList, fInterpreter is null " ) ;
assert ( classDecl ! = 0 & & " DisplayBasesAsList, 'classDecl' parameter is 0 " ) ;
2012-11-29 20:40:53 +00:00
assert ( classDecl - > hasDefinition ( ) = = true & & " DisplayBasesAsList, 'classDecl' is invalid " ) ;
2012-11-29 19:35:33 +00:00
assert ( fVerbose = = false & & " DisplayBasesAsList, called in a verbose output " ) ;
//we print a list of base classes as one line, with access specifiers and 'virtual' if needed.
std : : string bases ( " : " ) ;
for ( base_decl_iterator baseIt = classDecl - > bases_begin ( ) ; baseIt ! = classDecl - > bases_end ( ) ; + + baseIt ) {
if ( baseIt ! = classDecl - > bases_begin ( ) )
bases + = " , " ;
2012-11-29 20:09:41 +00:00
const RecordType * const type = baseIt - > getType ( ) - > getAs < RecordType > ( ) ;
2012-11-29 19:35:33 +00:00
if ( type ) {
2012-11-29 20:09:41 +00:00
const CXXRecordDecl * const baseDecl = cast < CXXRecordDecl > ( type - > getDecl ( ) - > getDefinition ( ) ) ;
2012-11-29 19:35:33 +00:00
if ( baseDecl ) {
AppendBaseClassSpecifiers ( baseIt , bases ) ;
bases + = ' ' ;
AppendClassName ( baseDecl , bases ) ;
2012-11-28 16:38:02 +00:00
} else
2012-11-29 19:35:33 +00:00
return ;
} else
return ;
}
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
if ( bases . length ( ) > 2 ) //initial ": "
fOut . Print ( bases . c_str ( ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void ClassPrinter : : DisplayBasesAsTree ( const CXXRecordDecl * classDecl , unsigned nSpaces ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " DisplayBasesAsTree, 'classDecl' parameter is null " ) ;
2012-11-29 20:40:53 +00:00
assert ( classDecl - > hasDefinition ( ) = = true & & " DisplayBasesAsTree, 'classDecl' is invalid " ) ;
2012-11-29 19:35:33 +00:00
assert ( fInterpreter ! = 0 & & " DisplayBasesAsTree, fInterpreter is null " ) ;
assert ( fVerbose = = true & & " DisplayBasesAsTree, call in a simplified output " ) ;
std : : string textLine ;
for ( base_decl_iterator baseIt = classDecl - > bases_begin ( ) ; baseIt ! = classDecl - > bases_end ( ) ; + + baseIt ) {
textLine . assign ( nSpaces , ' ' ) ;
2012-11-29 20:09:41 +00:00
const RecordType * const type = baseIt - > getType ( ) - > getAs < RecordType > ( ) ;
2012-11-29 19:35:33 +00:00
if ( type ) {
2012-11-29 20:09:41 +00:00
const CXXRecordDecl * const baseDecl = cast < CXXRecordDecl > ( type - > getDecl ( ) - > getDefinition ( ) ) ;
2012-11-29 19:35:33 +00:00
if ( baseDecl ) {
AppendBaseClassOffset ( fInterpreter - > getCI ( ) , classDecl , baseDecl , baseIt - > isVirtual ( ) , textLine ) ;
textLine + = ' ' ;
AppendBaseClassSpecifiers ( baseIt , textLine ) ;
textLine + = ' ' ;
AppendClassName ( baseDecl , textLine ) ;
textLine + = ' \n ' ;
fOut . Print ( textLine . c_str ( ) ) ;
DisplayBasesAsTree ( baseDecl , nSpaces + kBaseTreeShift ) ;
continue ;
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
textLine + = " <no type info for a base found> \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void ClassPrinter : : DisplayMemberFunctions ( const CXXRecordDecl * classDecl ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " DisplayMemberFunctions, 'classDecl' parameter is null " ) ;
2012-11-29 19:42:43 +00:00
typedef CXXRecordDecl : : method_iterator method_iterator ;
typedef CXXRecordDecl : : ctor_iterator ctor_iterator ;
2012-11-29 19:35:33 +00:00
std : : string textLine ;
for ( ctor_iterator ctor = classDecl - > ctor_begin ( ) ; ctor ! = classDecl - > ctor_end ( ) ; + + ctor ) {
if ( ctor - > isImplicit ( ) ) //Compiler-generated.
continue ;
textLine . clear ( ) ;
AppendMemberFunctionLocation ( fInterpreter - > getCI ( ) , * ctor , textLine ) ;
textLine + = ' ' ;
AppendMemberAccessSpecifier ( * ctor , textLine ) ;
textLine + = ' ' ;
2012-11-29 19:48:39 +00:00
AppendConstructorSignature ( dyn_cast < CXXConstructorDecl > ( * ctor ) , textLine ) ;
2012-11-29 19:35:33 +00:00
textLine + = " ; \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
}
for ( method_iterator method = classDecl - > method_begin ( ) ; method ! = classDecl - > method_end ( ) ; + + method ) {
2012-11-29 19:42:43 +00:00
if ( method - > getKind ( ) = = Decl : : CXXConstructor )
2012-11-29 19:35:33 +00:00
continue ;
if ( method - > isImplicit ( ) ) //Compiler-generated.
continue ;
textLine . clear ( ) ;
AppendMemberFunctionLocation ( fInterpreter - > getCI ( ) , * method , textLine ) ;
textLine + = ' ' ;
AppendMemberAccessSpecifier ( * method , textLine ) ;
textLine + = ' ' ;
AppendMemberFunctionSignature ( * method , textLine ) ;
textLine + = " ; \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
}
//Now, the problem: template member-functions are not in the list of methods.
//I have to additionally scan class declarations.
for ( decl_iterator decl = classDecl - > decls_begin ( ) ; decl ! = classDecl - > decls_end ( ) ; + + decl ) {
2012-11-29 19:42:43 +00:00
if ( decl - > getKind ( ) = = Decl : : FunctionTemplate ) {
2012-11-29 20:09:41 +00:00
const FunctionTemplateDecl * const ftDecl = dyn_cast < FunctionTemplateDecl > ( * decl ) ;
2012-11-29 19:35:33 +00:00
assert ( ftDecl ! = 0 & & " DisplayMemberFunctions, decl is not a function template " ) ;
2012-11-28 16:38:02 +00:00
textLine . clear ( ) ;
2012-11-29 19:35:33 +00:00
AppendMemberFunctionLocation ( fInterpreter - > getCI ( ) , * decl , textLine ) ;
2012-11-28 16:38:02 +00:00
textLine + = ' ' ;
2012-11-29 19:35:33 +00:00
AppendMemberAccessSpecifier ( * decl , textLine ) ;
2012-11-28 16:38:02 +00:00
textLine + = ' ' ;
2012-11-29 19:35:33 +00:00
AppendMemberFunctionSignature ( * decl , textLine ) ;
//Unless this is fixed in clang, I have to do a stupid trick here to
//print constructor-template correctly, otherwise, class name and
//parameters are omitted (this is also true for clang and normal, non-templated
//constructors.
2012-11-29 20:09:41 +00:00
if ( const FunctionDecl * const funcDecl = ftDecl - > getTemplatedDecl ( ) ) {
if ( const CXXConstructorDecl * const ctorDecl = dyn_cast < CXXConstructorDecl > ( funcDecl ) ) {
2012-11-29 19:35:33 +00:00
textLine + = ' ' ;
AppendConstructorSignature ( ctorDecl , textLine ) ;
}
}
2012-11-28 16:38:02 +00:00
textLine + = " ; \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void ClassPrinter : : DisplayDataMembers ( const CXXRecordDecl * classDecl , unsigned nSpaces ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( classDecl ! = 0 & & " DisplayDataMembers, 'classDecl' parameter is null " ) ;
2012-11-29 19:42:43 +00:00
typedef RecordDecl : : field_iterator field_iterator ;
typedef EnumDecl : : enumerator_iterator enumerator_iterator ;
2012-11-29 19:35:33 +00:00
//
2012-11-29 19:42:43 +00:00
const LangOptions langOpts ;
PrintingPolicy printingPolicy ( langOpts ) ;
2012-11-29 19:35:33 +00:00
printingPolicy . SuppressSpecifiers = false ;
printingPolicy . SuppressInitializers = true ;
//
std : : string textLine ;
const std : : string gap ( std : : max ( nSpaces , 1u ) , ' ' ) ;
2012-11-29 20:40:53 +00:00
for ( field_iterator field = classDecl - > field_begin ( ) ;
field ! = classDecl - > field_end ( ) ; + + field ) {
2012-11-29 19:35:33 +00:00
textLine . clear ( ) ;
AppendDeclLocation ( fInterpreter - > getCI ( ) , * field , textLine ) ;
textLine + = gap ;
AppendDataMemberOffset ( fInterpreter - > getCI ( ) , classDecl , * field , textLine ) ;
textLine + = ' ' ;
AppendMemberAccessSpecifier ( * field , textLine ) ;
textLine + = ' ' ;
AppendObjectDeclaration ( * field , printingPolicy , true , textLine ) ;
if ( HasUDT ( * field ) ) {
textLine + = " , size = " ;
AppendUDTSize ( fInterpreter - > getCI ( ) , * field , textLine ) ;
textLine + = ' \n ' ;
fOut . Print ( textLine . c_str ( ) ) ;
ProcessTypeOfMember ( * field , nSpaces + kMemberTypeShift ) ;
} else {
textLine + = " \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
}
}
//Now the problem: static data members are not fields, enumerators are not fields.
for ( decl_iterator decl = classDecl - > decls_begin ( ) ; decl ! = classDecl - > decls_end ( ) ; + + decl ) {
2012-11-29 19:42:43 +00:00
if ( decl - > getKind ( ) = = Decl : : Enum ) {
2012-11-29 20:09:41 +00:00
const EnumDecl * enumDecl = dyn_cast < EnumDecl > ( * decl ) ;
2012-11-29 20:40:53 +00:00
assert ( enumDecl ! = 0 & & " DisplayDataMembers, decl->getKind() == Enum, but decl is not a EnumDecl " ) ;
//it's not really clear, if I should really check this.
if ( enumDecl - > isComplete ( ) & & ( enumDecl = enumDecl - > getDefinition ( ) ) ) {
2012-11-29 19:35:33 +00:00
//if (fSeenDecls.find(enumDecl) == fSeenDecls.end()) {
// fSeenDecls.insert(enumDecl);
2012-11-29 20:40:53 +00:00
for ( enumerator_iterator enumerator = enumDecl - > enumerator_begin ( ) ;
enumerator ! = enumDecl - > enumerator_end ( ) ; + + enumerator ) {
2012-11-29 19:35:33 +00:00
//
textLine . clear ( ) ;
AppendDeclLocation ( fInterpreter - > getCI ( ) , * enumerator , textLine ) ;
textLine + = gap ;
textLine + = " 0x0 " ; //offset is meaningless.
AppendMemberAccessSpecifier ( * enumerator , textLine ) ;
textLine + = ' ' ;
//{//Block to force flush for stream.
//llvm::raw_string_ostream stream(textLine);
2012-11-29 19:42:43 +00:00
const QualType type ( enumerator - > getType ( ) ) ;
//const LangOptions lo;
//PrintingPolicy pp(lo);
2012-11-29 19:35:33 +00:00
//pp.SuppressScope = true;
//type.print(stream, pp);
textLine + = type . getAsString ( ) ;
//}
textLine + = ' ' ;
//SuppressInitializer does not help with PrintingPolicy,
//so I have to use getNameAsString.
textLine + = enumerator - > getNameAsString ( ) ;
textLine + = " \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
}
//}
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:42:43 +00:00
} else if ( decl - > getKind ( ) = = Decl : : Var ) {
2012-11-29 20:09:41 +00:00
const VarDecl * const varDecl = dyn_cast < VarDecl > ( * decl ) ;
2012-11-29 20:40:53 +00:00
assert ( varDecl ! = 0 & & " DisplayDataMembers, decl->getKind() == Var, but decl is not a VarDecl " ) ;
2012-11-29 19:42:43 +00:00
if ( varDecl - > getStorageClass ( ) = = SC_Static ) {
2012-11-29 19:35:33 +00:00
//I hope, this is a static data-member :)
textLine . clear ( ) ;
AppendDeclLocation ( fInterpreter - > getCI ( ) , varDecl , textLine ) ;
textLine + = gap ;
textLine + = " 0x0 " ; //offset is meaningless.
AppendMemberAccessSpecifier ( varDecl , textLine ) ;
textLine + = ' ' ;
AppendObjectDeclaration ( varDecl , printingPolicy , true , textLine ) ;
if ( HasUDT ( varDecl ) ) {
textLine + = " , size = " ;
AppendUDTSize ( fInterpreter - > getCI ( ) , varDecl , textLine ) ;
textLine + = ' \n ' ;
fOut . Print ( textLine . c_str ( ) ) ;
ProcessTypeOfMember ( varDecl , nSpaces + kMemberTypeShift ) ;
} else {
textLine + = " \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
}
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
}
//Aux. class to display global objects, macros (object-like), enumerators.
class GlobalsPrinter {
public :
2012-11-29 20:09:41 +00:00
GlobalsPrinter ( llvm : : raw_ostream & stream , const class cling : : Interpreter * interpreter ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
void DisplayGlobals ( ) const ;
2012-11-29 20:09:41 +00:00
void DisplayGlobal ( const std : : string & name ) const ;
2012-11-28 16:38:02 +00:00
private :
2012-11-29 19:35:33 +00:00
2012-11-29 20:09:41 +00:00
void DisplayVarDecl ( const VarDecl * varDecl ) const ;
void DisplayEnumeratorDecl ( const EnumConstantDecl * enumerator ) const ;
void DisplayObjectLikeMacro ( const IdentifierInfo * identifierInfo , const MacroInfo * macroInfo ) const ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
FILEPrintHelper fOut ;
2012-11-29 20:09:41 +00:00
const cling : : Interpreter * fInterpreter ;
2012-11-28 16:38:02 +00:00
2012-11-29 20:09:41 +00:00
mutable std : : set < const Decl * > fSeenDecls ;
2012-11-28 16:38:02 +00:00
} ;
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
GlobalsPrinter : : GlobalsPrinter ( llvm : : raw_ostream & stream , const cling : : Interpreter * interpreter )
2012-11-29 19:35:33 +00:00
: fOut ( stream ) ,
2012-11-29 20:09:41 +00:00
fInterpreter ( interpreter )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( interpreter ! = 0 & & " GlobalsPrinter, 'compiler' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
void GlobalsPrinter : : DisplayGlobals ( ) const
{
2012-11-29 19:42:43 +00:00
typedef EnumDecl : : enumerator_iterator enumerator_iterator ;
typedef Preprocessor : : macro_iterator macro_iterator ;
2012-11-29 19:35:33 +00:00
assert ( fInterpreter ! = 0 & & " DisplayGlobals, fInterpreter is null " ) ;
2012-11-29 20:09:41 +00:00
const CompilerInstance * const compiler = fInterpreter - > getCI ( ) ;
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " DisplayGlobals, compiler instance is null " ) ;
2012-11-29 20:09:41 +00:00
const TranslationUnitDecl * const tuDecl = compiler - > getASTContext ( ) . getTranslationUnitDecl ( ) ;
2012-11-29 19:35:33 +00:00
assert ( tuDecl ! = 0 & & " DisplayGlobals, translation unit is empty " ) ;
//fSeenDecls.clear();
//Try to print global macro definitions (object-like only).
2012-11-29 20:09:41 +00:00
const Preprocessor & pp = compiler - > getPreprocessor ( ) ;
2012-11-29 19:35:33 +00:00
for ( macro_iterator macro = pp . macro_begin ( ) ; macro ! = pp . macro_end ( ) ; + + macro ) {
if ( macro - > second - > isObjectLike ( ) )
DisplayObjectLikeMacro ( macro - > first , macro - > second ) ;
}
//TODO: fSeenDecls - should I check that some declaration is already visited?
//It's obviously that for objects we can have one definition and any number
//of declarations, should I print them?
for ( decl_iterator decl = tuDecl - > decls_begin ( ) ; decl ! = tuDecl - > decls_end ( ) ; + + decl ) {
2012-11-29 20:09:41 +00:00
if ( const VarDecl * const varDecl = dyn_cast < VarDecl > ( * decl ) )
2012-11-29 19:35:33 +00:00
DisplayVarDecl ( varDecl ) ;
2012-11-29 20:09:41 +00:00
else if ( const EnumDecl * enumDecl = dyn_cast < EnumDecl > ( * decl ) ) {
2012-11-29 20:40:53 +00:00
//it's not really clear, if I should really check this:
if ( enumDecl - > isComplete ( ) & & ( enumDecl = enumDecl - > getDefinition ( ) ) ) {
for ( enumerator_iterator enumerator = enumDecl - > enumerator_begin ( ) ;
enumerator ! = enumDecl - > enumerator_end ( ) ; + + enumerator )
2012-11-29 19:35:33 +00:00
DisplayEnumeratorDecl ( * enumerator ) ;
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void GlobalsPrinter : : DisplayGlobal ( const std : : string & name ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:42:43 +00:00
typedef EnumDecl : : enumerator_iterator enumerator_iterator ;
typedef Preprocessor : : macro_iterator macro_iterator ;
2012-11-29 19:35:33 +00:00
//TODO: is it ok to compare 'name' with decl->getNameAsString() ??
assert ( fInterpreter ! = 0 & & " DisplayGlobal, fInterpreter is null " ) ;
2012-11-29 20:09:41 +00:00
const CompilerInstance * const compiler = fInterpreter - > getCI ( ) ;
2012-11-29 19:35:33 +00:00
assert ( compiler ! = 0 & & " DisplayGlobal, compiler instance is null " ) ;
2012-11-29 20:09:41 +00:00
const TranslationUnitDecl * const tuDecl = compiler - > getASTContext ( ) . getTranslationUnitDecl ( ) ;
2012-11-29 19:35:33 +00:00
assert ( tuDecl ! = 0 & & " DisplayGlobal, translation unit is empty " ) ;
//fSeenDecls.clear();
bool found = false ;
2012-11-29 20:09:41 +00:00
const Preprocessor & pp = compiler - > getPreprocessor ( ) ;
2012-11-29 19:35:33 +00:00
for ( macro_iterator macro = pp . macro_begin ( ) ; macro ! = pp . macro_end ( ) ; + + macro ) {
if ( macro - > second - > isObjectLike ( ) ) {
if ( name = = macro - > first - > getName ( ) . data ( ) ) {
DisplayObjectLikeMacro ( macro - > first , macro - > second ) ;
found = true ;
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
}
for ( decl_iterator decl = tuDecl - > decls_begin ( ) ; decl ! = tuDecl - > decls_end ( ) ; + + decl ) {
2012-11-29 20:09:41 +00:00
if ( const VarDecl * const varDecl = dyn_cast < VarDecl > ( * decl ) ) {
2012-11-29 19:35:33 +00:00
if ( varDecl - > getNameAsString ( ) = = name ) {
DisplayVarDecl ( varDecl ) ;
found = true ;
}
2012-11-29 20:09:41 +00:00
} else if ( const EnumDecl * enumDecl = dyn_cast < EnumDecl > ( * decl ) ) {
2012-11-29 20:40:53 +00:00
//it's not really clear, if I should really check this:
if ( enumDecl - > isComplete ( ) & & ( enumDecl = enumDecl - > getDefinition ( ) ) ) {
for ( enumerator_iterator enumerator = enumDecl - > enumerator_begin ( ) ;
enumerator ! = enumDecl - > enumerator_end ( ) ; + + enumerator ) {
2012-11-29 19:35:33 +00:00
if ( enumerator - > getNameAsString ( ) = = name ) {
DisplayEnumeratorDecl ( * enumerator ) ;
2012-11-28 16:38:02 +00:00
found = true ;
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
}
2012-11-29 19:35:33 +00:00
}
}
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
//Do as CINT does:
if ( ! found )
fOut . Print ( ( " Variable " + name + " not found \n " ) . c_str ( ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void GlobalsPrinter : : DisplayVarDecl ( const VarDecl * varDecl ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( fInterpreter ! = 0 & & " DisplayVarDecl, fInterpreter is null " ) ;
assert ( varDecl ! = 0 & & " DisplayVarDecl, 'varDecl' parameter is null " ) ;
2012-11-29 19:42:43 +00:00
const LangOptions langOpts ;
PrintingPolicy printingPolicy ( langOpts ) ;
2012-11-29 19:35:33 +00:00
printingPolicy . SuppressSpecifiers = false ;
printingPolicy . SuppressInitializers = false ;
std : : string textLine ;
AppendDeclLocation ( fInterpreter - > getCI ( ) , varDecl , textLine ) ;
//TODO:
//Hehe, it's strange to expect addresses from an AST :)
//Add it, if you know how, I don't care.
textLine + = " (address: NA) " ;
AppendObjectDeclaration ( varDecl , printingPolicy , false , textLine ) ;
if ( HasUDT ( varDecl ) ) {
textLine + = " , size = " ;
AppendUDTSize ( fInterpreter - > getCI ( ) , varDecl , textLine ) ;
}
textLine + = " \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:09:41 +00:00
void GlobalsPrinter : : DisplayEnumeratorDecl ( const EnumConstantDecl * enumerator ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( fInterpreter ! = 0 & & " DisplayEnumeratorDecl, fInterpreter is null " ) ;
assert ( enumerator ! = 0 & & " DisplayEnumeratorDecl, 'enumerator' parameter is null " ) ;
2012-11-29 19:42:43 +00:00
const LangOptions langOpts ;
PrintingPolicy printingPolicy ( langOpts ) ;
2012-11-29 19:35:33 +00:00
printingPolicy . SuppressInitializers = false ;
std : : string textLine ;
AppendDeclLocation ( fInterpreter - > getCI ( ) , enumerator , textLine ) ;
textLine + = " (address: NA) " ; //No address, that's an enumerator.
2012-11-29 19:42:43 +00:00
const QualType type ( enumerator - > getType ( ) ) ;
2012-11-29 19:35:33 +00:00
textLine + = type . getAsString ( ) ;
textLine + = ' ' ;
AppendObjectDeclaration ( enumerator , printingPolicy , false , textLine ) ;
textLine + = " \n " ;
fOut . Print ( textLine . c_str ( ) ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-11-29 20:40:53 +00:00
void GlobalsPrinter : : DisplayObjectLikeMacro ( const IdentifierInfo * identifierInfo ,
const MacroInfo * macroInfo ) const
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( identifierInfo ! = 0 & & " DisplayObjectLikeMacro, 'identifierInfo' parameter is null " ) ;
assert ( macroInfo ! = 0 & & " DisplayObjectLikeMacro, 'macroInfo' parameter is null " ) ;
std : : string textLine ;
AppendMacroLocation ( fInterpreter - > getCI ( ) , macroInfo , textLine ) ;
textLine + = " (address: NA) #define " ; //No address exists for a macro definition.
textLine + = identifierInfo - > getName ( ) . data ( ) ;
if ( macroInfo - > getNumTokens ( ) )
textLine + = " = " ;
assert ( fInterpreter - > getCI ( ) ! = 0 & & " DisplayObjectLikeMacro, compiler instance is null " ) ;
2012-11-29 19:42:43 +00:00
const Preprocessor & pp = fInterpreter - > getCI ( ) - > getPreprocessor ( ) ;
2012-11-29 19:35:33 +00:00
for ( unsigned i = 0 , e = macroInfo - > getNumTokens ( ) ; i < e ; + + i ) {
textLine + = ' ' ;
textLine + = pp . getSpelling ( macroInfo - > getReplacementToken ( i ) ) ;
}
fOut . Print ( textLine . c_str ( ) ) ;
fOut . Print ( " \n " ) ;
2012-11-28 16:38:02 +00:00
}
2012-12-05 15:44:04 +00:00
//Print typedefs.
class TypedefPrinter {
public :
TypedefPrinter ( llvm : : raw_ostream & stream , const Interpreter * interpreter ) ;
void DisplayTypedefs ( ) const ;
void DisplayTypedef ( const std : : string & name ) const ;
private :
void ProcessNestedDeclarations ( const DeclContext * decl ) const ;
void ProcessDecl ( decl_iterator decl ) const ;
void DisplayTypedefDecl ( TypedefNameDecl * typedefDecl ) const ;
FILEPrintHelper fOut ;
const cling : : Interpreter * fInterpreter ;
//mutable std::set<const Decl*> fSeenDecls;
} ;
//______________________________________________________________________________
TypedefPrinter : : TypedefPrinter ( llvm : : raw_ostream & stream , const Interpreter * interpreter )
: fOut ( stream ) ,
fInterpreter ( interpreter )
{
assert ( interpreter ! = 0 & & " TypedefPrinter, parameter 'interpreter' is null " ) ;
}
//______________________________________________________________________________
void TypedefPrinter : : DisplayTypedefs ( ) const
{
assert ( fInterpreter ! = 0 & & " DisplayTypedefs, fInterpreter is null " ) ;
const CompilerInstance * const compiler = fInterpreter - > getCI ( ) ;
assert ( compiler ! = 0 & & " DisplayTypedefs, compiler instance is null " ) ;
const TranslationUnitDecl * const tuDecl = compiler - > getASTContext ( ) . getTranslationUnitDecl ( ) ;
assert ( tuDecl ! = 0 & & " DisplayTypedefs, translation unit is empty " ) ;
//fSeenDecls.clear();
2012-12-06 06:57:39 +00:00
fOut . Print ( " List of typedefs " ) ;
2012-12-05 15:44:04 +00:00
ProcessNestedDeclarations ( tuDecl ) ;
}
//______________________________________________________________________________
void TypedefPrinter : : DisplayTypedef ( const std : : string & typedefName ) const
{
assert ( fInterpreter ! = 0 & & " DisplayTypedef, fInterpreter is null " ) ;
const cling : : LookupHelper & lookupHelper = fInterpreter - > getLookupHelper ( ) ;
const QualType type = lookupHelper . findType ( typedefName ) ;
if ( ! type . isNull ( ) ) {
if ( const TypedefType * const typedefType = type - > getAs < TypedefType > ( ) ) {
if ( typedefType - > getDecl ( ) ) {
2012-12-06 06:57:39 +00:00
DisplayTypedefDecl ( typedefType - > getDecl ( ) ) ;
return ;
} else
fOut . Print ( ( " A " + std : : string ( type - > getTypeClassName ( ) ) + " declaration "
" was found for " + typedefName + " \n " ) . c_str ( ) ) ;
2012-12-05 15:44:04 +00:00
}
}
fOut . Print ( ( " Type " + typedefName + " is not defined \n " ) . c_str ( ) ) ;
}
//______________________________________________________________________________
void TypedefPrinter : : ProcessNestedDeclarations ( const DeclContext * decl ) const
{
assert ( decl ! = 0 & & " ProcessNestedDeclarations, parameter 'decl' is null " ) ;
for ( decl_iterator it = decl - > decls_begin ( ) , eIt = decl - > decls_end ( ) ; it ! = eIt ; + + it )
ProcessDecl ( it ) ;
}
//______________________________________________________________________________
void TypedefPrinter : : ProcessDecl ( decl_iterator decl ) const
{
assert ( fInterpreter ! = 0 & & " ProcessDecl, fInterpreter is null " ) ;
assert ( * decl ! = 0 & & " ProcessDecl, parameter 'decl' is not a valid iterator " ) ;
switch ( decl - > getKind ( ) ) {
case Decl : : Typedef :
DisplayTypedefDecl ( dyn_cast < TypedefDecl > ( * decl ) ) ;
break ;
case Decl : : Namespace :
case Decl : : Block :
case Decl : : Function :
case Decl : : CXXMethod :
case Decl : : CXXConstructor :
case Decl : : CXXConversion :
case Decl : : CXXDestructor :
case Decl : : LinkageSpec :
case Decl : : CXXRecord :
case Decl : : ClassTemplateSpecialization :
//case Decl::ClassTemplatePartialSpecialization:
ProcessNestedDeclarations ( dyn_cast < DeclContext > ( * decl ) ) ;
break ;
default :
if ( FunctionDecl * const funDecl = dyn_cast < FunctionDecl > ( * decl ) )
ProcessNestedDeclarations ( funDecl ) ;
break ;
}
}
//______________________________________________________________________________
void TypedefPrinter : : DisplayTypedefDecl ( TypedefNameDecl * typedefDecl ) const
{
2012-12-06 06:57:39 +00:00
assert ( typedefDecl ! = 0
& & " DisplayTypedefDecl, parameter 'typedefDecl' is null " ) ;
2012-12-05 15:44:04 +00:00
assert ( fInterpreter ! = 0 & & " DisplayTypedefDecl, fInterpreter is null " ) ;
std : : string textLine ;
AppendDeclLocation ( fInterpreter - > getCI ( ) , typedefDecl , textLine ) ;
2012-12-06 06:57:39 +00:00
textLine + = " typedef " ;
2012-12-05 15:44:04 +00:00
{
2012-12-06 06:57:39 +00:00
const LangOptions langOpts ;
PrintingPolicy printingPolicy ( langOpts ) ;
printingPolicy . SuppressSpecifiers = false ;
printingPolicy . SuppressInitializers = true ;
printingPolicy . SuppressScope = false ;
printingPolicy . SuppressTagKeyword = true ;
llvm : : raw_string_ostream out ( textLine ) ;
2012-12-06 17:08:19 +00:00
typedefDecl - > getUnderlyingType ( ) .
getDesugaredType ( typedefDecl - > getASTContext ( ) ) . print ( out , printingPolicy ) ;
2012-12-06 06:57:39 +00:00
std : : string tmp ;
//Name for diagnostic will include template arguments if any.
2012-12-06 17:08:19 +00:00
typedefDecl - > getNameForDiagnostic ( tmp , printingPolicy , /*qualified=*/ true ) ;
2012-12-06 06:57:39 +00:00
out < < " " < < tmp ;
2012-12-05 15:44:04 +00:00
}
fOut . Print ( textLine . c_str ( ) ) ;
fOut . Print ( " \n " ) ;
}
2012-11-28 16:38:02 +00:00
} //unnamed namespace
//______________________________________________________________________________
2012-12-05 15:44:04 +00:00
void DisplayClasses ( llvm : : raw_ostream & stream , const Interpreter * interpreter ,
2012-11-29 20:40:53 +00:00
bool verbose )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( interpreter ! = 0 & & " DisplayClasses, 'interpreter' parameter is null " ) ;
2012-11-28 16:38:02 +00:00
2012-11-29 19:35:33 +00:00
ClassPrinter printer ( stream , interpreter ) ;
printer . SetVerbose ( verbose ) ;
printer . DisplayAllClasses ( ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-12-05 15:44:04 +00:00
void DisplayClass ( llvm : : raw_ostream & stream , const Interpreter * interpreter ,
2012-11-29 20:40:53 +00:00
const char * className , bool verbose )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( interpreter ! = 0 & & " DisplayClass, 'interpreter' parameter is null " ) ;
assert ( className ! = 0 & & " DisplayClass, 'className' parameter is null " ) ;
while ( std : : isspace ( * className ) )
+ + className ;
ClassPrinter printer ( stream , interpreter ) ;
if ( * className ) {
printer . SetVerbose ( verbose ) ;
printer . DisplayClass ( className ) ;
} else {
printer . SetVerbose ( true ) ; //?
printer . DisplayAllClasses ( ) ;
}
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-12-05 15:44:04 +00:00
void DisplayGlobals ( llvm : : raw_ostream & stream , const Interpreter * interpreter )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( interpreter ! = 0 & & " DisplayGlobals, 'interpreter' parameter is null " ) ;
GlobalsPrinter printer ( stream , interpreter ) ;
printer . DisplayGlobals ( ) ;
2012-11-28 16:38:02 +00:00
}
//______________________________________________________________________________
2012-12-05 15:44:04 +00:00
void DisplayGlobal ( llvm : : raw_ostream & stream , const Interpreter * interpreter ,
2012-11-29 20:40:53 +00:00
const std : : string & name )
2012-11-28 16:38:02 +00:00
{
2012-11-29 19:35:33 +00:00
assert ( interpreter ! = 0 & & " DisplayGlobal, 'interpreter' parameter is null " ) ;
GlobalsPrinter printer ( stream , interpreter ) ;
printer . DisplayGlobal ( name ) ;
2012-11-28 16:38:02 +00:00
}
2012-12-05 13:20:58 +00:00
//______________________________________________________________________________
void DisplayTypedefs ( llvm : : raw_ostream & stream , const Interpreter * interpreter )
{
2012-12-05 15:44:04 +00:00
assert ( interpreter ! = 0 & & " DisplayTypedefs, parameter 'interpreter' is null " ) ;
TypedefPrinter printer ( stream , interpreter ) ;
printer . DisplayTypedefs ( ) ;
2012-12-05 13:20:58 +00:00
}
//______________________________________________________________________________
void DisplayTypedef ( llvm : : raw_ostream & stream , const Interpreter * interpreter ,
const std : : string & name )
{
2012-12-05 15:44:04 +00:00
assert ( interpreter ! = 0 & & " DisplayTypedef, parameter 'interpreter' is null " ) ;
TypedefPrinter printer ( stream , interpreter ) ;
printer . DisplayTypedef ( name ) ;
2012-12-05 13:20:58 +00:00
}
2012-11-28 16:38:02 +00:00
} //namespace cling