2013-08-23 13:46:38 -04:00
//===-- ClangASTContext.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/Symbol/ClangASTContext.h"
// C Includes
// C++ Includes
2015-02-08 20:44:09 -05:00
# include <mutex> // std::once
2013-08-23 13:46:38 -04:00
# include <string>
// Other libraries and framework includes
// Clang headers like to use NDEBUG inside of them to enable/disable debug
2014-11-25 16:00:58 -05:00
// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
2013-08-23 13:46:38 -04:00
// or another. This is bad because it means that if clang was built in release
// mode, it assumes that you are building in release mode which is not always
// the case. You can end up with functions that are defined as empty in header
// files when NDEBUG is not defined, and this can cause link errors with the
// clang .a files that you have since you might be missing functions in the .a
// file. So we have to define NDEBUG when including clang headers to avoid any
// mismatches. This is covered by rdar://problem/8691220
# if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
# define LLDB_DEFINED_NDEBUG_FOR_CLANG
# define NDEBUG
// Need to include assert.h so it is as clang would expect it to be (disabled)
# include <assert.h>
# endif
# include "clang/AST/ASTContext.h"
# include "clang/AST/ASTImporter.h"
# include "clang/AST/Attr.h"
# include "clang/AST/CXXInheritance.h"
# include "clang/AST/DeclObjC.h"
# include "clang/AST/DeclTemplate.h"
# include "clang/AST/RecordLayout.h"
# include "clang/AST/Type.h"
# include "clang/Basic/Builtins.h"
# include "clang/Basic/Diagnostic.h"
# include "clang/Basic/FileManager.h"
# include "clang/Basic/FileSystemOptions.h"
# include "clang/Basic/SourceManager.h"
# include "clang/Basic/TargetInfo.h"
# include "clang/Basic/TargetOptions.h"
# include "clang/Frontend/FrontendOptions.h"
# include "clang/Frontend/LangStandard.h"
# ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
# undef NDEBUG
# undef LLDB_DEFINED_NDEBUG_FOR_CLANG
// Need to re-include assert.h so it is as _we_ would expect it to be (enabled)
# include <assert.h>
# endif
# include "lldb/Core/ArchSpec.h"
# include "lldb/Core/dwarf.h"
# include "lldb/Core/Flags.h"
# include "lldb/Core/Log.h"
# include "lldb/Core/RegularExpression.h"
2015-02-06 16:38:51 -05:00
# include "lldb/Core/ThreadSafeDenseMap.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/UniqueCStringMap.h"
# include "lldb/Expression/ASTDumper.h"
# include "lldb/Symbol/ClangExternalASTSourceCommon.h"
# include "lldb/Symbol/VerifyDecl.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/ObjCLanguageRuntime.h"
# include <stdio.h>
# include <mutex>
using namespace lldb ;
using namespace lldb_private ;
using namespace llvm ;
using namespace clang ;
2015-02-06 16:38:51 -05:00
typedef lldb_private : : ThreadSafeDenseMap < clang : : ASTContext * , ClangASTContext * > ClangASTMap ;
2014-11-25 16:00:58 -05:00
static ClangASTMap &
GetASTMap ( )
{
2015-02-06 16:38:51 -05:00
static ClangASTMap * g_map_ptr = nullptr ;
static std : : once_flag g_once_flag ;
std : : call_once ( g_once_flag , [ ] ( ) {
g_map_ptr = new ClangASTMap ( ) ; // leaked on purpose to avoid spins
} ) ;
return * g_map_ptr ;
2014-11-25 16:00:58 -05:00
}
2013-08-23 13:46:38 -04:00
clang : : AccessSpecifier
ClangASTContext : : ConvertAccessTypeToAccessSpecifier ( AccessType access )
{
switch ( access )
{
default : break ;
case eAccessNone : return AS_none ;
case eAccessPublic : return AS_public ;
case eAccessPrivate : return AS_private ;
case eAccessProtected : return AS_protected ;
}
return AS_none ;
}
static void
ParseLangArgs
(
LangOptions & Opts ,
InputKind IK
)
{
// FIXME: Cleanup per-file based stuff.
2014-11-25 16:00:58 -05:00
// Set some properties which depend solely on the input kind; it would be nice
2013-08-23 13:46:38 -04:00
// to move these to the language standard, and have the driver resolve the
// input kind + language standard.
if ( IK = = IK_Asm ) {
Opts . AsmPreprocessor = 1 ;
} else if ( IK = = IK_ObjC | |
IK = = IK_ObjCXX | |
IK = = IK_PreprocessedObjC | |
IK = = IK_PreprocessedObjCXX ) {
Opts . ObjC1 = Opts . ObjC2 = 1 ;
}
LangStandard : : Kind LangStd = LangStandard : : lang_unspecified ;
if ( LangStd = = LangStandard : : lang_unspecified ) {
// Based on the base language, pick one.
switch ( IK ) {
case IK_None :
case IK_AST :
case IK_LLVM_IR :
assert ( ! " Invalid input kind! " ) ;
case IK_OpenCL :
LangStd = LangStandard : : lang_opencl ;
break ;
case IK_CUDA :
LangStd = LangStandard : : lang_cuda ;
break ;
case IK_Asm :
case IK_C :
case IK_PreprocessedC :
case IK_ObjC :
case IK_PreprocessedObjC :
LangStd = LangStandard : : lang_gnu99 ;
break ;
case IK_CXX :
case IK_PreprocessedCXX :
case IK_ObjCXX :
case IK_PreprocessedObjCXX :
LangStd = LangStandard : : lang_gnucxx98 ;
break ;
}
}
const LangStandard & Std = LangStandard : : getLangStandardForKind ( LangStd ) ;
Opts . LineComment = Std . hasLineComments ( ) ;
Opts . C99 = Std . isC99 ( ) ;
Opts . CPlusPlus = Std . isCPlusPlus ( ) ;
Opts . CPlusPlus11 = Std . isCPlusPlus11 ( ) ;
Opts . Digraphs = Std . hasDigraphs ( ) ;
Opts . GNUMode = Std . isGNUMode ( ) ;
Opts . GNUInline = ! Std . isC99 ( ) ;
Opts . HexFloats = Std . hasHexFloats ( ) ;
Opts . ImplicitInt = Std . hasImplicitInt ( ) ;
Opts . WChar = true ;
// OpenCL has some additional defaults.
if ( LangStd = = LangStandard : : lang_opencl ) {
Opts . OpenCL = 1 ;
Opts . AltiVec = 1 ;
Opts . CXXOperatorNames = 1 ;
Opts . LaxVectorConversions = 1 ;
}
// OpenCL and C++ both have bool, true, false keywords.
Opts . Bool = Opts . OpenCL | | Opts . CPlusPlus ;
// if (Opts.CPlusPlus)
// Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names);
//
// if (Args.hasArg(OPT_fobjc_gc_only))
// Opts.setGCMode(LangOptions::GCOnly);
// else if (Args.hasArg(OPT_fobjc_gc))
// Opts.setGCMode(LangOptions::HybridGC);
//
// if (Args.hasArg(OPT_print_ivar_layout))
// Opts.ObjCGCBitmapPrint = 1;
//
// if (Args.hasArg(OPT_faltivec))
// Opts.AltiVec = 1;
//
// if (Args.hasArg(OPT_pthread))
// Opts.POSIXThreads = 1;
//
// llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility,
// "default");
// if (Vis == "default")
Opts . setValueVisibilityMode ( DefaultVisibility ) ;
// else if (Vis == "hidden")
// Opts.setVisibilityMode(LangOptions::Hidden);
// else if (Vis == "protected")
// Opts.setVisibilityMode(LangOptions::Protected);
// else
// Diags.Report(diag::err_drv_invalid_value)
// << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
// Opts.OverflowChecking = Args.hasArg(OPT_ftrapv);
// Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
// is specified, or -std is set to a conforming mode.
Opts . Trigraphs = ! Opts . GNUMode ;
// if (Args.hasArg(OPT_trigraphs))
// Opts.Trigraphs = 1;
//
// Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
// OPT_fno_dollars_in_identifiers,
// !Opts.AsmPreprocessor);
// Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
// Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
// Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
// if (Args.hasArg(OPT_fno_lax_vector_conversions))
// Opts.LaxVectorConversions = 0;
// Opts.Exceptions = Args.hasArg(OPT_fexceptions);
// Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
// Opts.Blocks = Args.hasArg(OPT_fblocks);
// Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
// Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
// Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
// Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
// Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
// Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
// Opts.AccessControl = Args.hasArg(OPT_faccess_control);
// Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
// Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno);
// Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99,
// Diags);
// Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
// Opts.ObjCConstantStringClass = getLastArgValue(Args,
// OPT_fconstant_string_class);
// Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
// Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
// Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
// Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
// Opts.Static = Args.hasArg(OPT_static_define);
Opts . OptimizeSize = 0 ;
// FIXME: Eliminate this dependency.
// unsigned Opt =
// Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
// Opts.Optimize = Opt != 0;
unsigned Opt = 0 ;
// This is the __NO_INLINE__ define, which just depends on things like the
// optimization level and -fno-inline, not actually whether the backend has
// inlining enabled.
//
// FIXME: This is affected by other options (-fno-inline).
Opts . NoInlineDefine = ! Opt ;
// unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags);
// switch (SSP) {
// default:
// Diags.Report(diag::err_drv_invalid_value)
// << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
// break;
// case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break;
// case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break;
// case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break;
// }
}
ClangASTContext : : ClangASTContext ( const char * target_triple ) :
m_target_triple ( ) ,
m_ast_ap ( ) ,
m_language_options_ap ( ) ,
m_source_manager_ap ( ) ,
m_diagnostics_engine_ap ( ) ,
m_target_options_rp ( ) ,
m_target_info_ap ( ) ,
m_identifier_table_ap ( ) ,
m_selector_table_ap ( ) ,
m_builtins_ap ( ) ,
2014-11-25 16:00:58 -05:00
m_callback_tag_decl ( nullptr ) ,
m_callback_objc_decl ( nullptr ) ,
m_callback_baton ( nullptr ) ,
2013-08-23 13:46:38 -04:00
m_pointer_byte_size ( 0 )
{
if ( target_triple & & target_triple [ 0 ] )
SetTargetTriple ( target_triple ) ;
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ClangASTContext : : ~ ClangASTContext ( )
{
2014-11-25 16:00:58 -05:00
if ( m_ast_ap . get ( ) )
{
2015-02-06 16:38:51 -05:00
GetASTMap ( ) . Erase ( m_ast_ap . get ( ) ) ;
2014-11-25 16:00:58 -05:00
}
2013-08-23 13:46:38 -04:00
m_builtins_ap . reset ( ) ;
m_selector_table_ap . reset ( ) ;
m_identifier_table_ap . reset ( ) ;
m_target_info_ap . reset ( ) ;
m_target_options_rp . reset ( ) ;
m_diagnostics_engine_ap . reset ( ) ;
m_source_manager_ap . reset ( ) ;
m_language_options_ap . reset ( ) ;
m_ast_ap . reset ( ) ;
}
void
ClangASTContext : : Clear ( )
{
m_ast_ap . reset ( ) ;
m_language_options_ap . reset ( ) ;
m_source_manager_ap . reset ( ) ;
m_diagnostics_engine_ap . reset ( ) ;
m_target_options_rp . reset ( ) ;
m_target_info_ap . reset ( ) ;
m_identifier_table_ap . reset ( ) ;
m_selector_table_ap . reset ( ) ;
m_builtins_ap . reset ( ) ;
m_pointer_byte_size = 0 ;
}
const char *
ClangASTContext : : GetTargetTriple ( )
{
return m_target_triple . c_str ( ) ;
}
void
ClangASTContext : : SetTargetTriple ( const char * target_triple )
{
Clear ( ) ;
m_target_triple . assign ( target_triple ) ;
}
void
ClangASTContext : : SetArchitecture ( const ArchSpec & arch )
{
SetTargetTriple ( arch . GetTriple ( ) . str ( ) . c_str ( ) ) ;
}
bool
ClangASTContext : : HasExternalSource ( )
{
ASTContext * ast = getASTContext ( ) ;
if ( ast )
2014-11-25 16:00:58 -05:00
return ast - > getExternalSource ( ) ! = nullptr ;
2013-08-23 13:46:38 -04:00
return false ;
}
void
2014-11-25 16:00:58 -05:00
ClangASTContext : : SetExternalSource ( llvm : : IntrusiveRefCntPtr < ExternalASTSource > & ast_source_ap )
2013-08-23 13:46:38 -04:00
{
ASTContext * ast = getASTContext ( ) ;
if ( ast )
{
ast - > setExternalSource ( ast_source_ap ) ;
ast - > getTranslationUnitDecl ( ) - > setHasExternalLexicalStorage ( true ) ;
//ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true);
}
}
void
ClangASTContext : : RemoveExternalSource ( )
{
ASTContext * ast = getASTContext ( ) ;
if ( ast )
{
2014-11-25 16:00:58 -05:00
llvm : : IntrusiveRefCntPtr < ExternalASTSource > empty_ast_source_ap ;
2013-08-23 13:46:38 -04:00
ast - > setExternalSource ( empty_ast_source_ap ) ;
ast - > getTranslationUnitDecl ( ) - > setHasExternalLexicalStorage ( false ) ;
//ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false);
}
}
ASTContext *
ClangASTContext : : getASTContext ( )
{
2014-11-25 16:00:58 -05:00
if ( m_ast_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
{
m_ast_ap . reset ( new ASTContext ( * getLanguageOptions ( ) ,
* getSourceManager ( ) ,
* getIdentifierTable ( ) ,
* getSelectorTable ( ) ,
2014-11-25 16:00:58 -05:00
* getBuiltinContext ( ) ) ) ;
m_ast_ap - > InitBuiltinTypes ( * getTargetInfo ( ) ) ;
2013-08-23 13:46:38 -04:00
if ( ( m_callback_tag_decl | | m_callback_objc_decl ) & & m_callback_baton )
{
m_ast_ap - > getTranslationUnitDecl ( ) - > setHasExternalLexicalStorage ( ) ;
//m_ast_ap->getTranslationUnitDecl()->setHasExternalVisibleStorage();
}
m_ast_ap - > getDiagnostics ( ) . setClient ( getDiagnosticConsumer ( ) , false ) ;
2014-11-25 16:00:58 -05:00
2015-02-06 16:38:51 -05:00
GetASTMap ( ) . Insert ( m_ast_ap . get ( ) , this ) ;
2013-08-23 13:46:38 -04:00
}
return m_ast_ap . get ( ) ;
}
2014-11-25 16:00:58 -05:00
ClangASTContext *
ClangASTContext : : GetASTContext ( clang : : ASTContext * ast )
{
2015-02-06 16:38:51 -05:00
ClangASTContext * clang_ast = GetASTMap ( ) . Lookup ( ast ) ;
2014-11-25 16:00:58 -05:00
return clang_ast ;
}
2013-08-23 13:46:38 -04:00
Builtin : : Context *
ClangASTContext : : getBuiltinContext ( )
{
2014-11-25 16:00:58 -05:00
if ( m_builtins_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
m_builtins_ap . reset ( new Builtin : : Context ( ) ) ;
return m_builtins_ap . get ( ) ;
}
IdentifierTable *
ClangASTContext : : getIdentifierTable ( )
{
2014-11-25 16:00:58 -05:00
if ( m_identifier_table_ap . get ( ) = = nullptr )
m_identifier_table_ap . reset ( new IdentifierTable ( * ClangASTContext : : getLanguageOptions ( ) , nullptr ) ) ;
2013-08-23 13:46:38 -04:00
return m_identifier_table_ap . get ( ) ;
}
LangOptions *
ClangASTContext : : getLanguageOptions ( )
{
2014-11-25 16:00:58 -05:00
if ( m_language_options_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
{
m_language_options_ap . reset ( new LangOptions ( ) ) ;
ParseLangArgs ( * m_language_options_ap , IK_ObjCXX ) ;
// InitializeLangOptions(*m_language_options_ap, IK_ObjCXX);
}
return m_language_options_ap . get ( ) ;
}
SelectorTable *
ClangASTContext : : getSelectorTable ( )
{
2014-11-25 16:00:58 -05:00
if ( m_selector_table_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
m_selector_table_ap . reset ( new SelectorTable ( ) ) ;
return m_selector_table_ap . get ( ) ;
}
clang : : FileManager *
ClangASTContext : : getFileManager ( )
{
2014-11-25 16:00:58 -05:00
if ( m_file_manager_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
{
clang : : FileSystemOptions file_system_options ;
m_file_manager_ap . reset ( new clang : : FileManager ( file_system_options ) ) ;
}
return m_file_manager_ap . get ( ) ;
}
clang : : SourceManager *
ClangASTContext : : getSourceManager ( )
{
2014-11-25 16:00:58 -05:00
if ( m_source_manager_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
m_source_manager_ap . reset ( new clang : : SourceManager ( * getDiagnosticsEngine ( ) , * getFileManager ( ) ) ) ;
return m_source_manager_ap . get ( ) ;
}
clang : : DiagnosticsEngine *
ClangASTContext : : getDiagnosticsEngine ( )
{
2014-11-25 16:00:58 -05:00
if ( m_diagnostics_engine_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
{
llvm : : IntrusiveRefCntPtr < DiagnosticIDs > diag_id_sp ( new DiagnosticIDs ( ) ) ;
m_diagnostics_engine_ap . reset ( new DiagnosticsEngine ( diag_id_sp , new DiagnosticOptions ( ) ) ) ;
}
return m_diagnostics_engine_ap . get ( ) ;
}
class NullDiagnosticConsumer : public DiagnosticConsumer
{
public :
NullDiagnosticConsumer ( )
{
m_log = lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ;
}
void HandleDiagnostic ( DiagnosticsEngine : : Level DiagLevel , const Diagnostic & info )
{
if ( m_log )
{
llvm : : SmallVector < char , 32 > diag_str ( 10 ) ;
info . FormatDiagnostic ( diag_str ) ;
diag_str . push_back ( ' \0 ' ) ;
m_log - > Printf ( " Compiler diagnostic: %s \n " , diag_str . data ( ) ) ;
}
}
DiagnosticConsumer * clone ( DiagnosticsEngine & Diags ) const
{
return new NullDiagnosticConsumer ( ) ;
}
private :
Log * m_log ;
} ;
DiagnosticConsumer *
ClangASTContext : : getDiagnosticConsumer ( )
{
2014-11-25 16:00:58 -05:00
if ( m_diagnostic_consumer_ap . get ( ) = = nullptr )
2013-08-23 13:46:38 -04:00
m_diagnostic_consumer_ap . reset ( new NullDiagnosticConsumer ) ;
return m_diagnostic_consumer_ap . get ( ) ;
}
2014-11-25 16:00:58 -05:00
std : : shared_ptr < TargetOptions > &
ClangASTContext : : getTargetOptions ( ) {
if ( m_target_options_rp . get ( ) = = nullptr & & ! m_target_triple . empty ( ) )
2013-08-23 13:46:38 -04:00
{
2014-11-25 16:00:58 -05:00
m_target_options_rp = std : : make_shared < TargetOptions > ( ) ;
if ( m_target_options_rp . get ( ) ! = nullptr )
2013-08-23 13:46:38 -04:00
m_target_options_rp - > Triple = m_target_triple ;
}
2014-11-25 16:00:58 -05:00
return m_target_options_rp ;
2013-08-23 13:46:38 -04:00
}
TargetInfo *
ClangASTContext : : getTargetInfo ( )
{
// target_triple should be something like "x86_64-apple-macosx"
2014-11-25 16:00:58 -05:00
if ( m_target_info_ap . get ( ) = = nullptr & & ! m_target_triple . empty ( ) )
2013-08-23 13:46:38 -04:00
m_target_info_ap . reset ( TargetInfo : : CreateTargetInfo ( * getDiagnosticsEngine ( ) , getTargetOptions ( ) ) ) ;
return m_target_info_ap . get ( ) ;
}
# pragma mark Basic Types
static inline bool
QualTypeMatchesBitSize ( const uint64_t bit_size , ASTContext * ast , QualType qual_type )
{
uint64_t qual_type_bit_size = ast - > getTypeSize ( qual_type ) ;
if ( qual_type_bit_size = = bit_size )
return true ;
return false ;
}
ClangASTType
ClangASTContext : : GetBuiltinTypeForEncodingAndBitSize ( Encoding encoding , uint32_t bit_size )
{
return ClangASTContext : : GetBuiltinTypeForEncodingAndBitSize ( getASTContext ( ) , encoding , bit_size ) ;
}
ClangASTType
ClangASTContext : : GetBuiltinTypeForEncodingAndBitSize ( ASTContext * ast , Encoding encoding , uint32_t bit_size )
{
if ( ! ast )
return ClangASTType ( ) ;
switch ( encoding )
{
case eEncodingInvalid :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > VoidPtrTy ) )
return ClangASTType ( ast , ast - > VoidPtrTy . getAsOpaquePtr ( ) ) ;
break ;
case eEncodingUint :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedCharTy ) )
return ClangASTType ( ast , ast - > UnsignedCharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedShortTy ) )
return ClangASTType ( ast , ast - > UnsignedShortTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedIntTy ) )
return ClangASTType ( ast , ast - > UnsignedIntTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedLongLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongLongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedInt128Ty ) )
return ClangASTType ( ast , ast - > UnsignedInt128Ty . getAsOpaquePtr ( ) ) ;
break ;
case eEncodingSint :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > CharTy ) )
return ClangASTType ( ast , ast - > CharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > ShortTy ) )
return ClangASTType ( ast , ast - > ShortTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > IntTy ) )
return ClangASTType ( ast , ast - > IntTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongTy ) )
return ClangASTType ( ast , ast - > LongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongLongTy ) )
return ClangASTType ( ast , ast - > LongLongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > Int128Ty ) )
return ClangASTType ( ast , ast - > Int128Ty . getAsOpaquePtr ( ) ) ;
break ;
case eEncodingIEEE754 :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > FloatTy ) )
return ClangASTType ( ast , ast - > FloatTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > DoubleTy ) )
return ClangASTType ( ast , ast - > DoubleTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongDoubleTy ) )
return ClangASTType ( ast , ast - > LongDoubleTy . getAsOpaquePtr ( ) ) ;
break ;
case eEncodingVector :
// Sanity check that bit_size is a multiple of 8's.
if ( bit_size & & ! ( bit_size & 0x7u ) )
return ClangASTType ( ast , ast - > getExtVectorType ( ast - > UnsignedCharTy , bit_size / 8 ) . getAsOpaquePtr ( ) ) ;
break ;
}
return ClangASTType ( ) ;
}
lldb : : BasicType
ClangASTContext : : GetBasicTypeEnumeration ( const ConstString & name )
{
if ( name )
{
typedef UniqueCStringMap < lldb : : BasicType > TypeNameToBasicTypeMap ;
static TypeNameToBasicTypeMap g_type_map ;
static std : : once_flag g_once_flag ;
std : : call_once ( g_once_flag , [ ] ( ) {
// "void"
g_type_map . Append ( ConstString ( " void " ) . GetCString ( ) , eBasicTypeVoid ) ;
// "char"
g_type_map . Append ( ConstString ( " char " ) . GetCString ( ) , eBasicTypeChar ) ;
g_type_map . Append ( ConstString ( " signed char " ) . GetCString ( ) , eBasicTypeSignedChar ) ;
g_type_map . Append ( ConstString ( " unsigned char " ) . GetCString ( ) , eBasicTypeUnsignedChar ) ;
g_type_map . Append ( ConstString ( " wchar_t " ) . GetCString ( ) , eBasicTypeWChar ) ;
g_type_map . Append ( ConstString ( " signed wchar_t " ) . GetCString ( ) , eBasicTypeSignedWChar ) ;
g_type_map . Append ( ConstString ( " unsigned wchar_t " ) . GetCString ( ) , eBasicTypeUnsignedWChar ) ;
// "short"
g_type_map . Append ( ConstString ( " short " ) . GetCString ( ) , eBasicTypeShort ) ;
g_type_map . Append ( ConstString ( " short int " ) . GetCString ( ) , eBasicTypeShort ) ;
g_type_map . Append ( ConstString ( " unsigned short " ) . GetCString ( ) , eBasicTypeUnsignedShort ) ;
g_type_map . Append ( ConstString ( " unsigned short int " ) . GetCString ( ) , eBasicTypeUnsignedShort ) ;
// "int"
g_type_map . Append ( ConstString ( " int " ) . GetCString ( ) , eBasicTypeInt ) ;
g_type_map . Append ( ConstString ( " signed int " ) . GetCString ( ) , eBasicTypeInt ) ;
g_type_map . Append ( ConstString ( " unsigned int " ) . GetCString ( ) , eBasicTypeUnsignedInt ) ;
g_type_map . Append ( ConstString ( " unsigned " ) . GetCString ( ) , eBasicTypeUnsignedInt ) ;
// "long"
g_type_map . Append ( ConstString ( " long " ) . GetCString ( ) , eBasicTypeLong ) ;
g_type_map . Append ( ConstString ( " long int " ) . GetCString ( ) , eBasicTypeLong ) ;
g_type_map . Append ( ConstString ( " unsigned long " ) . GetCString ( ) , eBasicTypeUnsignedLong ) ;
g_type_map . Append ( ConstString ( " unsigned long int " ) . GetCString ( ) , eBasicTypeUnsignedLong ) ;
// "long long"
g_type_map . Append ( ConstString ( " long long " ) . GetCString ( ) , eBasicTypeLongLong ) ;
g_type_map . Append ( ConstString ( " long long int " ) . GetCString ( ) , eBasicTypeLongLong ) ;
g_type_map . Append ( ConstString ( " unsigned long long " ) . GetCString ( ) , eBasicTypeUnsignedLongLong ) ;
g_type_map . Append ( ConstString ( " unsigned long long int " ) . GetCString ( ) , eBasicTypeUnsignedLongLong ) ;
// "int128"
g_type_map . Append ( ConstString ( " __int128_t " ) . GetCString ( ) , eBasicTypeInt128 ) ;
g_type_map . Append ( ConstString ( " __uint128_t " ) . GetCString ( ) , eBasicTypeUnsignedInt128 ) ;
2014-11-25 16:00:58 -05:00
// Miscellaneous
2013-08-23 13:46:38 -04:00
g_type_map . Append ( ConstString ( " bool " ) . GetCString ( ) , eBasicTypeBool ) ;
g_type_map . Append ( ConstString ( " float " ) . GetCString ( ) , eBasicTypeFloat ) ;
g_type_map . Append ( ConstString ( " double " ) . GetCString ( ) , eBasicTypeDouble ) ;
g_type_map . Append ( ConstString ( " long double " ) . GetCString ( ) , eBasicTypeLongDouble ) ;
g_type_map . Append ( ConstString ( " id " ) . GetCString ( ) , eBasicTypeObjCID ) ;
g_type_map . Append ( ConstString ( " SEL " ) . GetCString ( ) , eBasicTypeObjCSel ) ;
g_type_map . Append ( ConstString ( " nullptr " ) . GetCString ( ) , eBasicTypeNullPtr ) ;
g_type_map . Sort ( ) ;
} ) ;
return g_type_map . Find ( name . GetCString ( ) , eBasicTypeInvalid ) ;
}
return eBasicTypeInvalid ;
}
ClangASTType
ClangASTContext : : GetBasicType ( ASTContext * ast , const ConstString & name )
{
if ( ast )
{
lldb : : BasicType basic_type = ClangASTContext : : GetBasicTypeEnumeration ( name ) ;
return ClangASTContext : : GetBasicType ( ast , basic_type ) ;
}
return ClangASTType ( ) ;
}
uint32_t
ClangASTContext : : GetPointerByteSize ( )
{
if ( m_pointer_byte_size = = 0 )
2015-02-08 20:44:09 -05:00
m_pointer_byte_size = GetBasicType ( lldb : : eBasicTypeVoid ) . GetPointerType ( ) . GetByteSize ( nullptr ) ;
2013-08-23 13:46:38 -04:00
return m_pointer_byte_size ;
}
ClangASTType
ClangASTContext : : GetBasicType ( lldb : : BasicType basic_type )
{
return GetBasicType ( getASTContext ( ) , basic_type ) ;
}
ClangASTType
ClangASTContext : : GetBasicType ( ASTContext * ast , lldb : : BasicType basic_type )
{
if ( ast )
{
2014-11-25 16:00:58 -05:00
clang_type_t clang_type = nullptr ;
2013-08-23 13:46:38 -04:00
switch ( basic_type )
{
case eBasicTypeInvalid :
case eBasicTypeOther :
break ;
case eBasicTypeVoid :
clang_type = ast - > VoidTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeChar :
clang_type = ast - > CharTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeSignedChar :
clang_type = ast - > SignedCharTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedChar :
clang_type = ast - > UnsignedCharTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeWChar :
clang_type = ast - > getWCharType ( ) . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeSignedWChar :
clang_type = ast - > getSignedWCharType ( ) . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedWChar :
clang_type = ast - > getUnsignedWCharType ( ) . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeChar16 :
clang_type = ast - > Char16Ty . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeChar32 :
clang_type = ast - > Char32Ty . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeShort :
clang_type = ast - > ShortTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedShort :
clang_type = ast - > UnsignedShortTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeInt :
clang_type = ast - > IntTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedInt :
clang_type = ast - > UnsignedIntTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeLong :
clang_type = ast - > LongTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedLong :
clang_type = ast - > UnsignedLongTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeLongLong :
clang_type = ast - > LongLongTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedLongLong :
clang_type = ast - > UnsignedLongLongTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeInt128 :
clang_type = ast - > Int128Ty . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeUnsignedInt128 :
clang_type = ast - > UnsignedInt128Ty . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeBool :
clang_type = ast - > BoolTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeHalf :
clang_type = ast - > HalfTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeFloat :
clang_type = ast - > FloatTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeDouble :
clang_type = ast - > DoubleTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeLongDouble :
clang_type = ast - > LongDoubleTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeFloatComplex :
clang_type = ast - > FloatComplexTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeDoubleComplex :
clang_type = ast - > DoubleComplexTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeLongDoubleComplex :
clang_type = ast - > LongDoubleComplexTy . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeObjCID :
clang_type = ast - > getObjCIdType ( ) . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeObjCClass :
clang_type = ast - > getObjCClassType ( ) . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeObjCSel :
clang_type = ast - > getObjCSelType ( ) . getAsOpaquePtr ( ) ;
break ;
case eBasicTypeNullPtr :
clang_type = ast - > NullPtrTy . getAsOpaquePtr ( ) ;
break ;
}
if ( clang_type )
return ClangASTType ( ast , clang_type ) ;
}
return ClangASTType ( ) ;
}
ClangASTType
ClangASTContext : : GetBuiltinTypeForDWARFEncodingAndBitSize ( const char * type_name , uint32_t dw_ate , uint32_t bit_size )
{
ASTContext * ast = getASTContext ( ) ;
# define streq(a,b) strcmp(a,b) == 0
2014-11-25 16:00:58 -05:00
assert ( ast ! = nullptr ) ;
2013-08-23 13:46:38 -04:00
if ( ast )
{
switch ( dw_ate )
{
default :
break ;
case DW_ATE_address :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > VoidPtrTy ) )
return ClangASTType ( ast , ast - > VoidPtrTy . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_boolean :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > BoolTy ) )
return ClangASTType ( ast , ast - > BoolTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedCharTy ) )
return ClangASTType ( ast , ast - > UnsignedCharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedShortTy ) )
return ClangASTType ( ast , ast - > UnsignedShortTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedIntTy ) )
return ClangASTType ( ast , ast - > UnsignedIntTy . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_lo_user :
// This has been seen to mean DW_AT_complex_integer
if ( type_name )
{
if ( : : strstr ( type_name , " complex " ) )
{
ClangASTType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ( " int " , DW_ATE_signed , bit_size / 2 ) ;
return ClangASTType ( ast , ast - > getComplexType ( complex_int_clang_type . GetQualType ( ) ) . getAsOpaquePtr ( ) ) ;
}
}
break ;
case DW_ATE_complex_float :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > FloatComplexTy ) )
return ClangASTType ( ast , ast - > FloatComplexTy . getAsOpaquePtr ( ) ) ;
else if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > DoubleComplexTy ) )
return ClangASTType ( ast , ast - > DoubleComplexTy . getAsOpaquePtr ( ) ) ;
else if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongDoubleComplexTy ) )
return ClangASTType ( ast , ast - > LongDoubleComplexTy . getAsOpaquePtr ( ) ) ;
else
{
ClangASTType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ( " float " , DW_ATE_float , bit_size / 2 ) ;
return ClangASTType ( ast , ast - > getComplexType ( complex_float_clang_type . GetQualType ( ) ) . getAsOpaquePtr ( ) ) ;
}
break ;
case DW_ATE_float :
2015-02-06 16:38:51 -05:00
if ( streq ( type_name , " float " ) & & QualTypeMatchesBitSize ( bit_size , ast , ast - > FloatTy ) )
return ClangASTType ( ast , ast - > FloatTy . getAsOpaquePtr ( ) ) ;
if ( streq ( type_name , " double " ) & & QualTypeMatchesBitSize ( bit_size , ast , ast - > DoubleTy ) )
return ClangASTType ( ast , ast - > DoubleTy . getAsOpaquePtr ( ) ) ;
if ( streq ( type_name , " long double " ) & & QualTypeMatchesBitSize ( bit_size , ast , ast - > LongDoubleTy ) )
return ClangASTType ( ast , ast - > LongDoubleTy . getAsOpaquePtr ( ) ) ;
// Fall back to not requring a name match
2013-08-23 13:46:38 -04:00
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > FloatTy ) )
return ClangASTType ( ast , ast - > FloatTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > DoubleTy ) )
return ClangASTType ( ast , ast - > DoubleTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongDoubleTy ) )
return ClangASTType ( ast , ast - > LongDoubleTy . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_signed :
if ( type_name )
{
if ( streq ( type_name , " wchar_t " ) & &
QualTypeMatchesBitSize ( bit_size , ast , ast - > WCharTy ) )
return ClangASTType ( ast , ast - > WCharTy . getAsOpaquePtr ( ) ) ;
if ( streq ( type_name , " void " ) & &
QualTypeMatchesBitSize ( bit_size , ast , ast - > VoidTy ) )
return ClangASTType ( ast , ast - > VoidTy . getAsOpaquePtr ( ) ) ;
if ( strstr ( type_name , " long long " ) & &
QualTypeMatchesBitSize ( bit_size , ast , ast - > LongLongTy ) )
return ClangASTType ( ast , ast - > LongLongTy . getAsOpaquePtr ( ) ) ;
if ( strstr ( type_name , " long " ) & &
QualTypeMatchesBitSize ( bit_size , ast , ast - > LongTy ) )
return ClangASTType ( ast , ast - > LongTy . getAsOpaquePtr ( ) ) ;
if ( strstr ( type_name , " short " ) & &
QualTypeMatchesBitSize ( bit_size , ast , ast - > ShortTy ) )
return ClangASTType ( ast , ast - > ShortTy . getAsOpaquePtr ( ) ) ;
if ( strstr ( type_name , " char " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > CharTy ) )
return ClangASTType ( ast , ast - > CharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > SignedCharTy ) )
return ClangASTType ( ast , ast - > SignedCharTy . getAsOpaquePtr ( ) ) ;
}
if ( strstr ( type_name , " int " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > IntTy ) )
return ClangASTType ( ast , ast - > IntTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > Int128Ty ) )
return ClangASTType ( ast , ast - > Int128Ty . getAsOpaquePtr ( ) ) ;
}
}
// We weren't able to match up a type name, just search by size
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > CharTy ) )
return ClangASTType ( ast , ast - > CharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > ShortTy ) )
return ClangASTType ( ast , ast - > ShortTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > IntTy ) )
return ClangASTType ( ast , ast - > IntTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongTy ) )
return ClangASTType ( ast , ast - > LongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > LongLongTy ) )
return ClangASTType ( ast , ast - > LongLongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > Int128Ty ) )
return ClangASTType ( ast , ast - > Int128Ty . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_signed_char :
if ( type_name )
{
if ( streq ( type_name , " signed char " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > SignedCharTy ) )
return ClangASTType ( ast , ast - > SignedCharTy . getAsOpaquePtr ( ) ) ;
}
}
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > CharTy ) )
return ClangASTType ( ast , ast - > CharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > SignedCharTy ) )
return ClangASTType ( ast , ast - > SignedCharTy . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_unsigned :
if ( type_name )
{
if ( strstr ( type_name , " long long " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedLongLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongLongTy . getAsOpaquePtr ( ) ) ;
}
else if ( strstr ( type_name , " long " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongTy . getAsOpaquePtr ( ) ) ;
}
else if ( strstr ( type_name , " short " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedShortTy ) )
return ClangASTType ( ast , ast - > UnsignedShortTy . getAsOpaquePtr ( ) ) ;
}
else if ( strstr ( type_name , " char " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedCharTy ) )
return ClangASTType ( ast , ast - > UnsignedCharTy . getAsOpaquePtr ( ) ) ;
}
else if ( strstr ( type_name , " int " ) )
{
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedIntTy ) )
return ClangASTType ( ast , ast - > UnsignedIntTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedInt128Ty ) )
return ClangASTType ( ast , ast - > UnsignedInt128Ty . getAsOpaquePtr ( ) ) ;
}
}
// We weren't able to match up a type name, just search by size
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedCharTy ) )
return ClangASTType ( ast , ast - > UnsignedCharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedShortTy ) )
return ClangASTType ( ast , ast - > UnsignedShortTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedIntTy ) )
return ClangASTType ( ast , ast - > UnsignedIntTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedLongLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongLongTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedInt128Ty ) )
return ClangASTType ( ast , ast - > UnsignedInt128Ty . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_unsigned_char :
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedCharTy ) )
return ClangASTType ( ast , ast - > UnsignedCharTy . getAsOpaquePtr ( ) ) ;
if ( QualTypeMatchesBitSize ( bit_size , ast , ast - > UnsignedShortTy ) )
return ClangASTType ( ast , ast - > UnsignedShortTy . getAsOpaquePtr ( ) ) ;
break ;
case DW_ATE_imaginary_float :
break ;
case DW_ATE_UTF :
if ( type_name )
{
if ( streq ( type_name , " char16_t " ) )
{
return ClangASTType ( ast , ast - > Char16Ty . getAsOpaquePtr ( ) ) ;
}
else if ( streq ( type_name , " char32_t " ) )
{
return ClangASTType ( ast , ast - > Char32Ty . getAsOpaquePtr ( ) ) ;
}
}
break ;
}
}
// This assert should fire for anything that we don't catch above so we know
// to fix any issues we run into.
if ( type_name )
{
Host : : SystemLog ( Host : : eSystemLogError , " error: need to add support for DW_TAG_base_type '%s' encoded with DW_ATE = 0x%x, bit_size = %u \n " , type_name , dw_ate , bit_size ) ;
}
else
{
Host : : SystemLog ( Host : : eSystemLogError , " error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u \n " , dw_ate , bit_size ) ;
}
return ClangASTType ( ) ;
}
ClangASTType
ClangASTContext : : GetUnknownAnyType ( clang : : ASTContext * ast )
{
if ( ast )
return ClangASTType ( ast , ast - > UnknownAnyTy . getAsOpaquePtr ( ) ) ;
return ClangASTType ( ) ;
}
ClangASTType
ClangASTContext : : GetCStringType ( bool is_const )
{
ASTContext * ast = getASTContext ( ) ;
QualType char_type ( ast - > CharTy ) ;
if ( is_const )
char_type . addConst ( ) ;
return ClangASTType ( ast , ast - > getPointerType ( char_type ) . getAsOpaquePtr ( ) ) ;
}
clang : : DeclContext *
ClangASTContext : : GetTranslationUnitDecl ( clang : : ASTContext * ast )
{
return ast - > getTranslationUnitDecl ( ) ;
}
ClangASTType
ClangASTContext : : CopyType ( ASTContext * dst_ast ,
ClangASTType src )
{
FileSystemOptions file_system_options ;
ASTContext * src_ast = src . GetASTContext ( ) ;
FileManager file_manager ( file_system_options ) ;
ASTImporter importer ( * dst_ast , file_manager ,
* src_ast , file_manager ,
false ) ;
QualType dst ( importer . Import ( src . GetQualType ( ) ) ) ;
return ClangASTType ( dst_ast , dst . getAsOpaquePtr ( ) ) ;
}
clang : : Decl *
ClangASTContext : : CopyDecl ( ASTContext * dst_ast ,
ASTContext * src_ast ,
clang : : Decl * source_decl )
{
FileSystemOptions file_system_options ;
FileManager file_manager ( file_system_options ) ;
ASTImporter importer ( * dst_ast , file_manager ,
* src_ast , file_manager ,
false ) ;
return importer . Import ( source_decl ) ;
}
bool
ClangASTContext : : AreTypesSame ( ClangASTType type1 ,
ClangASTType type2 ,
bool ignore_qualifiers )
{
ASTContext * ast = type1 . GetASTContext ( ) ;
if ( ast ! = type2 . GetASTContext ( ) )
return false ;
if ( type1 . GetOpaqueQualType ( ) = = type2 . GetOpaqueQualType ( ) )
return true ;
QualType type1_qual = type1 . GetQualType ( ) ;
QualType type2_qual = type2 . GetQualType ( ) ;
if ( ignore_qualifiers )
{
type1_qual = type1_qual . getUnqualifiedType ( ) ;
type2_qual = type2_qual . getUnqualifiedType ( ) ;
}
return ast - > hasSameType ( type1_qual , type2_qual ) ;
}
2015-02-06 16:38:51 -05:00
ClangASTType
ClangASTContext : : GetTypeForDecl ( clang : : NamedDecl * decl )
{
if ( clang : : ObjCInterfaceDecl * interface_decl = llvm : : dyn_cast < clang : : ObjCInterfaceDecl > ( decl ) )
return GetTypeForDecl ( interface_decl ) ;
if ( clang : : TagDecl * tag_decl = llvm : : dyn_cast < clang : : TagDecl > ( decl ) )
return GetTypeForDecl ( tag_decl ) ;
return ClangASTType ( ) ;
}
2013-08-23 13:46:38 -04:00
ClangASTType
ClangASTContext : : GetTypeForDecl ( TagDecl * decl )
{
// No need to call the getASTContext() accessor (which can create the AST
// if it isn't created yet, because we can't have created a decl in this
// AST if our AST didn't already exist...
2015-02-06 16:38:51 -05:00
ASTContext * ast = & decl - > getASTContext ( ) ;
2013-08-23 13:46:38 -04:00
if ( ast )
return ClangASTType ( ast , ast - > getTagDeclType ( decl ) . getAsOpaquePtr ( ) ) ;
return ClangASTType ( ) ;
}
ClangASTType
ClangASTContext : : GetTypeForDecl ( ObjCInterfaceDecl * decl )
{
// No need to call the getASTContext() accessor (which can create the AST
// if it isn't created yet, because we can't have created a decl in this
// AST if our AST didn't already exist...
2015-02-06 16:38:51 -05:00
ASTContext * ast = & decl - > getASTContext ( ) ;
2013-08-23 13:46:38 -04:00
if ( ast )
return ClangASTType ( ast , ast - > getObjCInterfaceType ( decl ) . getAsOpaquePtr ( ) ) ;
return ClangASTType ( ) ;
}
# pragma mark Structure, Unions, Classes
ClangASTType
ClangASTContext : : CreateRecordType ( DeclContext * decl_ctx ,
AccessType access_type ,
const char * name ,
int kind ,
LanguageType language ,
ClangASTMetadata * metadata )
{
ASTContext * ast = getASTContext ( ) ;
2014-11-25 16:00:58 -05:00
assert ( ast ! = nullptr ) ;
2013-08-23 13:46:38 -04:00
2014-11-25 16:00:58 -05:00
if ( decl_ctx = = nullptr )
2013-08-23 13:46:38 -04:00
decl_ctx = ast - > getTranslationUnitDecl ( ) ;
if ( language = = eLanguageTypeObjC | | language = = eLanguageTypeObjC_plus_plus )
{
bool isForwardDecl = true ;
bool isInternal = false ;
return CreateObjCClass ( name , decl_ctx , isForwardDecl , isInternal , metadata ) ;
}
// NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
// we will need to update this code. I was told to currently always use
// the CXXRecordDecl class since we often don't know from debug information
// if something is struct or a class, so we default to always use the more
// complete definition just in case.
2014-02-18 11:23:10 -05:00
bool is_anonymous = ( ! name ) | | ( ! name [ 0 ] ) ;
2013-08-23 13:46:38 -04:00
CXXRecordDecl * decl = CXXRecordDecl : : Create ( * ast ,
( TagDecl : : TagKind ) kind ,
decl_ctx ,
SourceLocation ( ) ,
SourceLocation ( ) ,
2014-11-25 16:00:58 -05:00
is_anonymous ? nullptr : & ast - > Idents . get ( name ) ) ;
2014-02-18 11:23:10 -05:00
if ( is_anonymous )
decl - > setAnonymousStructOrUnion ( true ) ;
2013-08-23 13:46:38 -04:00
if ( decl )
{
if ( metadata )
SetMetadata ( ast , decl , * metadata ) ;
if ( access_type ! = eAccessNone )
decl - > setAccess ( ConvertAccessTypeToAccessSpecifier ( access_type ) ) ;
if ( decl_ctx )
decl_ctx - > addDecl ( decl ) ;
return ClangASTType ( ast , ast - > getTagDeclType ( decl ) . getAsOpaquePtr ( ) ) ;
}
return ClangASTType ( ) ;
}
static TemplateParameterList *
CreateTemplateParameterList ( ASTContext * ast ,
const ClangASTContext : : TemplateParameterInfos & template_param_infos ,
llvm : : SmallVector < NamedDecl * , 8 > & template_param_decls )
{
const bool parameter_pack = false ;
const bool is_typename = false ;
const unsigned depth = 0 ;
const size_t num_template_params = template_param_infos . GetSize ( ) ;
for ( size_t i = 0 ; i < num_template_params ; + + i )
{
const char * name = template_param_infos . names [ i ] ;
2014-11-25 16:00:58 -05:00
IdentifierInfo * identifier_info = nullptr ;
2013-08-23 13:46:38 -04:00
if ( name & & name [ 0 ] )
identifier_info = & ast - > Idents . get ( name ) ;
if ( template_param_infos . args [ i ] . getKind ( ) = = TemplateArgument : : Integral )
{
template_param_decls . push_back ( NonTypeTemplateParmDecl : : Create ( * ast ,
ast - > getTranslationUnitDecl ( ) , // Is this the right decl context?, SourceLocation StartLoc,
SourceLocation ( ) ,
SourceLocation ( ) ,
depth ,
i ,
identifier_info ,
template_param_infos . args [ i ] . getIntegralType ( ) ,
parameter_pack ,
2014-11-25 16:00:58 -05:00
nullptr ) ) ;
2013-08-23 13:46:38 -04:00
}
else
{
template_param_decls . push_back ( TemplateTypeParmDecl : : Create ( * ast ,
ast - > getTranslationUnitDecl ( ) , // Is this the right decl context?
SourceLocation ( ) ,
SourceLocation ( ) ,
depth ,
i ,
identifier_info ,
is_typename ,
parameter_pack ) ) ;
}
}
TemplateParameterList * template_param_list = TemplateParameterList : : Create ( * ast ,
SourceLocation ( ) ,
SourceLocation ( ) ,
& template_param_decls . front ( ) ,
template_param_decls . size ( ) ,
SourceLocation ( ) ) ;
return template_param_list ;
}
clang : : FunctionTemplateDecl *
ClangASTContext : : CreateFunctionTemplateDecl ( clang : : DeclContext * decl_ctx ,
clang : : FunctionDecl * func_decl ,
const char * name ,
const TemplateParameterInfos & template_param_infos )
{
// /// \brief Create a function template node.
ASTContext * ast = getASTContext ( ) ;
llvm : : SmallVector < NamedDecl * , 8 > template_param_decls ;
TemplateParameterList * template_param_list = CreateTemplateParameterList ( ast ,
template_param_infos ,
template_param_decls ) ;
FunctionTemplateDecl * func_tmpl_decl = FunctionTemplateDecl : : Create ( * ast ,
decl_ctx ,
func_decl - > getLocation ( ) ,
func_decl - > getDeclName ( ) ,
template_param_list ,
func_decl ) ;
for ( size_t i = 0 , template_param_decl_count = template_param_decls . size ( ) ;
i < template_param_decl_count ;
+ + i )
{
// TODO: verify which decl context we should put template_param_decls into..
template_param_decls [ i ] - > setDeclContext ( func_decl ) ;
}
return func_tmpl_decl ;
}
void
ClangASTContext : : CreateFunctionTemplateSpecializationInfo ( FunctionDecl * func_decl ,
clang : : FunctionTemplateDecl * func_tmpl_decl ,
const TemplateParameterInfos & infos )
{
TemplateArgumentList template_args ( TemplateArgumentList : : OnStack ,
infos . args . data ( ) ,
infos . args . size ( ) ) ;
func_decl - > setFunctionTemplateSpecialization ( func_tmpl_decl ,
& template_args ,
2014-11-25 16:00:58 -05:00
nullptr ) ;
2013-08-23 13:46:38 -04:00
}
ClassTemplateDecl *
ClangASTContext : : CreateClassTemplateDecl ( DeclContext * decl_ctx ,
lldb : : AccessType access_type ,
const char * class_name ,
int kind ,
const TemplateParameterInfos & template_param_infos )
{
ASTContext * ast = getASTContext ( ) ;
2014-11-25 16:00:58 -05:00
ClassTemplateDecl * class_template_decl = nullptr ;
if ( decl_ctx = = nullptr )
2013-08-23 13:46:38 -04:00
decl_ctx = ast - > getTranslationUnitDecl ( ) ;
IdentifierInfo & identifier_info = ast - > Idents . get ( class_name ) ;
DeclarationName decl_name ( & identifier_info ) ;
clang : : DeclContext : : lookup_result result = decl_ctx - > lookup ( decl_name ) ;
for ( NamedDecl * decl : result )
{
class_template_decl = dyn_cast < clang : : ClassTemplateDecl > ( decl ) ;
if ( class_template_decl )
return class_template_decl ;
}
llvm : : SmallVector < NamedDecl * , 8 > template_param_decls ;
TemplateParameterList * template_param_list = CreateTemplateParameterList ( ast ,
template_param_infos ,
template_param_decls ) ;
CXXRecordDecl * template_cxx_decl = CXXRecordDecl : : Create ( * ast ,
( TagDecl : : TagKind ) kind ,
decl_ctx , // What decl context do we use here? TU? The actual decl context?
SourceLocation ( ) ,
SourceLocation ( ) ,
& identifier_info ) ;
for ( size_t i = 0 , template_param_decl_count = template_param_decls . size ( ) ;
i < template_param_decl_count ;
+ + i )
{
template_param_decls [ i ] - > setDeclContext ( template_cxx_decl ) ;
}
// With templated classes, we say that a class is templated with
// specializations, but that the bare class has no functions.
//template_cxx_decl->startDefinition();
//template_cxx_decl->completeDefinition();
class_template_decl = ClassTemplateDecl : : Create ( * ast ,
decl_ctx , // What decl context do we use here? TU? The actual decl context?
SourceLocation ( ) ,
decl_name ,
template_param_list ,
template_cxx_decl ,
2014-11-25 16:00:58 -05:00
nullptr ) ;
2013-08-23 13:46:38 -04:00
if ( class_template_decl )
{
if ( access_type ! = eAccessNone )
class_template_decl - > setAccess ( ConvertAccessTypeToAccessSpecifier ( access_type ) ) ;
//if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx))
// CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl));
decl_ctx - > addDecl ( class_template_decl ) ;
# ifdef LLDB_CONFIGURATION_DEBUG
VerifyDecl ( class_template_decl ) ;
# endif
}
return class_template_decl ;
}
ClassTemplateSpecializationDecl *
ClangASTContext : : CreateClassTemplateSpecializationDecl ( DeclContext * decl_ctx ,
ClassTemplateDecl * class_template_decl ,
int kind ,
const TemplateParameterInfos & template_param_infos )
{
ASTContext * ast = getASTContext ( ) ;
ClassTemplateSpecializationDecl * class_template_specialization_decl = ClassTemplateSpecializationDecl : : Create ( * ast ,
( TagDecl : : TagKind ) kind ,
decl_ctx ,
SourceLocation ( ) ,
SourceLocation ( ) ,
class_template_decl ,
& template_param_infos . args . front ( ) ,
template_param_infos . args . size ( ) ,
2014-11-25 16:00:58 -05:00
nullptr ) ;
2013-08-23 13:46:38 -04:00
class_template_specialization_decl - > setSpecializationKind ( TSK_ExplicitSpecialization ) ;
return class_template_specialization_decl ;
}
ClangASTType
ClangASTContext : : CreateClassTemplateSpecializationType ( ClassTemplateSpecializationDecl * class_template_specialization_decl )
{
if ( class_template_specialization_decl )
{
ASTContext * ast = getASTContext ( ) ;
if ( ast )
return ClangASTType ( ast , ast - > getTagDeclType ( class_template_specialization_decl ) . getAsOpaquePtr ( ) ) ;
}
return ClangASTType ( ) ;
}
static inline bool
check_op_param ( uint32_t op_kind , bool unary , bool binary , uint32_t num_params )
{
// Special-case call since it can take any number of operands
if ( op_kind = = OO_Call )
return true ;
2014-11-25 16:00:58 -05:00
// The parameter count doesn't include "this"
2013-08-23 13:46:38 -04:00
if ( num_params = = 0 )
return unary ;
if ( num_params = = 1 )
return binary ;
else
return false ;
}
bool
ClangASTContext : : CheckOverloadedOperatorKindParameterCount ( uint32_t op_kind , uint32_t num_params )
{
switch ( op_kind )
{
default :
break ;
// C++ standard allows any number of arguments to new/delete
case OO_New :
case OO_Array_New :
case OO_Delete :
case OO_Array_Delete :
return true ;
}
# define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) case OO_##Name: return check_op_param (op_kind, Unary, Binary, num_params);
switch ( op_kind )
{
# include "clang/Basic/OperatorKinds.def"
default : break ;
}
return false ;
}
clang : : AccessSpecifier
ClangASTContext : : UnifyAccessSpecifiers ( clang : : AccessSpecifier lhs , clang : : AccessSpecifier rhs )
{
clang : : AccessSpecifier ret = lhs ;
// Make the access equal to the stricter of the field and the nested field's access
switch ( ret )
{
case clang : : AS_none :
break ;
case clang : : AS_private :
break ;
case clang : : AS_protected :
if ( rhs = = AS_private )
ret = AS_private ;
break ;
case clang : : AS_public :
ret = rhs ;
break ;
}
return ret ;
}
bool
ClangASTContext : : FieldIsBitfield ( FieldDecl * field , uint32_t & bitfield_bit_size )
{
return FieldIsBitfield ( getASTContext ( ) , field , bitfield_bit_size ) ;
}
bool
ClangASTContext : : FieldIsBitfield
(
ASTContext * ast ,
FieldDecl * field ,
uint32_t & bitfield_bit_size
)
{
2014-11-25 16:00:58 -05:00
if ( ast = = nullptr | | field = = nullptr )
2013-08-23 13:46:38 -04:00
return false ;
if ( field - > isBitField ( ) )
{
Expr * bit_width_expr = field - > getBitWidth ( ) ;
if ( bit_width_expr )
{
llvm : : APSInt bit_width_apsint ;
if ( bit_width_expr - > isIntegerConstantExpr ( bit_width_apsint , * ast ) )
{
bitfield_bit_size = bit_width_apsint . getLimitedValue ( UINT32_MAX ) ;
return true ;
}
}
}
return false ;
}
bool
ClangASTContext : : RecordHasFields ( const RecordDecl * record_decl )
{
2014-11-25 16:00:58 -05:00
if ( record_decl = = nullptr )
2013-08-23 13:46:38 -04:00
return false ;
if ( ! record_decl - > field_empty ( ) )
return true ;
// No fields, lets check this is a CXX record and check the base classes
const CXXRecordDecl * cxx_record_decl = dyn_cast < CXXRecordDecl > ( record_decl ) ;
if ( cxx_record_decl )
{
CXXRecordDecl : : base_class_const_iterator base_class , base_class_end ;
for ( base_class = cxx_record_decl - > bases_begin ( ) , base_class_end = cxx_record_decl - > bases_end ( ) ;
base_class ! = base_class_end ;
+ + base_class )
{
const CXXRecordDecl * base_class_decl = cast < CXXRecordDecl > ( base_class - > getType ( ) - > getAs < RecordType > ( ) - > getDecl ( ) ) ;
if ( RecordHasFields ( base_class_decl ) )
return true ;
}
}
return false ;
}
# pragma mark Objective C Classes
ClangASTType
ClangASTContext : : CreateObjCClass
(
const char * name ,
DeclContext * decl_ctx ,
bool isForwardDecl ,
bool isInternal ,
ClangASTMetadata * metadata
)
{
ASTContext * ast = getASTContext ( ) ;
2014-11-25 16:00:58 -05:00
assert ( ast ! = nullptr ) ;
2013-08-23 13:46:38 -04:00
assert ( name & & name [ 0 ] ) ;
2014-11-25 16:00:58 -05:00
if ( decl_ctx = = nullptr )
2013-08-23 13:46:38 -04:00
decl_ctx = ast - > getTranslationUnitDecl ( ) ;
ObjCInterfaceDecl * decl = ObjCInterfaceDecl : : Create ( * ast ,
decl_ctx ,
SourceLocation ( ) ,
& ast - > Idents . get ( name ) ,
2014-11-25 16:00:58 -05:00
nullptr ,
2013-08-23 13:46:38 -04:00
SourceLocation ( ) ,
/*isForwardDecl,*/
isInternal ) ;
if ( decl & & metadata )
SetMetadata ( ast , decl , * metadata ) ;
return ClangASTType ( ast , ast - > getObjCInterfaceType ( decl ) ) ;
}
static inline bool
BaseSpecifierIsEmpty ( const CXXBaseSpecifier * b )
{
return ClangASTContext : : RecordHasFields ( b - > getType ( ) - > getAsCXXRecordDecl ( ) ) = = false ;
}
uint32_t
ClangASTContext : : GetNumBaseClasses ( const CXXRecordDecl * cxx_record_decl , bool omit_empty_base_classes )
{
uint32_t num_bases = 0 ;
if ( cxx_record_decl )
{
if ( omit_empty_base_classes )
{
CXXRecordDecl : : base_class_const_iterator base_class , base_class_end ;
for ( base_class = cxx_record_decl - > bases_begin ( ) , base_class_end = cxx_record_decl - > bases_end ( ) ;
base_class ! = base_class_end ;
+ + base_class )
{
// Skip empty base classes
if ( omit_empty_base_classes )
{
if ( BaseSpecifierIsEmpty ( base_class ) )
continue ;
}
+ + num_bases ;
}
}
else
num_bases = cxx_record_decl - > getNumBases ( ) ;
}
return num_bases ;
}
# pragma mark Namespace Declarations
NamespaceDecl *
ClangASTContext : : GetUniqueNamespaceDeclaration ( const char * name , DeclContext * decl_ctx )
{
2014-11-25 16:00:58 -05:00
NamespaceDecl * namespace_decl = nullptr ;
2013-08-23 13:46:38 -04:00
ASTContext * ast = getASTContext ( ) ;
TranslationUnitDecl * translation_unit_decl = ast - > getTranslationUnitDecl ( ) ;
2014-11-25 16:00:58 -05:00
if ( decl_ctx = = nullptr )
2013-08-23 13:46:38 -04:00
decl_ctx = translation_unit_decl ;
if ( name )
{
IdentifierInfo & identifier_info = ast - > Idents . get ( name ) ;
DeclarationName decl_name ( & identifier_info ) ;
clang : : DeclContext : : lookup_result result = decl_ctx - > lookup ( decl_name ) ;
for ( NamedDecl * decl : result )
{
namespace_decl = dyn_cast < clang : : NamespaceDecl > ( decl ) ;
if ( namespace_decl )
return namespace_decl ;
}
namespace_decl = NamespaceDecl : : Create ( * ast ,
decl_ctx ,
false ,
SourceLocation ( ) ,
SourceLocation ( ) ,
& identifier_info ,
2014-11-25 16:00:58 -05:00
nullptr ) ;
2013-08-23 13:46:38 -04:00
decl_ctx - > addDecl ( namespace_decl ) ;
}
else
{
if ( decl_ctx = = translation_unit_decl )
{
namespace_decl = translation_unit_decl - > getAnonymousNamespace ( ) ;
if ( namespace_decl )
return namespace_decl ;
namespace_decl = NamespaceDecl : : Create ( * ast ,
decl_ctx ,
false ,
SourceLocation ( ) ,
SourceLocation ( ) ,
2014-11-25 16:00:58 -05:00
nullptr ,
nullptr ) ;
2013-08-23 13:46:38 -04:00
translation_unit_decl - > setAnonymousNamespace ( namespace_decl ) ;
translation_unit_decl - > addDecl ( namespace_decl ) ;
assert ( namespace_decl = = translation_unit_decl - > getAnonymousNamespace ( ) ) ;
}
else
{
NamespaceDecl * parent_namespace_decl = cast < NamespaceDecl > ( decl_ctx ) ;
if ( parent_namespace_decl )
{
namespace_decl = parent_namespace_decl - > getAnonymousNamespace ( ) ;
if ( namespace_decl )
return namespace_decl ;
namespace_decl = NamespaceDecl : : Create ( * ast ,
decl_ctx ,
false ,
SourceLocation ( ) ,
SourceLocation ( ) ,
2014-11-25 16:00:58 -05:00
nullptr ,
nullptr ) ;
2013-08-23 13:46:38 -04:00
parent_namespace_decl - > setAnonymousNamespace ( namespace_decl ) ;
parent_namespace_decl - > addDecl ( namespace_decl ) ;
assert ( namespace_decl = = parent_namespace_decl - > getAnonymousNamespace ( ) ) ;
}
else
{
// BAD!!!
}
}
if ( namespace_decl )
{
// If we make it here, we are creating the anonymous namespace decl
// for the first time, so we need to do the using directive magic
// like SEMA does
UsingDirectiveDecl * using_directive_decl = UsingDirectiveDecl : : Create ( * ast ,
decl_ctx ,
SourceLocation ( ) ,
SourceLocation ( ) ,
NestedNameSpecifierLoc ( ) ,
SourceLocation ( ) ,
namespace_decl ,
decl_ctx ) ;
using_directive_decl - > setImplicit ( ) ;
decl_ctx - > addDecl ( using_directive_decl ) ;
}
}
# ifdef LLDB_CONFIGURATION_DEBUG
VerifyDecl ( namespace_decl ) ;
# endif
return namespace_decl ;
}
# pragma mark Function Types
FunctionDecl *
ClangASTContext : : CreateFunctionDeclaration ( DeclContext * decl_ctx ,
const char * name ,
const ClangASTType & function_clang_type ,
int storage ,
bool is_inline )
{
2014-11-25 16:00:58 -05:00
FunctionDecl * func_decl = nullptr ;
2013-08-23 13:46:38 -04:00
ASTContext * ast = getASTContext ( ) ;
2014-11-25 16:00:58 -05:00
if ( decl_ctx = = nullptr )
2013-08-23 13:46:38 -04:00
decl_ctx = ast - > getTranslationUnitDecl ( ) ;
const bool hasWrittenPrototype = true ;
const bool isConstexprSpecified = false ;
if ( name & & name [ 0 ] )
{
func_decl = FunctionDecl : : Create ( * ast ,
decl_ctx ,
SourceLocation ( ) ,
SourceLocation ( ) ,
DeclarationName ( & ast - > Idents . get ( name ) ) ,
function_clang_type . GetQualType ( ) ,
2014-11-25 16:00:58 -05:00
nullptr ,
2015-02-06 16:38:51 -05:00
( clang : : StorageClass ) storage ,
2013-08-23 13:46:38 -04:00
is_inline ,
hasWrittenPrototype ,
isConstexprSpecified ) ;
}
else
{
func_decl = FunctionDecl : : Create ( * ast ,
decl_ctx ,
SourceLocation ( ) ,
SourceLocation ( ) ,
DeclarationName ( ) ,
function_clang_type . GetQualType ( ) ,
2014-11-25 16:00:58 -05:00
nullptr ,
2015-02-06 16:38:51 -05:00
( clang : : StorageClass ) storage ,
2013-08-23 13:46:38 -04:00
is_inline ,
hasWrittenPrototype ,
isConstexprSpecified ) ;
}
if ( func_decl )
decl_ctx - > addDecl ( func_decl ) ;
# ifdef LLDB_CONFIGURATION_DEBUG
VerifyDecl ( func_decl ) ;
# endif
return func_decl ;
}
ClangASTType
ClangASTContext : : CreateFunctionType ( ASTContext * ast ,
const ClangASTType & result_type ,
const ClangASTType * args ,
unsigned num_args ,
bool is_variadic ,
unsigned type_quals )
{
2014-11-25 16:00:58 -05:00
assert ( ast ! = nullptr ) ;
2013-08-23 13:46:38 -04:00
std : : vector < QualType > qual_type_args ;
for ( unsigned i = 0 ; i < num_args ; + + i )
qual_type_args . push_back ( args [ i ] . GetQualType ( ) ) ;
// TODO: Detect calling convention in DWARF?
FunctionProtoType : : ExtProtoInfo proto_info ;
proto_info . Variadic = is_variadic ;
2014-11-25 16:00:58 -05:00
proto_info . ExceptionSpec = EST_None ;
2013-08-23 13:46:38 -04:00
proto_info . TypeQuals = type_quals ;
proto_info . RefQualifier = RQ_None ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return ClangASTType ( ast , ast - > getFunctionType ( result_type . GetQualType ( ) ,
qual_type_args ,
proto_info ) . getAsOpaquePtr ( ) ) ;
}
ParmVarDecl *
ClangASTContext : : CreateParameterDeclaration ( const char * name , const ClangASTType & param_type , int storage )
{
ASTContext * ast = getASTContext ( ) ;
2014-11-25 16:00:58 -05:00
assert ( ast ! = nullptr ) ;
2013-08-23 13:46:38 -04:00
return ParmVarDecl : : Create ( * ast ,
ast - > getTranslationUnitDecl ( ) ,
SourceLocation ( ) ,
SourceLocation ( ) ,
2014-11-25 16:00:58 -05:00
name & & name [ 0 ] ? & ast - > Idents . get ( name ) : nullptr ,
2013-08-23 13:46:38 -04:00
param_type . GetQualType ( ) ,
2014-11-25 16:00:58 -05:00
nullptr ,
2015-02-06 16:38:51 -05:00
( clang : : StorageClass ) storage ,
2014-11-25 16:00:58 -05:00
nullptr ) ;
2013-08-23 13:46:38 -04:00
}
void
ClangASTContext : : SetFunctionParameters ( FunctionDecl * function_decl , ParmVarDecl * * params , unsigned num_params )
{
if ( function_decl )
function_decl - > setParams ( ArrayRef < ParmVarDecl * > ( params , num_params ) ) ;
}
# pragma mark Array Types
ClangASTType
ClangASTContext : : CreateArrayType ( const ClangASTType & element_type ,
size_t element_count ,
bool is_vector )
{
if ( element_type . IsValid ( ) )
{
ASTContext * ast = getASTContext ( ) ;
2014-11-25 16:00:58 -05:00
assert ( ast ! = nullptr ) ;
2013-08-23 13:46:38 -04:00
if ( is_vector )
{
return ClangASTType ( ast , ast - > getExtVectorType ( element_type . GetQualType ( ) , element_count ) . getAsOpaquePtr ( ) ) ;
}
else
{
llvm : : APInt ap_element_count ( 64 , element_count ) ;
if ( element_count = = 0 )
{
return ClangASTType ( ast , ast - > getIncompleteArrayType ( element_type . GetQualType ( ) ,
ArrayType : : Normal ,
0 ) . getAsOpaquePtr ( ) ) ;
}
else
{
return ClangASTType ( ast , ast - > getConstantArrayType ( element_type . GetQualType ( ) ,
ap_element_count ,
ArrayType : : Normal ,
0 ) . getAsOpaquePtr ( ) ) ;
}
}
}
return ClangASTType ( ) ;
}
2015-02-06 16:38:51 -05:00
ClangASTType
ClangASTContext : : GetOrCreateStructForIdentifier ( const ConstString & type_name ,
const std : : initializer_list < std : : pair < const char * , ClangASTType > > & type_fields ,
bool packed )
{
ClangASTType type ;
if ( ( type = GetTypeForIdentifier < clang : : CXXRecordDecl > ( type_name ) ) . IsValid ( ) )
return type ;
type = CreateRecordType ( nullptr , lldb : : eAccessPublic , type_name . GetCString ( ) , clang : : TTK_Struct , lldb : : eLanguageTypeC ) ;
type . StartTagDeclarationDefinition ( ) ;
for ( const auto & field : type_fields )
type . AddFieldToRecordType ( field . first , field . second , lldb : : eAccessPublic , 0 ) ;
if ( packed )
type . SetIsPacked ( ) ;
type . CompleteTagDeclarationDefinition ( ) ;
return type ;
}
2013-08-23 13:46:38 -04:00
# pragma mark Enumeration Types
ClangASTType
ClangASTContext : : CreateEnumerationType
(
const char * name ,
DeclContext * decl_ctx ,
const Declaration & decl ,
const ClangASTType & integer_clang_type
)
{
// TODO: Do something intelligent with the Declaration object passed in
// like maybe filling in the SourceLocation with it...
ASTContext * ast = getASTContext ( ) ;
// TODO: ask about these...
// const bool IsScoped = false;
// const bool IsFixed = false;
EnumDecl * enum_decl = EnumDecl : : Create ( * ast ,
decl_ctx ,
SourceLocation ( ) ,
SourceLocation ( ) ,
2014-11-25 16:00:58 -05:00
name & & name [ 0 ] ? & ast - > Idents . get ( name ) : nullptr ,
nullptr ,
2013-08-23 13:46:38 -04:00
false , // IsScoped
false , // IsScopedUsingClassTag
false ) ; // IsFixed
if ( enum_decl )
{
// TODO: check if we should be setting the promotion type too?
enum_decl - > setIntegerType ( integer_clang_type . GetQualType ( ) ) ;
enum_decl - > setAccess ( AS_public ) ; // TODO respect what's in the debug info
return ClangASTType ( ast , ast - > getTagDeclType ( enum_decl ) . getAsOpaquePtr ( ) ) ;
}
return ClangASTType ( ) ;
}
// Disable this for now since I can't seem to get a nicely formatted float
// out of the APFloat class without just getting the float, double or quad
// and then using a formatted print on it which defeats the purpose. We ideally
// would like to get perfect string values for any kind of float semantics
// so we can support remote targets. The code below also requires a patch to
// llvm::APInt.
//bool
//ClangASTContext::ConvertFloatValueToString (ASTContext *ast, clang_type_t clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str)
//{
// uint32_t count = 0;
// bool is_complex = false;
// if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex))
// {
// unsigned num_bytes_per_float = byte_size / count;
// unsigned num_bits_per_float = num_bytes_per_float * 8;
//
// float_str.clear();
// uint32_t i;
// for (i=0; i<count; i++)
// {
// APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, (APInt::ByteOrder)apint_byte_order);
// bool is_ieee = false;
// APFloat ap_float(ap_int, is_ieee);
// char s[1024];
// unsigned int hex_digits = 0;
// bool upper_case = false;
//
// if (ap_float.convertToHexString(s, hex_digits, upper_case, APFloat::rmNearestTiesToEven) > 0)
// {
// if (i > 0)
// float_str.append(", ");
// float_str.append(s);
// if (i == 1 && is_complex)
// float_str.append(1, 'i');
// }
// }
// return !float_str.empty();
// }
// return false;
//}
2014-11-25 16:00:58 -05:00
ClangASTType
ClangASTContext : : GetIntTypeFromBitSize ( clang : : ASTContext * ast ,
size_t bit_size , bool is_signed )
{
if ( ast )
{
if ( is_signed )
{
if ( bit_size = = ast - > getTypeSize ( ast - > SignedCharTy ) )
return ClangASTType ( ast , ast - > SignedCharTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > ShortTy ) )
return ClangASTType ( ast , ast - > ShortTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > IntTy ) )
return ClangASTType ( ast , ast - > IntTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > LongTy ) )
return ClangASTType ( ast , ast - > LongTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > LongLongTy ) )
return ClangASTType ( ast , ast - > LongLongTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > Int128Ty ) )
return ClangASTType ( ast , ast - > Int128Ty . getAsOpaquePtr ( ) ) ;
}
else
{
if ( bit_size = = ast - > getTypeSize ( ast - > UnsignedCharTy ) )
return ClangASTType ( ast , ast - > UnsignedCharTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > UnsignedShortTy ) )
return ClangASTType ( ast , ast - > UnsignedShortTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > UnsignedIntTy ) )
return ClangASTType ( ast , ast - > UnsignedIntTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > UnsignedLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > UnsignedLongLongTy ) )
return ClangASTType ( ast , ast - > UnsignedLongLongTy . getAsOpaquePtr ( ) ) ;
if ( bit_size = = ast - > getTypeSize ( ast - > UnsignedInt128Ty ) )
return ClangASTType ( ast , ast - > UnsignedInt128Ty . getAsOpaquePtr ( ) ) ;
}
}
return ClangASTType ( ) ;
}
ClangASTType
ClangASTContext : : GetPointerSizedIntType ( clang : : ASTContext * ast , bool is_signed )
{
if ( ast )
return GetIntTypeFromBitSize ( ast , ast - > getTypeSize ( ast - > VoidPtrTy ) , is_signed ) ;
return ClangASTType ( ) ;
}
2013-08-23 13:46:38 -04:00
ClangASTType
ClangASTContext : : GetFloatTypeFromBitSize ( clang : : ASTContext * ast ,
size_t bit_size )
{
if ( ast )
{
if ( bit_size = = ast - > getTypeSize ( ast - > FloatTy ) )
return ClangASTType ( ast , ast - > FloatTy . getAsOpaquePtr ( ) ) ;
else if ( bit_size = = ast - > getTypeSize ( ast - > DoubleTy ) )
return ClangASTType ( ast , ast - > DoubleTy . getAsOpaquePtr ( ) ) ;
else if ( bit_size = = ast - > getTypeSize ( ast - > LongDoubleTy ) )
return ClangASTType ( ast , ast - > LongDoubleTy . getAsOpaquePtr ( ) ) ;
else if ( bit_size = = ast - > getTypeSize ( ast - > HalfTy ) )
return ClangASTType ( ast , ast - > HalfTy . getAsOpaquePtr ( ) ) ;
}
return ClangASTType ( ) ;
}
bool
ClangASTContext : : GetCompleteDecl ( clang : : ASTContext * ast ,
clang : : Decl * decl )
{
if ( ! decl )
return false ;
ExternalASTSource * ast_source = ast - > getExternalSource ( ) ;
if ( ! ast_source )
return false ;
if ( clang : : TagDecl * tag_decl = llvm : : dyn_cast < clang : : TagDecl > ( decl ) )
{
if ( tag_decl - > isCompleteDefinition ( ) )
return true ;
if ( ! tag_decl - > hasExternalLexicalStorage ( ) )
return false ;
ast_source - > CompleteType ( tag_decl ) ;
return ! tag_decl - > getTypeForDecl ( ) - > isIncompleteType ( ) ;
}
else if ( clang : : ObjCInterfaceDecl * objc_interface_decl = llvm : : dyn_cast < clang : : ObjCInterfaceDecl > ( decl ) )
{
if ( objc_interface_decl - > getDefinition ( ) )
return true ;
if ( ! objc_interface_decl - > hasExternalLexicalStorage ( ) )
return false ;
ast_source - > CompleteType ( objc_interface_decl ) ;
return ! objc_interface_decl - > getTypeForDecl ( ) - > isIncompleteType ( ) ;
}
else
{
return false ;
}
}
void
ClangASTContext : : SetMetadataAsUserID ( const void * object ,
user_id_t user_id )
{
ClangASTMetadata meta_data ;
meta_data . SetUserID ( user_id ) ;
SetMetadata ( object , meta_data ) ;
}
void
ClangASTContext : : SetMetadata ( clang : : ASTContext * ast ,
const void * object ,
ClangASTMetadata & metadata )
{
ClangExternalASTSourceCommon * external_source =
2015-02-06 16:38:51 -05:00
ClangExternalASTSourceCommon : : Lookup ( ast - > getExternalSource ( ) ) ;
2013-08-23 13:46:38 -04:00
if ( external_source )
external_source - > SetMetadata ( object , metadata ) ;
}
ClangASTMetadata *
ClangASTContext : : GetMetadata ( clang : : ASTContext * ast ,
const void * object )
{
ClangExternalASTSourceCommon * external_source =
2015-02-06 16:38:51 -05:00
ClangExternalASTSourceCommon : : Lookup ( ast - > getExternalSource ( ) ) ;
2013-08-23 13:46:38 -04:00
if ( external_source & & external_source - > HasMetadata ( object ) )
return external_source - > GetMetadata ( object ) ;
else
2014-11-25 16:00:58 -05:00
return nullptr ;
2013-08-23 13:46:38 -04:00
}
clang : : DeclContext *
ClangASTContext : : GetAsDeclContext ( clang : : CXXMethodDecl * cxx_method_decl )
{
return llvm : : dyn_cast < clang : : DeclContext > ( cxx_method_decl ) ;
}
clang : : DeclContext *
ClangASTContext : : GetAsDeclContext ( clang : : ObjCMethodDecl * objc_method_decl )
{
return llvm : : dyn_cast < clang : : DeclContext > ( objc_method_decl ) ;
}
bool
ClangASTContext : : GetClassMethodInfoForDeclContext ( clang : : DeclContext * decl_ctx ,
lldb : : LanguageType & language ,
bool & is_instance_method ,
ConstString & language_object_name )
{
language_object_name . Clear ( ) ;
language = eLanguageTypeUnknown ;
is_instance_method = false ;
if ( decl_ctx )
{
if ( clang : : CXXMethodDecl * method_decl = llvm : : dyn_cast < clang : : CXXMethodDecl > ( decl_ctx ) )
{
if ( method_decl - > isStatic ( ) )
{
is_instance_method = false ;
}
else
{
language_object_name . SetCString ( " this " ) ;
is_instance_method = true ;
}
language = eLanguageTypeC_plus_plus ;
return true ;
}
else if ( clang : : ObjCMethodDecl * method_decl = llvm : : dyn_cast < clang : : ObjCMethodDecl > ( decl_ctx ) )
{
// Both static and instance methods have a "self" object in objective C
language_object_name . SetCString ( " self " ) ;
if ( method_decl - > isInstanceMethod ( ) )
{
is_instance_method = true ;
}
else
{
is_instance_method = false ;
}
language = eLanguageTypeObjC ;
return true ;
}
else if ( clang : : FunctionDecl * function_decl = llvm : : dyn_cast < clang : : FunctionDecl > ( decl_ctx ) )
{
ClangASTMetadata * metadata = GetMetadata ( & decl_ctx - > getParentASTContext ( ) , function_decl ) ;
if ( metadata & & metadata - > HasObjectPtr ( ) )
{
language_object_name . SetCString ( metadata - > GetObjectPtrName ( ) ) ;
language = eLanguageTypeObjC ;
is_instance_method = true ;
}
return true ;
}
}
return false ;
}