diff options
Diffstat (limited to 'lldb/source/Symbol/ClangASTContext.cpp')
| -rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 6325 |
1 files changed, 0 insertions, 6325 deletions
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp deleted file mode 100644 index 1d7063b4ebba..000000000000 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ /dev/null @@ -1,6325 +0,0 @@ -//===-- 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 -#include <string> - -// Other libraries and framework includes - -// Clang headers like to use NDEBUG inside of them to enable/disable debug -// releated features using "#ifndef NDEBUG" preprocessor blocks to do one thing -// 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/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" -#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> - -using namespace lldb; -using namespace lldb_private; -using namespace llvm; -using namespace clang; - - -static bool -GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true) -{ - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ConstantArray: - { - const clang::ArrayType *array_type = dyn_cast<clang::ArrayType>(qual_type.getTypePtr()); - - if (array_type) - return GetCompleteQualType (ast, array_type->getElementType(), allow_completion); - } - break; - - case clang::Type::Record: - case clang::Type::Enum: - { - const clang::TagType *tag_type = dyn_cast<clang::TagType>(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - if (tag_decl->isCompleteDefinition()) - return true; - - if (!allow_completion) - return false; - - if (tag_decl->hasExternalLexicalStorage()) - { - if (ast) - { - ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType(tag_decl); - return !tag_type->isIncompleteType(); - } - } - } - return false; - } - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (class_interface_decl->getDefinition()) - return true; - - if (!allow_completion) - return false; - - if (class_interface_decl->hasExternalLexicalStorage()) - { - if (ast) - { - ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType (class_interface_decl); - return !objc_class_type->isIncompleteType(); - } - } - } - return false; - } - } - } - break; - - case clang::Type::Typedef: - return GetCompleteQualType (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion); - - case clang::Type::Elaborated: - return GetCompleteQualType (ast, cast<ElaboratedType>(qual_type)->getNamedType(), allow_completion); - - default: - break; - } - - return true; -} - -static AccessSpecifier -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 ObjCIvarDecl::AccessControl -ConvertAccessTypeToObjCIvarAccessControl (AccessType access) -{ - switch (access) - { - default: break; - case eAccessNone: return ObjCIvarDecl::None; - case eAccessPublic: return ObjCIvarDecl::Public; - case eAccessPrivate: return ObjCIvarDecl::Private; - case eAccessProtected: return ObjCIvarDecl::Protected; - case eAccessPackage: return ObjCIvarDecl::Package; - } - return ObjCIvarDecl::None; -} - - -static void -ParseLangArgs -( - LangOptions &Opts, - InputKind IK -) -{ - // FIXME: Cleanup per-file based stuff. - - // Set some properties which depend soley on the input kind; it would be nice - // 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.BCPLComment = Std.hasBCPLComments(); - Opts.C99 = Std.isC99(); - Opts.CPlusPlus = Std.isCPlusPlus(); - Opts.CPlusPlus0x = Std.isCPlusPlus0x(); - Opts.Digraphs = Std.hasDigraphs(); - Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = !Std.isC99(); - Opts.HexFloats = Std.hasHexFloats(); - Opts.ImplicitInt = Std.hasImplicitInt(); - - // 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.setVisibilityMode(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.NoInline = !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_ap(), - m_target_info_ap(), - m_identifier_table_ap(), - m_selector_table_ap(), - m_builtins_ap(), - m_callback_tag_decl (NULL), - m_callback_objc_decl (NULL), - m_callback_baton (NULL) - -{ - if (target_triple && target_triple[0]) - SetTargetTriple (target_triple); -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -ClangASTContext::~ClangASTContext() -{ - m_builtins_ap.reset(); - m_selector_table_ap.reset(); - m_identifier_table_ap.reset(); - m_target_info_ap.reset(); - m_target_options_ap.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_ap.reset(); - m_target_info_ap.reset(); - m_identifier_table_ap.reset(); - m_selector_table_ap.reset(); - m_builtins_ap.reset(); -} - -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) - return ast->getExternalSource () != NULL; - return false; -} - -void -ClangASTContext::SetExternalSource (llvm::OwningPtr<ExternalASTSource> &ast_source_ap) -{ - 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) - { - llvm::OwningPtr<ExternalASTSource> empty_ast_source_ap; - ast->setExternalSource (empty_ast_source_ap); - ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); - //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); - } -} - - - -ASTContext * -ClangASTContext::getASTContext() -{ - if (m_ast_ap.get() == NULL) - { - m_ast_ap.reset(new ASTContext (*getLanguageOptions(), - *getSourceManager(), - getTargetInfo(), - *getIdentifierTable(), - *getSelectorTable(), - *getBuiltinContext(), - 0)); - - 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); - } - return m_ast_ap.get(); -} - -Builtin::Context * -ClangASTContext::getBuiltinContext() -{ - if (m_builtins_ap.get() == NULL) - m_builtins_ap.reset (new Builtin::Context()); - return m_builtins_ap.get(); -} - -IdentifierTable * -ClangASTContext::getIdentifierTable() -{ - if (m_identifier_table_ap.get() == NULL) - m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), NULL)); - return m_identifier_table_ap.get(); -} - -LangOptions * -ClangASTContext::getLanguageOptions() -{ - if (m_language_options_ap.get() == NULL) - { - 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() -{ - if (m_selector_table_ap.get() == NULL) - m_selector_table_ap.reset (new SelectorTable()); - return m_selector_table_ap.get(); -} - -clang::FileManager * -ClangASTContext::getFileManager() -{ - if (m_file_manager_ap.get() == NULL) - { - 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() -{ - if (m_source_manager_ap.get() == NULL) - m_source_manager_ap.reset(new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager())); - return m_source_manager_ap.get(); -} - -clang::DiagnosticsEngine * -ClangASTContext::getDiagnosticsEngine() -{ - if (m_diagnostics_engine_ap.get() == NULL) - { - llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs()); - m_diagnostics_engine_ap.reset(new DiagnosticsEngine(diag_id_sp)); - } - 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: - LogSP m_log; -}; - -DiagnosticConsumer * -ClangASTContext::getDiagnosticConsumer() -{ - if (m_diagnostic_consumer_ap.get() == NULL) - m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer); - - return m_diagnostic_consumer_ap.get(); -} - -TargetOptions * -ClangASTContext::getTargetOptions() -{ - if (m_target_options_ap.get() == NULL && !m_target_triple.empty()) - { - m_target_options_ap.reset (new TargetOptions()); - if (m_target_options_ap.get()) - m_target_options_ap->Triple = m_target_triple; - } - return m_target_options_ap.get(); -} - - -TargetInfo * -ClangASTContext::getTargetInfo() -{ - // target_triple should be something like "x86_64-apple-darwin10" - if (m_target_info_ap.get() == NULL && !m_target_triple.empty()) - 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; -} - -clang_type_t -ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (Encoding encoding, uint32_t bit_size) -{ - ASTContext *ast = getASTContext(); - - assert (ast != NULL); - - return GetBuiltinTypeForEncodingAndBitSize (ast, encoding, bit_size); -} - -clang_type_t -ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (ASTContext *ast, Encoding encoding, uint32_t bit_size) -{ - if (!ast) - return NULL; - - switch (encoding) - { - case eEncodingInvalid: - if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return ast->VoidPtrTy.getAsOpaquePtr(); - break; - - case eEncodingUint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ast->UnsignedCharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ast->UnsignedShortTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ast->UnsignedIntTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return ast->UnsignedLongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return ast->UnsignedLongLongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return ast->UnsignedInt128Ty.getAsOpaquePtr(); - break; - - case eEncodingSint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ast->CharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return ast->ShortTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return ast->IntTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return ast->LongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return ast->LongLongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return ast->Int128Ty.getAsOpaquePtr(); - break; - - case eEncodingIEEE754: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return ast->FloatTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return ast->DoubleTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return ast->LongDoubleTy.getAsOpaquePtr(); - break; - - case eEncodingVector: - // Sanity check that bit_size is a multiple of 8's. - if (bit_size && !(bit_size & 0x7u)) - return ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8).getAsOpaquePtr(); - break; - default: - break; - } - - return NULL; -} - -clang_type_t -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 - assert (ast != NULL); - if (ast) - { - switch (dw_ate) - { - default: - break; - - case DW_ATE_address: - if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return ast->VoidPtrTy.getAsOpaquePtr(); - break; - - case DW_ATE_boolean: - if (QualTypeMatchesBitSize (bit_size, ast, ast->BoolTy)) - return ast->BoolTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ast->UnsignedCharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ast->UnsignedShortTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return 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")) - { - clang_type_t complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2); - return ast->getComplexType (QualType::getFromOpaquePtr(complex_int_clang_type)).getAsOpaquePtr(); - } - } - break; - - case DW_ATE_complex_float: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatComplexTy)) - return ast->FloatComplexTy.getAsOpaquePtr(); - else if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleComplexTy)) - return ast->DoubleComplexTy.getAsOpaquePtr(); - else if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleComplexTy)) - return ast->LongDoubleComplexTy.getAsOpaquePtr(); - else - { - clang_type_t complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2); - return ast->getComplexType (QualType::getFromOpaquePtr(complex_float_clang_type)).getAsOpaquePtr(); - } - break; - - case DW_ATE_float: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return ast->FloatTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return ast->DoubleTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return ast->LongDoubleTy.getAsOpaquePtr(); - break; - - case DW_ATE_signed: - if (type_name) - { - if (streq(type_name, "wchar_t") && - QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy)) - return ast->WCharTy.getAsOpaquePtr(); - if (streq(type_name, "void") && - QualTypeMatchesBitSize (bit_size, ast, ast->VoidTy)) - return ast->VoidTy.getAsOpaquePtr(); - if (strstr(type_name, "long long") && - QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return ast->LongLongTy.getAsOpaquePtr(); - if (strstr(type_name, "long") && - QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return ast->LongTy.getAsOpaquePtr(); - if (strstr(type_name, "short") && - QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return ast->ShortTy.getAsOpaquePtr(); - if (strstr(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ast->CharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return ast->SignedCharTy.getAsOpaquePtr(); - } - if (strstr(type_name, "int")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return ast->IntTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return 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 ast->CharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return ast->ShortTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return ast->IntTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return ast->LongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return ast->LongLongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return 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 ast->SignedCharTy.getAsOpaquePtr(); - } - } - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return ast->CharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return 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 ast->UnsignedLongLongTy.getAsOpaquePtr(); - } - else if (strstr(type_name, "long")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return ast->UnsignedLongTy.getAsOpaquePtr(); - } - else if (strstr(type_name, "short")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ast->UnsignedShortTy.getAsOpaquePtr(); - } - else if (strstr(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ast->UnsignedCharTy.getAsOpaquePtr(); - } - else if (strstr(type_name, "int")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ast->UnsignedIntTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return 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 ast->UnsignedCharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ast->UnsignedShortTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return ast->UnsignedIntTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return ast->UnsignedLongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return ast->UnsignedLongLongTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return ast->UnsignedInt128Ty.getAsOpaquePtr(); - break; - - case DW_ATE_unsigned_char: - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return ast->UnsignedCharTy.getAsOpaquePtr(); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return ast->UnsignedShortTy.getAsOpaquePtr(); - break; - - case DW_ATE_imaginary_float: - break; - - case DW_ATE_UTF: - if (type_name) - { - if (streq(type_name, "char16_t")) - { - return ast->Char16Ty.getAsOpaquePtr(); - } - else if (streq(type_name, "char32_t")) - { - return 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 NULL; -} - -clang_type_t -ClangASTContext::GetBuiltInType_void(ASTContext *ast) -{ - return ast->VoidTy.getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetBuiltInType_bool() -{ - return getASTContext()->BoolTy.getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetBuiltInType_objc_id() -{ - return getASTContext()->getObjCIdType().getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetBuiltInType_objc_Class() -{ - return getASTContext()->getObjCClassType().getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetBuiltInType_objc_selector() -{ - return getASTContext()->getObjCSelType().getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) -{ - return ast->UnknownAnyTy.getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetCStringType (bool is_const) -{ - QualType char_type(getASTContext()->CharTy); - - if (is_const) - char_type.addConst(); - - return getASTContext()->getPointerType(char_type).getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetVoidType() -{ - return GetVoidType(getASTContext()); -} - -clang_type_t -ClangASTContext::GetVoidType(ASTContext *ast) -{ - return ast->VoidTy.getAsOpaquePtr(); -} - -clang_type_t -ClangASTContext::GetVoidPtrType (bool is_const) -{ - return GetVoidPtrType(getASTContext(), is_const); -} - -clang_type_t -ClangASTContext::GetVoidPtrType (ASTContext *ast, bool is_const) -{ - QualType void_ptr_type(ast->VoidPtrTy); - - if (is_const) - void_ptr_type.addConst(); - - return void_ptr_type.getAsOpaquePtr(); -} - -clang::DeclContext * -ClangASTContext::GetTranslationUnitDecl (clang::ASTContext *ast) -{ - return ast->getTranslationUnitDecl(); -} - -clang_type_t -ClangASTContext::CopyType (ASTContext *dst_ast, - ASTContext *src_ast, - clang_type_t clang_type) -{ - FileSystemOptions file_system_options; - FileManager file_manager (file_system_options); - ASTImporter importer(*dst_ast, file_manager, - *src_ast, file_manager, - false); - - QualType src (QualType::getFromOpaquePtr(clang_type)); - QualType dst (importer.Import(src)); - - return 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 (ASTContext *ast, - clang_type_t type1, - clang_type_t type2, - bool ignore_qualifiers) -{ - if (type1 == type2) - return true; - - QualType type1_qual = QualType::getFromOpaquePtr(type1); - QualType type2_qual = QualType::getFromOpaquePtr(type2); - - if (ignore_qualifiers) - { - type1_qual = type1_qual.getUnqualifiedType(); - type2_qual = type2_qual.getUnqualifiedType(); - } - - return ast->hasSameType (type1_qual, - type2_qual); -} - -#pragma mark CVR modifiers - -clang_type_t -ClangASTContext::AddConstModifier (clang_type_t clang_type) -{ - if (clang_type) - { - QualType result(QualType::getFromOpaquePtr(clang_type)); - result.addConst(); - return result.getAsOpaquePtr(); - } - return NULL; -} - -clang_type_t -ClangASTContext::AddRestrictModifier (clang_type_t clang_type) -{ - if (clang_type) - { - QualType result(QualType::getFromOpaquePtr(clang_type)); - result.getQualifiers().setRestrict (true); - return result.getAsOpaquePtr(); - } - return NULL; -} - -clang_type_t -ClangASTContext::AddVolatileModifier (clang_type_t clang_type) -{ - if (clang_type) - { - QualType result(QualType::getFromOpaquePtr(clang_type)); - result.getQualifiers().setVolatile (true); - return result.getAsOpaquePtr(); - } - return NULL; -} - - -clang_type_t -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... - if (m_ast_ap.get()) - return m_ast_ap->getTagDeclType(decl).getAsOpaquePtr(); - return NULL; -} - -clang_type_t -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... - if (m_ast_ap.get()) - return m_ast_ap->getObjCInterfaceType(decl).getAsOpaquePtr(); - return NULL; -} - -#pragma mark Structure, Unions, Classes - -clang_type_t -ClangASTContext::CreateRecordType (DeclContext *decl_ctx, AccessType access_type, const char *name, int kind, LanguageType language, uint64_t metadata) -{ - ASTContext *ast = getASTContext(); - assert (ast != NULL); - - if (decl_ctx == NULL) - 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. - CXXRecordDecl *decl = CXXRecordDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, - SourceLocation(), - SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : NULL); - - if (decl) - SetMetadata(ast, (uintptr_t)decl, metadata); - - if (!name) - decl->setAnonymousStructOrUnion(true); - - if (decl_ctx) - { - if (access_type != eAccessNone) - decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); - decl_ctx->addDecl (decl); - } - return ast->getTagDeclType(decl).getAsOpaquePtr(); -} - -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]; - if (template_param_infos.args[i].getAsIntegral()) - { - template_param_decls.push_back (NonTypeTemplateParmDecl::Create (*ast, - ast->getTranslationUnitDecl(), // Is this the right decl context?, SourceLocation StartLoc, - SourceLocation(), - SourceLocation(), - depth, - i, - &ast->Idents.get(name), - template_param_infos.args[i].getIntegralType(), - parameter_pack, - NULL)); - - } - else - { - template_param_decls.push_back (TemplateTypeParmDecl::Create (*ast, - ast->getTranslationUnitDecl(), // Is this the right decl context? - SourceLocation(), - SourceLocation(), - depth, - i, - &ast->Idents.get(name), - 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, - NULL); -} - - -ClassTemplateDecl * -ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *class_name, - int kind, - const TemplateParameterInfos &template_param_infos) -{ - ASTContext *ast = getASTContext(); - - ClassTemplateDecl *class_template_decl = NULL; - if (decl_ctx == NULL) - 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 (clang::DeclContext::lookup_iterator pos = result.first, end = result.second; pos != end; ++pos) - { - class_template_decl = dyn_cast<clang::ClassTemplateDecl>(*pos); - 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, - NULL); - - 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(), - NULL); - - return class_template_specialization_decl; -} - -lldb::clang_type_t -ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializationDecl *class_template_specialization_decl) -{ - if (class_template_specialization_decl) - { - ASTContext *ast = getASTContext(); - if (ast) - return ast->getTagDeclType(class_template_specialization_decl).getAsOpaquePtr(); - } - return NULL; -} - -bool -ClangASTContext::SetHasExternalStorage (clang_type_t clang_type, bool has_extern) -{ - if (clang_type == NULL) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - cxx_record_decl->setHasExternalLexicalStorage (has_extern); - cxx_record_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - break; - - case clang::Type::Enum: - { - EnumDecl *enum_decl = cast<EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - enum_decl->setHasExternalLexicalStorage (has_extern); - enum_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - class_interface_decl->setHasExternalLexicalStorage (has_extern); - class_interface_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTContext::SetHasExternalStorage (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), has_extern); - - case clang::Type::Elaborated: - return ClangASTContext::SetHasExternalStorage (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), has_extern); - - default: - break; - } - return false; -} - -static bool -IsOperator (const char *name, OverloadedOperatorKind &op_kind) -{ - if (name == NULL || name[0] == '\0') - return false; - -#define OPERATOR_PREFIX "operator" -#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1) - - const char *post_op_name = NULL; - - bool no_space = true; - - if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) - return false; - - post_op_name = name + OPERATOR_PREFIX_LENGTH; - - if (post_op_name[0] == ' ') - { - post_op_name++; - no_space = false; - } - -#undef OPERATOR_PREFIX -#undef OPERATOR_PREFIX_LENGTH - - // This is an operator, set the overloaded operator kind to invalid - // in case this is a conversion operator... - op_kind = NUM_OVERLOADED_OPERATORS; - - switch (post_op_name[0]) - { - default: - if (no_space) - return false; - break; - case 'n': - if (no_space) - return false; - if (strcmp (post_op_name, "new") == 0) - op_kind = OO_New; - else if (strcmp (post_op_name, "new[]") == 0) - op_kind = OO_Array_New; - break; - - case 'd': - if (no_space) - return false; - if (strcmp (post_op_name, "delete") == 0) - op_kind = OO_Delete; - else if (strcmp (post_op_name, "delete[]") == 0) - op_kind = OO_Array_Delete; - break; - - case '+': - if (post_op_name[1] == '\0') - op_kind = OO_Plus; - else if (post_op_name[2] == '\0') - { - if (post_op_name[1] == '=') - op_kind = OO_PlusEqual; - else if (post_op_name[1] == '+') - op_kind = OO_PlusPlus; - } - break; - - case '-': - if (post_op_name[1] == '\0') - op_kind = OO_Minus; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': op_kind = OO_MinusEqual; break; - case '-': op_kind = OO_MinusMinus; break; - case '>': op_kind = OO_Arrow; break; - } - } - else if (post_op_name[3] == '\0') - { - if (post_op_name[2] == '*') - op_kind = OO_ArrowStar; break; - } - break; - - case '*': - if (post_op_name[1] == '\0') - op_kind = OO_Star; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = OO_StarEqual; - break; - - case '/': - if (post_op_name[1] == '\0') - op_kind = OO_Slash; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = OO_SlashEqual; - break; - - case '%': - if (post_op_name[1] == '\0') - op_kind = OO_Percent; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = OO_PercentEqual; - break; - - - case '^': - if (post_op_name[1] == '\0') - op_kind = OO_Caret; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = OO_CaretEqual; - break; - - case '&': - if (post_op_name[1] == '\0') - op_kind = OO_Amp; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': op_kind = OO_AmpEqual; break; - case '&': op_kind = OO_AmpAmp; break; - } - } - break; - - case '|': - if (post_op_name[1] == '\0') - op_kind = OO_Pipe; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': op_kind = OO_PipeEqual; break; - case '|': op_kind = OO_PipePipe; break; - } - } - break; - - case '~': - if (post_op_name[1] == '\0') - op_kind = OO_Tilde; - break; - - case '!': - if (post_op_name[1] == '\0') - op_kind = OO_Exclaim; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = OO_ExclaimEqual; - break; - - case '=': - if (post_op_name[1] == '\0') - op_kind = OO_Equal; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = OO_EqualEqual; - break; - - case '<': - if (post_op_name[1] == '\0') - op_kind = OO_Less; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '<': op_kind = OO_LessLess; break; - case '=': op_kind = OO_LessEqual; break; - } - } - else if (post_op_name[3] == '\0') - { - if (post_op_name[2] == '=') - op_kind = OO_LessLessEqual; - } - break; - - case '>': - if (post_op_name[1] == '\0') - op_kind = OO_Greater; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '>': op_kind = OO_GreaterGreater; break; - case '=': op_kind = OO_GreaterEqual; break; - } - } - else if (post_op_name[1] == '>' && - post_op_name[2] == '=' && - post_op_name[3] == '\0') - { - op_kind = OO_GreaterGreaterEqual; - } - break; - - case ',': - if (post_op_name[1] == '\0') - op_kind = OO_Comma; - break; - - case '(': - if (post_op_name[1] == ')' && post_op_name[2] == '\0') - op_kind = OO_Call; - break; - - case '[': - if (post_op_name[1] == ']' && post_op_name[2] == '\0') - op_kind = OO_Subscript; - break; - } - - return true; -} - -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; - - // The parameter count doens't include "this" - 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; -} - -CXXMethodDecl * -ClangASTContext::AddMethodToCXXRecordType -( - ASTContext *ast, - clang_type_t record_opaque_type, - const char *name, - clang_type_t method_opaque_type, - lldb::AccessType access, - bool is_virtual, - bool is_static, - bool is_inline, - bool is_explicit, - bool is_attr_used, - bool is_artificial -) -{ - if (!record_opaque_type || !method_opaque_type || !name) - return NULL; - - assert(ast); - - IdentifierTable *identifier_table = &ast->Idents; - - assert(identifier_table); - - QualType record_qual_type(QualType::getFromOpaquePtr(record_opaque_type)); - - CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl(); - - if (cxx_record_decl == NULL) - return NULL; - - QualType method_qual_type (QualType::getFromOpaquePtr (method_opaque_type)); - - CXXMethodDecl *cxx_method_decl = NULL; - - DeclarationName decl_name (&identifier_table->get(name)); - - const clang::FunctionType *function_Type = dyn_cast<FunctionType>(method_qual_type.getTypePtr()); - - if (function_Type == NULL) - return NULL; - - const FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(function_Type)); - - if (!method_function_prototype) - return NULL; - - unsigned int num_params = method_function_prototype->getNumArgs(); - - CXXDestructorDecl *cxx_dtor_decl(NULL); - CXXConstructorDecl *cxx_ctor_decl(NULL); - - if (name[0] == '~') - { - cxx_dtor_decl = CXXDestructorDecl::Create (*ast, - cxx_record_decl, - SourceLocation(), - DeclarationNameInfo (ast->DeclarationNames.getCXXDestructorName (ast->getCanonicalType (record_qual_type)), SourceLocation()), - method_qual_type, - NULL, - is_inline, - is_artificial); - cxx_method_decl = cxx_dtor_decl; - } - else if (decl_name == cxx_record_decl->getDeclName()) - { - cxx_ctor_decl = CXXConstructorDecl::Create (*ast, - cxx_record_decl, - SourceLocation(), - DeclarationNameInfo (ast->DeclarationNames.getCXXConstructorName (ast->getCanonicalType (record_qual_type)), SourceLocation()), - method_qual_type, - NULL, // TypeSourceInfo * - is_explicit, - is_inline, - is_artificial, - false /*is_constexpr*/); - cxx_method_decl = cxx_ctor_decl; - } - else - { - - OverloadedOperatorKind op_kind = NUM_OVERLOADED_OPERATORS; - if (IsOperator (name, op_kind)) - { - if (op_kind != NUM_OVERLOADED_OPERATORS) - { - // Check the number of operator parameters. Sometimes we have - // seen bad DWARF that doesn't correctly describe operators and - // if we try to create a methed and add it to the class, clang - // will assert and crash, so we need to make sure things are - // acceptable. - if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount (op_kind, num_params)) - return NULL; - cxx_method_decl = CXXMethodDecl::Create (*ast, - cxx_record_decl, - SourceLocation(), - DeclarationNameInfo (ast->DeclarationNames.getCXXOperatorName (op_kind), SourceLocation()), - method_qual_type, - NULL, // TypeSourceInfo * - is_static, - SC_None, - is_inline, - false /*is_constexpr*/, - SourceLocation()); - } - else if (num_params == 0) - { - // Conversion operators don't take params... - cxx_method_decl = CXXConversionDecl::Create (*ast, - cxx_record_decl, - SourceLocation(), - DeclarationNameInfo (ast->DeclarationNames.getCXXConversionFunctionName (ast->getCanonicalType (function_Type->getResultType())), SourceLocation()), - method_qual_type, - NULL, // TypeSourceInfo * - is_inline, - is_explicit, - false /*is_constexpr*/, - SourceLocation()); - } - } - - if (cxx_method_decl == NULL) - { - cxx_method_decl = CXXMethodDecl::Create (*ast, - cxx_record_decl, - SourceLocation(), - DeclarationNameInfo (decl_name, SourceLocation()), - method_qual_type, - NULL, // TypeSourceInfo * - is_static, - SC_None, - is_inline, - false /*is_constexpr*/, - SourceLocation()); - } - } - - AccessSpecifier access_specifier = ConvertAccessTypeToAccessSpecifier (access); - - cxx_method_decl->setAccess (access_specifier); - cxx_method_decl->setVirtualAsWritten (is_virtual); - - if (is_attr_used) - cxx_method_decl->addAttr(::new (*ast) UsedAttr(SourceRange(), *ast)); - - // Populate the method decl with parameter decls - - llvm::SmallVector<ParmVarDecl *, 12> params; - - for (int param_index = 0; - param_index < num_params; - ++param_index) - { - params.push_back (ParmVarDecl::Create (*ast, - cxx_method_decl, - SourceLocation(), - SourceLocation(), - NULL, // anonymous - method_function_prototype->getArgType(param_index), - NULL, - SC_None, - SC_None, - NULL)); - } - - cxx_method_decl->setParams (ArrayRef<ParmVarDecl*>(params)); - - cxx_record_decl->addDecl (cxx_method_decl); - - // Sometimes the debug info will mention a constructor (default/copy/move), - // destructor, or assignment operator (copy/move) but there won't be any - // version of this in the code. So we check if the function was artificially - // generated and if it is trivial and this lets the compiler/backend know - // that it can inline the IR for these when it needs to and we can avoid a - // "missing function" error when running expressions. - - if (is_artificial) - { - if (cxx_ctor_decl && - ((cxx_ctor_decl->isDefaultConstructor() && cxx_record_decl->hasTrivialDefaultConstructor ()) || - (cxx_ctor_decl->isCopyConstructor() && cxx_record_decl->hasTrivialCopyConstructor ()) || - (cxx_ctor_decl->isMoveConstructor() && cxx_record_decl->hasTrivialMoveConstructor ()) )) - { - cxx_ctor_decl->setDefaulted(); - cxx_ctor_decl->setTrivial(true); - } - else if (cxx_dtor_decl) - { - if (cxx_record_decl->hasTrivialDestructor()) - { - cxx_dtor_decl->setDefaulted(); - cxx_dtor_decl->setTrivial(true); - } - } - else if ((cxx_method_decl->isCopyAssignmentOperator() && cxx_record_decl->hasTrivialCopyAssignment()) || - (cxx_method_decl->isMoveAssignmentOperator() && cxx_record_decl->hasTrivialMoveAssignment())) - { - cxx_method_decl->setDefaulted(); - cxx_method_decl->setTrivial(true); - } - } - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(cxx_method_decl); -#endif - -// printf ("decl->isPolymorphic() = %i\n", cxx_record_decl->isPolymorphic()); -// printf ("decl->isAggregate() = %i\n", cxx_record_decl->isAggregate()); -// printf ("decl->isPOD() = %i\n", cxx_record_decl->isPOD()); -// printf ("decl->isEmpty() = %i\n", cxx_record_decl->isEmpty()); -// printf ("decl->isAbstract() = %i\n", cxx_record_decl->isAbstract()); -// printf ("decl->hasTrivialConstructor() = %i\n", cxx_record_decl->hasTrivialConstructor()); -// printf ("decl->hasTrivialCopyConstructor() = %i\n", cxx_record_decl->hasTrivialCopyConstructor()); -// printf ("decl->hasTrivialCopyAssignment() = %i\n", cxx_record_decl->hasTrivialCopyAssignment()); -// printf ("decl->hasTrivialDestructor() = %i\n", cxx_record_decl->hasTrivialDestructor()); - return cxx_method_decl; -} - -clang::FieldDecl * -ClangASTContext::AddFieldToRecordType -( - ASTContext *ast, - clang_type_t record_clang_type, - const char *name, - clang_type_t field_type, - AccessType access, - uint32_t bitfield_bit_size -) -{ - if (record_clang_type == NULL || field_type == NULL) - return NULL; - - FieldDecl *field = NULL; - IdentifierTable *identifier_table = &ast->Idents; - - assert (ast != NULL); - assert (identifier_table != NULL); - - QualType record_qual_type(QualType::getFromOpaquePtr(record_clang_type)); - - const clang::Type *clang_type = record_qual_type.getTypePtr(); - if (clang_type) - { - const RecordType *record_type = dyn_cast<RecordType>(clang_type); - - if (record_type) - { - RecordDecl *record_decl = record_type->getDecl(); - - clang::Expr *bit_width = NULL; - if (bitfield_bit_size != 0) - { - APInt bitfield_bit_size_apint(ast->getTypeSize(ast->IntTy), bitfield_bit_size); - bit_width = new (*ast)IntegerLiteral (*ast, bitfield_bit_size_apint, ast->IntTy, SourceLocation()); - } - field = FieldDecl::Create (*ast, - record_decl, - SourceLocation(), - SourceLocation(), - name ? &identifier_table->get(name) : NULL, // Identifier - QualType::getFromOpaquePtr(field_type), // Field type - NULL, // TInfo * - bit_width, // BitWidth - false, // Mutable - false); // HasInit - - if (!name) - field->setImplicit(); - - field->setAccess (ConvertAccessTypeToAccessSpecifier (access)); - - if (field) - { - record_decl->addDecl(field); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(field); -#endif - } - } - else - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(clang_type); - if (objc_class_type) - { - bool is_synthesized = false; - field = ClangASTContext::AddObjCClassIVar (ast, - record_clang_type, - name, - field_type, - access, - bitfield_bit_size, - is_synthesized); - } - } - } - return field; -} - -static clang::AccessSpecifier 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; -} - -void -ClangASTContext::BuildIndirectFields (clang::ASTContext *ast, - lldb::clang_type_t record_clang_type) -{ - QualType record_qual_type(QualType::getFromOpaquePtr(record_clang_type)); - - const RecordType *record_type = record_qual_type->getAs<RecordType>(); - - if (!record_type) - return; - - RecordDecl *record_decl = record_type->getDecl(); - - if (!record_decl) - return; - - typedef llvm::SmallVector <IndirectFieldDecl *, 1> IndirectFieldVector; - - IndirectFieldVector indirect_fields; - - for (RecordDecl::field_iterator fi = record_decl->field_begin(), fe = record_decl->field_end(); - fi != fe; - ++fi) - { - if (fi->isAnonymousStructOrUnion()) - { - QualType field_qual_type = fi->getType(); - - const RecordType *field_record_type = field_qual_type->getAs<RecordType>(); - - if (!field_record_type) - continue; - - RecordDecl *field_record_decl = field_record_type->getDecl(); - - if (!field_record_decl) - continue; - - for (RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end(); - di != de; - ++di) - { - if (FieldDecl *nested_field_decl = dyn_cast<FieldDecl>(*di)) - { - NamedDecl **chain = new (*ast) NamedDecl*[2]; - chain[0] = *fi; - chain[1] = nested_field_decl; - IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*ast, - record_decl, - SourceLocation(), - nested_field_decl->getIdentifier(), - nested_field_decl->getType(), - chain, - 2); - - indirect_field->setAccess(UnifyAccessSpecifiers(fi->getAccess(), - nested_field_decl->getAccess())); - - indirect_fields.push_back(indirect_field); - } - else if (IndirectFieldDecl *nested_indirect_field_decl = dyn_cast<IndirectFieldDecl>(*di)) - { - int nested_chain_size = nested_indirect_field_decl->getChainingSize(); - NamedDecl **chain = new (*ast) NamedDecl*[nested_chain_size + 1]; - chain[0] = *fi; - - int chain_index = 1; - for (IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(), - nce = nested_indirect_field_decl->chain_end(); - nci < nce; - ++nci) - { - chain[chain_index] = *nci; - chain_index++; - } - - IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*ast, - record_decl, - SourceLocation(), - nested_indirect_field_decl->getIdentifier(), - nested_indirect_field_decl->getType(), - chain, - nested_chain_size + 1); - - indirect_field->setAccess(UnifyAccessSpecifiers(fi->getAccess(), - nested_indirect_field_decl->getAccess())); - - indirect_fields.push_back(indirect_field); - } - } - } - } - - for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end(); - ifi < ife; - ++ifi) - { - record_decl->addDecl(*ifi); - } -} - -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 -) -{ - if (ast == NULL || field == NULL) - 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) -{ - if (record_decl == NULL) - 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; -} - -void -ClangASTContext::SetDefaultAccessForRecordFields (clang_type_t clang_type, int default_accessibility, int *assigned_accessibilities, size_t num_assigned_accessibilities) -{ - if (clang_type) - { - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - - const RecordType *record_type = dyn_cast<RecordType>(qual_type.getTypePtr()); - if (record_type) - { - RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - uint32_t field_idx; - RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0; - field != field_end; - ++field, ++field_idx) - { - // If no accessibility was assigned, assign the correct one - if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none) - field->setAccess ((AccessSpecifier)default_accessibility); - } - } - } - } -} - -#pragma mark C++ Base Classes - -CXXBaseSpecifier * -ClangASTContext::CreateBaseClassSpecifier (clang_type_t base_class_type, AccessType access, bool is_virtual, bool base_of_class) -{ - if (base_class_type) - return new CXXBaseSpecifier (SourceRange(), - is_virtual, - base_of_class, - ConvertAccessTypeToAccessSpecifier (access), - getASTContext()->CreateTypeSourceInfo (QualType::getFromOpaquePtr(base_class_type)), - SourceLocation()); - return NULL; -} - -void -ClangASTContext::DeleteBaseClassSpecifiers (CXXBaseSpecifier **base_classes, unsigned num_base_classes) -{ - for (unsigned i=0; i<num_base_classes; ++i) - { - delete base_classes[i]; - base_classes[i] = NULL; - } -} - -bool -ClangASTContext::SetBaseClassesForClassType (clang_type_t class_clang_type, CXXBaseSpecifier const * const *base_classes, unsigned num_base_classes) -{ - if (class_clang_type) - { - CXXRecordDecl *cxx_record_decl = QualType::getFromOpaquePtr(class_clang_type)->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - cxx_record_decl->setBases(base_classes, num_base_classes); - return true; - } - } - return false; -} -#pragma mark Objective C Classes - -clang_type_t -ClangASTContext::CreateObjCClass -( - const char *name, - DeclContext *decl_ctx, - bool isForwardDecl, - bool isInternal, - uint64_t metadata -) -{ - ASTContext *ast = getASTContext(); - assert (ast != NULL); - assert (name && name[0]); - if (decl_ctx == NULL) - decl_ctx = ast->getTranslationUnitDecl(); - - // 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. - ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create (*ast, - decl_ctx, - SourceLocation(), - &ast->Idents.get(name), - NULL, - SourceLocation(), - /*isForwardDecl,*/ - isInternal); - - if (decl) - SetMetadata(ast, (uintptr_t)decl, metadata); - - return ast->getObjCInterfaceType(decl).getAsOpaquePtr(); -} - -bool -ClangASTContext::SetObjCSuperClass (clang_type_t class_opaque_type, clang_type_t super_opaque_type) -{ - if (class_opaque_type && super_opaque_type) - { - QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type)); - QualType super_qual_type(QualType::getFromOpaquePtr(super_opaque_type)); - const clang::Type *class_type = class_qual_type.getTypePtr(); - const clang::Type *super_type = super_qual_type.getTypePtr(); - if (class_type && super_type) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type); - const ObjCObjectType *objc_super_type = dyn_cast<ObjCObjectType>(super_type); - if (objc_class_type && objc_super_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - ObjCInterfaceDecl *super_interface_decl = objc_super_type->getInterface(); - if (class_interface_decl && super_interface_decl) - { - class_interface_decl->setSuperClass(super_interface_decl); - return true; - } - } - } - } - return false; -} - - -FieldDecl * -ClangASTContext::AddObjCClassIVar -( - ASTContext *ast, - clang_type_t class_opaque_type, - const char *name, - clang_type_t ivar_opaque_type, - AccessType access, - uint32_t bitfield_bit_size, - bool is_synthesized -) -{ - if (class_opaque_type == NULL || ivar_opaque_type == NULL) - return NULL; - - ObjCIvarDecl *field = NULL; - - IdentifierTable *identifier_table = &ast->Idents; - - assert (ast != NULL); - assert (identifier_table != NULL); - - QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type)); - - const clang::Type *class_type = class_qual_type.getTypePtr(); - if (class_type) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type); - - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::Expr *bit_width = NULL; - if (bitfield_bit_size != 0) - { - APInt bitfield_bit_size_apint(ast->getTypeSize(ast->IntTy), bitfield_bit_size); - bit_width = new (*ast)IntegerLiteral (*ast, bitfield_bit_size_apint, ast->IntTy, SourceLocation()); - } - - field = ObjCIvarDecl::Create (*ast, - class_interface_decl, - SourceLocation(), - SourceLocation(), - &identifier_table->get(name), // Identifier - QualType::getFromOpaquePtr(ivar_opaque_type), // Field type - NULL, // TypeSourceInfo * - ConvertAccessTypeToObjCIvarAccessControl (access), - bit_width, - is_synthesized); - - if (field) - { - class_interface_decl->addDecl(field); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(field); -#endif - - return field; - } - } - } - } - return NULL; -} - -bool -ClangASTContext::AddObjCClassProperty -( - ASTContext *ast, - clang_type_t class_opaque_type, - const char *property_name, - clang_type_t property_opaque_type, - ObjCIvarDecl *ivar_decl, - const char *property_setter_name, - const char *property_getter_name, - uint32_t property_attributes, - uint64_t metadata -) -{ - if (class_opaque_type == NULL || property_name == NULL || property_name[0] == '\0') - return false; - - IdentifierTable *identifier_table = &ast->Idents; - - assert (ast != NULL); - assert (identifier_table != NULL); - - QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type)); - const clang::Type *class_type = class_qual_type.getTypePtr(); - if (class_type) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type); - - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - clang_type_t property_opaque_type_to_access; - - if (property_opaque_type) - property_opaque_type_to_access = property_opaque_type; - else if (ivar_decl) - property_opaque_type_to_access = ivar_decl->getType().getAsOpaquePtr(); - - if (class_interface_decl && property_opaque_type_to_access) - { - clang::TypeSourceInfo *prop_type_source; - if (ivar_decl) - prop_type_source = ast->CreateTypeSourceInfo (ivar_decl->getType()); - else - prop_type_source = ast->CreateTypeSourceInfo (QualType::getFromOpaquePtr(property_opaque_type)); - - ObjCPropertyDecl *property_decl = ObjCPropertyDecl::Create(*ast, - class_interface_decl, - SourceLocation(), // Source Location - &identifier_table->get(property_name), - SourceLocation(), //Source Location for AT - SourceLocation(), //Source location for ( - prop_type_source - ); - - if (property_decl) - { - SetMetadata(ast, (uintptr_t)property_decl, metadata); - - class_interface_decl->addDecl (property_decl); - - Selector setter_sel, getter_sel; - - if (property_setter_name != NULL) - { - std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1); - clang::IdentifierInfo *setter_ident = &identifier_table->get(property_setter_no_colon.c_str()); - setter_sel = ast->Selectors.getSelector(1, &setter_ident); - } - else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) - { - std::string setter_sel_string("set"); - setter_sel_string.push_back(::toupper(property_name[0])); - setter_sel_string.append(&property_name[1]); - clang::IdentifierInfo *setter_ident = &identifier_table->get(setter_sel_string.c_str()); - setter_sel = ast->Selectors.getSelector(1, &setter_ident); - } - property_decl->setSetterName(setter_sel); - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter); - - if (property_getter_name != NULL) - { - clang::IdentifierInfo *getter_ident = &identifier_table->get(property_getter_name); - getter_sel = ast->Selectors.getSelector(0, &getter_ident); - } - else - { - clang::IdentifierInfo *getter_ident = &identifier_table->get(property_name); - getter_sel = ast->Selectors.getSelector(0, &getter_ident); - } - property_decl->setGetterName(getter_sel); - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_getter); - - if (ivar_decl) - property_decl->setPropertyIvarDecl (ivar_decl); - - if (property_attributes & DW_APPLE_PROPERTY_readonly) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readonly); - if (property_attributes & DW_APPLE_PROPERTY_readwrite) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readwrite); - if (property_attributes & DW_APPLE_PROPERTY_assign) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_assign); - if (property_attributes & DW_APPLE_PROPERTY_retain) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_retain); - if (property_attributes & DW_APPLE_PROPERTY_copy) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy); - if (property_attributes & DW_APPLE_PROPERTY_nonatomic) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic); - - if (!getter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(getter_sel)) - { - QualType result_type = QualType::getFromOpaquePtr(property_opaque_type_to_access); - - const bool isInstance = true; - const bool isVariadic = false; - const bool isSynthesized = false; - const bool isImplicitlyDeclared = true; - const bool isDefined = false; - const ObjCMethodDecl::ImplementationControl impControl = ObjCMethodDecl::None; - const bool HasRelatedResultType = false; - - ObjCMethodDecl *getter = ObjCMethodDecl::Create(*ast, - SourceLocation(), - SourceLocation(), - getter_sel, - result_type, - NULL, - class_interface_decl, - isInstance, - isVariadic, - isSynthesized, - isImplicitlyDeclared, - isDefined, - impControl, - HasRelatedResultType); - - if (getter) - SetMetadata(ast, (uintptr_t)getter, metadata); - - getter->setMethodParams(*ast, ArrayRef<ParmVarDecl*>(), ArrayRef<SourceLocation>()); - - class_interface_decl->addDecl(getter); - } - - if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel)) - { - QualType result_type = ast->VoidTy; - - const bool isInstance = true; - const bool isVariadic = false; - const bool isSynthesized = false; - const bool isImplicitlyDeclared = true; - const bool isDefined = false; - const ObjCMethodDecl::ImplementationControl impControl = ObjCMethodDecl::None; - const bool HasRelatedResultType = false; - - ObjCMethodDecl *setter = ObjCMethodDecl::Create(*ast, - SourceLocation(), - SourceLocation(), - setter_sel, - result_type, - NULL, - class_interface_decl, - isInstance, - isVariadic, - isSynthesized, - isImplicitlyDeclared, - isDefined, - impControl, - HasRelatedResultType); - - if (setter) - SetMetadata(ast, (uintptr_t)setter, metadata); - - llvm::SmallVector<ParmVarDecl *, 1> params; - - params.push_back (ParmVarDecl::Create (*ast, - setter, - SourceLocation(), - SourceLocation(), - NULL, // anonymous - QualType::getFromOpaquePtr(property_opaque_type_to_access), - NULL, - SC_Auto, - SC_Auto, - NULL)); - - setter->setMethodParams(*ast, ArrayRef<ParmVarDecl*>(params), ArrayRef<SourceLocation>()); - - class_interface_decl->addDecl(setter); - } - - return true; - } - } - } - } - return false; -} - -bool -ClangASTContext::ObjCTypeHasIVars (clang_type_t class_opaque_type, bool check_superclass) -{ - QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type)); - - const clang::Type *class_type = class_qual_type.getTypePtr(); - if (class_type) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type); - - if (objc_class_type) - return ObjCDeclHasIVars (objc_class_type->getInterface(), check_superclass); - } - return false; -} - -bool -ClangASTContext::ObjCDeclHasIVars (ObjCInterfaceDecl *class_interface_decl, bool check_superclass) -{ - while (class_interface_decl) - { - if (class_interface_decl->ivar_size() > 0) - return true; - - if (check_superclass) - class_interface_decl = class_interface_decl->getSuperClass(); - else - break; - } - return false; -} - -ObjCMethodDecl * -ClangASTContext::AddMethodToObjCObjectType -( - ASTContext *ast, - clang_type_t class_opaque_type, - const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]") - clang_type_t method_opaque_type, - lldb::AccessType access -) -{ - if (class_opaque_type == NULL || method_opaque_type == NULL) - return NULL; - - IdentifierTable *identifier_table = &ast->Idents; - - assert (ast != NULL); - assert (identifier_table != NULL); - - QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type)); - - const clang::Type *class_type = class_qual_type.getTypePtr(); - if (class_type == NULL) - return NULL; - - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type); - - if (objc_class_type == NULL) - return NULL; - - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl == NULL) - return NULL; - - const char *selector_start = ::strchr (name, ' '); - if (selector_start == NULL) - return NULL; - - selector_start++; - if (!(::isalpha (selector_start[0]) || selector_start[0] == '_')) - return NULL; - llvm::SmallVector<IdentifierInfo *, 12> selector_idents; - - size_t len = 0; - const char *start; - //printf ("name = '%s'\n", name); - - unsigned num_selectors_with_args = 0; - for (start = selector_start; - start && *start != '\0' && *start != ']'; - start += len) - { - len = ::strcspn(start, ":]"); - bool has_arg = (start[len] == ':'); - if (has_arg) - ++num_selectors_with_args; - selector_idents.push_back (&identifier_table->get (StringRef (start, len))); - if (has_arg) - len += 1; - } - - - if (selector_idents.size() == 0) - return 0; - - clang::Selector method_selector = ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0, - selector_idents.data()); - - QualType method_qual_type (QualType::getFromOpaquePtr (method_opaque_type)); - - // Populate the method decl with parameter decls - const clang::Type *method_type(method_qual_type.getTypePtr()); - - if (method_type == NULL) - return NULL; - - const FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(method_type)); - - if (!method_function_prototype) - return NULL; - - - bool is_variadic = false; - bool is_synthesized = false; - bool is_defined = false; - ObjCMethodDecl::ImplementationControl imp_control = ObjCMethodDecl::None; - - const unsigned num_args = method_function_prototype->getNumArgs(); - - ObjCMethodDecl *objc_method_decl = ObjCMethodDecl::Create (*ast, - SourceLocation(), // beginLoc, - SourceLocation(), // endLoc, - method_selector, - method_function_prototype->getResultType(), - NULL, // TypeSourceInfo *ResultTInfo, - GetDeclContextForType (class_opaque_type), - name[0] == '-', - is_variadic, - is_synthesized, - true, // is_implicitly_declared - is_defined, - imp_control, - false /*has_related_result_type*/); - - - if (objc_method_decl == NULL) - return NULL; - - if (num_args > 0) - { - llvm::SmallVector<ParmVarDecl *, 12> params; - - for (int param_index = 0; param_index < num_args; ++param_index) - { - params.push_back (ParmVarDecl::Create (*ast, - objc_method_decl, - SourceLocation(), - SourceLocation(), - NULL, // anonymous - method_function_prototype->getArgType(param_index), - NULL, - SC_Auto, - SC_Auto, - NULL)); - } - - objc_method_decl->setMethodParams(*ast, ArrayRef<ParmVarDecl*>(params), ArrayRef<SourceLocation>()); - } - - class_interface_decl->addDecl (objc_method_decl); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(objc_method_decl); -#endif - - return objc_method_decl; -} - -size_t -ClangASTContext::GetNumTemplateArguments (clang::ASTContext *ast, clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - const ClassTemplateSpecializationDecl *template_decl = dyn_cast<ClassTemplateSpecializationDecl>(cxx_record_decl); - if (template_decl) - return template_decl->getTemplateArgs().size(); - } - } - break; - - case clang::Type::Typedef: - return ClangASTContext::GetNumTemplateArguments (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - default: - break; - } - } - return 0; -} - -clang_type_t -ClangASTContext::GetTemplateArgument (clang::ASTContext *ast, clang_type_t clang_type, size_t arg_idx, lldb::TemplateArgumentKind &kind) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - const ClassTemplateSpecializationDecl *template_decl = dyn_cast<ClassTemplateSpecializationDecl>(cxx_record_decl); - if (template_decl && arg_idx < template_decl->getTemplateArgs().size()) - { - const TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx]; - switch (template_arg.getKind()) - { - case clang::TemplateArgument::Null: - kind = eTemplateArgumentKindNull; - return NULL; - - case clang::TemplateArgument::Type: - kind = eTemplateArgumentKindType; - return template_arg.getAsType().getAsOpaquePtr(); - - case clang::TemplateArgument::Declaration: - kind = eTemplateArgumentKindDeclaration; - return NULL; - - case clang::TemplateArgument::Integral: - kind = eTemplateArgumentKindIntegral; - return template_arg.getIntegralType().getAsOpaquePtr(); - - case clang::TemplateArgument::Template: - kind = eTemplateArgumentKindTemplate; - return NULL; - - case clang::TemplateArgument::TemplateExpansion: - kind = eTemplateArgumentKindTemplateExpansion; - return NULL; - - case clang::TemplateArgument::Expression: - kind = eTemplateArgumentKindExpression; - return NULL; - - case clang::TemplateArgument::Pack: - kind = eTemplateArgumentKindPack; - return NULL; - - default: - assert (!"Unhandled TemplateArgument::ArgKind"); - kind = eTemplateArgumentKindNull; - return NULL; - } - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTContext::GetTemplateArgument (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), arg_idx, kind); - default: - break; - } - } - kind = eTemplateArgumentKindNull; - return NULL; -} - -uint32_t -ClangASTContext::GetTypeInfo -( - clang_type_t clang_type, - clang::ASTContext *ast, - clang_type_t *pointee_or_element_clang_type -) -{ - if (clang_type == NULL) - return 0; - - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = NULL; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - if (ast && pointee_or_element_clang_type) - *pointee_or_element_clang_type = ast->ObjCBuiltinClassTy.getAsOpaquePtr(); - return eTypeIsBuiltIn | eTypeIsPointer | eTypeHasValue; - break; - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - return eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar; - default: - break; - } - return eTypeIsBuiltIn | eTypeHasValue; - - case clang::Type::BlockPointer: - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = qual_type->getPointeeType().getAsOpaquePtr(); - return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; - - case clang::Type::Complex: return eTypeIsBuiltIn | eTypeHasValue; - - case clang::Type::ConstantArray: - case clang::Type::DependentSizedArray: - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = cast<ArrayType>(qual_type.getTypePtr())->getElementType().getAsOpaquePtr(); - return eTypeHasChildren | eTypeIsArray; - - case clang::Type::DependentName: return 0; - case clang::Type::DependentSizedExtVector: return eTypeHasChildren | eTypeIsVector; - case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate; - case clang::Type::Decltype: return 0; - - case clang::Type::Enum: - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = cast<EnumType>(qual_type)->getDecl()->getIntegerType().getAsOpaquePtr(); - return eTypeIsEnumeration | eTypeHasValue; - - case clang::Type::Elaborated: - return ClangASTContext::GetTypeInfo (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - ast, - pointee_or_element_clang_type); - case clang::Type::ExtVector: return eTypeHasChildren | eTypeIsVector; - case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue; - case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue; - case clang::Type::InjectedClassName: return 0; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = cast<ReferenceType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(); - return eTypeHasChildren | eTypeIsReference | eTypeHasValue; - - case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue; - - case clang::Type::ObjCObjectPointer: - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = qual_type->getPointeeType().getAsOpaquePtr(); - return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue; - - case clang::Type::ObjCObject: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; - case clang::Type::ObjCInterface: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; - - case clang::Type::Pointer: - if (pointee_or_element_clang_type) - *pointee_or_element_clang_type = qual_type->getPointeeType().getAsOpaquePtr(); - return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; - - case clang::Type::Record: - if (qual_type->getAsCXXRecordDecl()) - return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus; - else - return eTypeHasChildren | eTypeIsStructUnion; - break; - case clang::Type::SubstTemplateTypeParm: return eTypeIsTemplate; - case clang::Type::TemplateTypeParm: return eTypeIsTemplate; - case clang::Type::TemplateSpecialization: return eTypeIsTemplate; - - case clang::Type::Typedef: - return eTypeIsTypedef | ClangASTContext::GetTypeInfo (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - ast, - pointee_or_element_clang_type); - - case clang::Type::TypeOfExpr: return 0; - case clang::Type::TypeOf: return 0; - case clang::Type::UnresolvedUsing: return 0; - case clang::Type::Vector: return eTypeHasChildren | eTypeIsVector; - default: return 0; - } - return 0; -} - - -#pragma mark Aggregate Types - -bool -ClangASTContext::IsAggregateType (clang_type_t clang_type) -{ - if (clang_type == NULL) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - case clang::Type::ConstantArray: - case clang::Type::ExtVector: - case clang::Type::Vector: - case clang::Type::Record: - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - return true; - case clang::Type::Elaborated: - return ClangASTContext::IsAggregateType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Typedef: - return ClangASTContext::IsAggregateType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - - default: - break; - } - // The clang type does have a value - return false; -} - -uint32_t -ClangASTContext::GetNumChildren (clang::ASTContext *ast, clang_type_t clang_type, bool omit_empty_base_classes) -{ - if (clang_type == NULL) - return 0; - - uint32_t num_children = 0; - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: // child is Class - case clang::BuiltinType::ObjCClass: // child is Class - num_children = 1; - break; - - default: - break; - } - break; - - case clang::Type::Complex: return 0; - - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr()); - const RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - if (omit_empty_base_classes) - { - // Check each base classes to see if it or any of its - // base classes contain any fields. This can help - // limit the noise in variable views by not having to - // show base classes that contain no members. - 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()); - - // Skip empty base classes - if (RecordHasFields(base_class_decl) == false) - continue; - - num_children++; - } - } - else - { - // Include all base classes - num_children += cxx_record_decl->getNumBases(); - } - - } - RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) - ++num_children; - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, qual_type)) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - - ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (omit_empty_base_classes) - { - if (ClangASTContext::ObjCDeclHasIVars (superclass_interface_decl, true)) - ++num_children; - } - else - ++num_children; - } - - num_children += class_interface_decl->ivar_size(); - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - const ObjCObjectPointerType *pointer_type = cast<ObjCObjectPointerType>(qual_type.getTypePtr()); - QualType pointee_type = pointer_type->getPointeeType(); - uint32_t num_pointee_children = ClangASTContext::GetNumChildren (ast, - pointee_type.getAsOpaquePtr(), - omit_empty_base_classes); - // If this type points to a simple type, then it has 1 child - if (num_pointee_children == 0) - num_children = 1; - else - num_children = num_pointee_children; - } - break; - - case clang::Type::ConstantArray: - num_children = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue(); - break; - - case clang::Type::Pointer: - { - const PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr()); - QualType pointee_type (pointer_type->getPointeeType()); - uint32_t num_pointee_children = ClangASTContext::GetNumChildren (ast, - pointee_type.getAsOpaquePtr(), - omit_empty_base_classes); - if (num_pointee_children == 0) - { - // We have a pointer to a pointee type that claims it has no children. - // We will want to look at - num_children = ClangASTContext::GetNumPointeeChildren (pointee_type.getAsOpaquePtr()); - } - else - num_children = num_pointee_children; - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr()); - QualType pointee_type = reference_type->getPointeeType(); - uint32_t num_pointee_children = ClangASTContext::GetNumChildren (ast, - pointee_type.getAsOpaquePtr(), - omit_empty_base_classes); - // If this type points to a simple type, then it has 1 child - if (num_pointee_children == 0) - num_children = 1; - else - num_children = num_pointee_children; - } - break; - - - case clang::Type::Typedef: - num_children = ClangASTContext::GetNumChildren (ast, - cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - omit_empty_base_classes); - break; - - case clang::Type::Elaborated: - num_children = ClangASTContext::GetNumChildren (ast, - cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - omit_empty_base_classes); - break; - - default: - break; - } - return num_children; -} - -uint32_t -ClangASTContext::GetNumDirectBaseClasses (clang::ASTContext *ast, clang_type_t clang_type) -{ - if (clang_type == NULL) - return 0; - - uint32_t count = 0; - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumBases(); - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, qual_type)) - { - const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl && class_interface_decl->getSuperClass()) - count = 1; - } - } - break; - - - case clang::Type::Typedef: - count = ClangASTContext::GetNumDirectBaseClasses (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = ClangASTContext::GetNumDirectBaseClasses (ast, cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - default: - break; - } - return count; -} - -uint32_t -ClangASTContext::GetNumVirtualBaseClasses (clang::ASTContext *ast, - clang_type_t clang_type) -{ - if (clang_type == NULL) - return 0; - - uint32_t count = 0; - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumVBases(); - } - break; - - case clang::Type::Typedef: - count = ClangASTContext::GetNumVirtualBaseClasses (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = ClangASTContext::GetNumVirtualBaseClasses (ast, cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - default: - break; - } - return count; -} - -uint32_t -ClangASTContext::GetNumFields (clang::ASTContext *ast, clang_type_t clang_type) -{ - if (clang_type == NULL) - return 0; - - uint32_t count = 0; - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const RecordType *record_type = dyn_cast<RecordType>(qual_type.getTypePtr()); - if (record_type) - { - RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - uint32_t field_idx = 0; - RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) - ++field_idx; - count = field_idx; - } - } - } - break; - - case clang::Type::Typedef: - count = ClangASTContext::GetNumFields (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = ClangASTContext::GetNumFields (ast, cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, qual_type)) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr()); - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - count = class_interface_decl->ivar_size(); - } - } - break; - - default: - break; - } - return count; -} - -clang_type_t -ClangASTContext::GetDirectBaseClassAtIndex (clang::ASTContext *ast, - clang_type_t clang_type, - uint32_t idx, - uint32_t *bit_offset_ptr) -{ - if (clang_type == NULL) - return 0; - - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - uint32_t curr_idx = 0; - 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, ++curr_idx) - { - if (curr_idx == idx) - { - if (bit_offset_ptr) - { - const ASTRecordLayout &record_layout = ast->getASTRecordLayout(cxx_record_decl); - const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); -// if (base_class->isVirtual()) -// *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; -// else - *bit_offset_ptr = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - } - return base_class->getType().getAsOpaquePtr(); - } - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (idx == 0 && GetCompleteQualType (ast, qual_type)) - { - const ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (bit_offset_ptr) - *bit_offset_ptr = 0; - return ast->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(); - } - } - } - } - break; - - - case clang::Type::Typedef: - return ClangASTContext::GetDirectBaseClassAtIndex (ast, - cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - idx, - bit_offset_ptr); - - case clang::Type::Elaborated: - return ClangASTContext::GetDirectBaseClassAtIndex (ast, - cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - idx, - bit_offset_ptr); - - default: - break; - } - return NULL; -} - -clang_type_t -ClangASTContext::GetVirtualBaseClassAtIndex (clang::ASTContext *ast, - clang_type_t clang_type, - uint32_t idx, - uint32_t *bit_offset_ptr) -{ - if (clang_type == NULL) - return 0; - - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - uint32_t curr_idx = 0; - CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end(); - base_class != base_class_end; - ++base_class, ++curr_idx) - { - if (curr_idx == idx) - { - if (bit_offset_ptr) - { - const ASTRecordLayout &record_layout = ast->getASTRecordLayout(cxx_record_decl); - const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); - *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - - } - return base_class->getType().getAsOpaquePtr(); - } - } - } - } - break; - - case clang::Type::Typedef: - return ClangASTContext::GetVirtualBaseClassAtIndex (ast, - cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - idx, - bit_offset_ptr); - - case clang::Type::Elaborated: - return ClangASTContext::GetVirtualBaseClassAtIndex (ast, - cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - idx, - bit_offset_ptr); - - default: - break; - } - return NULL; -} - -clang_type_t -ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, - clang_type_t clang_type, - uint32_t idx, - std::string& name, - uint32_t *bit_offset_ptr) -{ - if (clang_type == NULL) - return 0; - - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr()); - const RecordDecl *record_decl = record_type->getDecl(); - uint32_t field_idx = 0; - RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx) - { - if (idx == field_idx) - { - // Print the member type if requested - // Print the member name and equal sign - name.assign(field->getNameAsString()); - - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - if (bit_offset_ptr) - { - const ASTRecordLayout &record_layout = ast->getASTRecordLayout(record_decl); - *bit_offset_ptr = record_layout.getFieldOffset (field_idx); - } - - return field->getType().getAsOpaquePtr(); - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, qual_type)) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - if (idx < (class_interface_decl->ivar_size())) - { - ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - uint32_t ivar_idx = 0; - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx) - { - if (ivar_idx == idx) - { - const ObjCIvarDecl* ivar_decl = *ivar_pos; - - QualType ivar_qual_type(ivar_decl->getType()); - - name.assign(ivar_decl->getNameAsString()); - - if (bit_offset_ptr) - { - const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); - *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); - } - - return ivar_qual_type.getAsOpaquePtr(); - } - } - } - } - } - } - break; - - - case clang::Type::Typedef: - return ClangASTContext::GetFieldAtIndex (ast, - cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - idx, - name, - bit_offset_ptr); - - case clang::Type::Elaborated: - return ClangASTContext::GetFieldAtIndex (ast, - cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - idx, - name, - bit_offset_ptr); - - default: - break; - } - return NULL; -} - - -// If a pointer to a pointee type (the clang_type arg) says that it has no -// children, then we either need to trust it, or override it and return a -// different result. For example, an "int *" has one child that is an integer, -// but a function pointer doesn't have any children. Likewise if a Record type -// claims it has no children, then there really is nothing to show. -uint32_t -ClangASTContext::GetNumPointeeChildren (clang_type_t clang_type) -{ - if (clang_type == NULL) - return 0; - - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - case clang::BuiltinType::NullPtr: - return 0; - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::Half: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::PseudoObject: - return 1; - } - break; - - case clang::Type::Complex: return 1; - case clang::Type::Pointer: return 1; - case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them - case clang::Type::LValueReference: return 1; - case clang::Type::RValueReference: return 1; - case clang::Type::MemberPointer: return 0; - case clang::Type::ConstantArray: return 0; - case clang::Type::IncompleteArray: return 0; - case clang::Type::VariableArray: return 0; - case clang::Type::DependentSizedArray: return 0; - case clang::Type::DependentSizedExtVector: return 0; - case clang::Type::Vector: return 0; - case clang::Type::ExtVector: return 0; - case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children... - case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children... - case clang::Type::UnresolvedUsing: return 0; - case clang::Type::Paren: return 0; - case clang::Type::Typedef: return ClangASTContext::GetNumPointeeChildren (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Elaborated: return ClangASTContext::GetNumPointeeChildren (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::TypeOfExpr: return 0; - case clang::Type::TypeOf: return 0; - case clang::Type::Decltype: return 0; - case clang::Type::Record: return 0; - case clang::Type::Enum: return 1; - case clang::Type::TemplateTypeParm: return 1; - case clang::Type::SubstTemplateTypeParm: return 1; - case clang::Type::TemplateSpecialization: return 1; - case clang::Type::InjectedClassName: return 0; - case clang::Type::DependentName: return 1; - case clang::Type::DependentTemplateSpecialization: return 1; - case clang::Type::ObjCObject: return 0; - case clang::Type::ObjCInterface: return 0; - case clang::Type::ObjCObjectPointer: return 1; - default: - break; - } - return 0; -} - -clang_type_t -ClangASTContext::GetChildClangTypeAtIndex -( - ExecutionContext *exe_ctx, - const char *parent_name, - clang_type_t parent_clang_type, - uint32_t idx, - bool transparent_pointers, - bool omit_empty_base_classes, - bool ignore_array_bounds, - std::string& child_name, - uint32_t &child_byte_size, - int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, - uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, - bool &child_is_deref_of_parent -) -{ - if (parent_clang_type) - - return GetChildClangTypeAtIndex (exe_ctx, - getASTContext(), - parent_name, - parent_clang_type, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - return NULL; -} - -clang_type_t -ClangASTContext::GetChildClangTypeAtIndex -( - ExecutionContext *exe_ctx, - ASTContext *ast, - const char *parent_name, - clang_type_t parent_clang_type, - uint32_t idx, - bool transparent_pointers, - bool omit_empty_base_classes, - bool ignore_array_bounds, - std::string& child_name, - uint32_t &child_byte_size, - int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, - uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, - bool &child_is_deref_of_parent -) -{ - if (parent_clang_type == NULL) - return NULL; - - if (idx < ClangASTContext::GetNumChildren (ast, parent_clang_type, omit_empty_base_classes)) - { - uint32_t bit_offset; - child_bitfield_bit_size = 0; - child_bitfield_bit_offset = 0; - child_is_base_class = false; - QualType parent_qual_type(QualType::getFromOpaquePtr(parent_clang_type)); - const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass(); - switch (parent_type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(parent_qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - child_name = "isa"; - child_byte_size = ast->getTypeSize(ast->ObjCBuiltinClassTy) / CHAR_BIT; - return ast->ObjCBuiltinClassTy.getAsOpaquePtr(); - - default: - break; - } - break; - - case clang::Type::Record: - if (GetCompleteQualType (ast, parent_qual_type)) - { - const RecordType *record_type = cast<RecordType>(parent_qual_type.getTypePtr()); - const RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const ASTRecordLayout &record_layout = ast->getASTRecordLayout(record_decl); - uint32_t child_idx = 0; - - const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - // We might have base classes to print out first - 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 = NULL; - - // Skip empty base classes - if (omit_empty_base_classes) - { - base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); - if (RecordHasFields(base_class_decl) == false) - continue; - } - - if (idx == child_idx) - { - if (base_class_decl == NULL) - base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); - - - if (base_class->isVirtual()) - bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - else - bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - - // Base classes should be a multiple of 8 bits in size - child_byte_offset = bit_offset/8; - - child_name = ClangASTType::GetTypeNameForQualType(ast, base_class->getType()); - - uint64_t clang_type_info_bit_size = ast->getTypeSize(base_class->getType()); - - // Base classes bit sizes should be a multiple of 8 bits in size - assert (clang_type_info_bit_size % 8 == 0); - child_byte_size = clang_type_info_bit_size / 8; - child_is_base_class = true; - return base_class->getType().getAsOpaquePtr(); - } - // We don't increment the child index in the for loop since we might - // be skipping empty base classes - ++child_idx; - } - } - // Make sure index is in range... - uint32_t field_idx = 0; - RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) - { - if (idx == child_idx) - { - // Print the member type if requested - // Print the member name and equal sign - child_name.assign(field->getNameAsString().c_str()); - - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(field->getType()); - assert(field_idx < record_layout.getFieldCount()); - - child_byte_size = field_type_info.first / 8; - - // Figure out the field offset within the current struct/union/class type - bit_offset = record_layout.getFieldOffset (field_idx); - child_byte_offset = bit_offset / 8; - if (ClangASTContext::FieldIsBitfield (ast, *field, child_bitfield_bit_size)) - child_bitfield_bit_offset = bit_offset % 8; - - return field->getType().getAsOpaquePtr(); - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, parent_qual_type)) - { - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(parent_qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - - const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); - ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (omit_empty_base_classes) - { - if (ClangASTContext::GetNumChildren(ast, ast->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(), omit_empty_base_classes) > 0) - { - if (idx == 0) - { - QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl)); - - - child_name.assign(superclass_interface_decl->getNameAsString().c_str()); - - std::pair<uint64_t, unsigned> ivar_type_info = ast->getTypeInfo(ivar_qual_type.getTypePtr()); - - child_byte_size = ivar_type_info.first / 8; - child_byte_offset = 0; - child_is_base_class = true; - - return ivar_qual_type.getAsOpaquePtr(); - } - - ++child_idx; - } - } - else - ++child_idx; - } - - const uint32_t superclass_idx = child_idx; - - if (idx < (child_idx + class_interface_decl->ivar_size())) - { - ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos) - { - if (child_idx == idx) - { - ObjCIvarDecl* ivar_decl = *ivar_pos; - - QualType ivar_qual_type(ivar_decl->getType()); - - child_name.assign(ivar_decl->getNameAsString().c_str()); - - std::pair<uint64_t, unsigned> ivar_type_info = ast->getTypeInfo(ivar_qual_type.getTypePtr()); - - child_byte_size = ivar_type_info.first / 8; - - // Figure out the field offset within the current struct/union/class type - // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since - // that doesn't account for the space taken up by unbacked properties, or from - // the changing size of base classes that are newer than this class. - // So if we have a process around that we can ask about this object, do so. - child_byte_offset = LLDB_INVALID_IVAR_OFFSET; - Process *process = NULL; - if (exe_ctx) - process = exe_ctx->GetProcessPtr(); - if (process) - { - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); - if (objc_runtime != NULL) - { - ClangASTType parent_ast_type (ast, parent_qual_type.getAsOpaquePtr()); - child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str()); - } - } - - // Setting this to UINT32_MAX to make sure we don't compute it twice... - bit_offset = UINT32_MAX; - - if (child_byte_offset == LLDB_INVALID_IVAR_OFFSET) - { - bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); - child_byte_offset = bit_offset / 8; - } - - // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset - // of a bitfield within its containing object. So regardless of where we get the byte - // offset from, we still need to get the bit offset for bitfields from the layout. - - if (ClangASTContext::FieldIsBitfield (ast, ivar_decl, child_bitfield_bit_size)) - { - if (bit_offset == UINT32_MAX) - bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); - - child_bitfield_bit_offset = bit_offset % 8; - } - return ivar_qual_type.getAsOpaquePtr(); - } - ++child_idx; - } - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - const ObjCObjectPointerType *pointer_type = cast<ObjCObjectPointerType>(parent_qual_type.getTypePtr()); - QualType pointee_type = pointer_type->getPointeeType(); - - if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return GetChildClangTypeAtIndex (exe_ctx, - ast, - parent_name, - pointer_type->getPointeeType().getAsOpaquePtr(), - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent); - } - else - { - child_is_deref_of_parent = true; - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0 && GetCompleteQualType(ast, pointee_type)) - { - std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); - assert(clang_type_info.first % 8 == 0); - child_byte_size = clang_type_info.first / 8; - child_byte_offset = 0; - return pointee_type.getAsOpaquePtr(); - } - } - } - break; - - case clang::Type::ConstantArray: - { - const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr()); - const uint64_t element_count = array->getSize().getLimitedValue(); - - if (ignore_array_bounds || idx < element_count) - { - if (GetCompleteQualType (ast, array->getElementType())) - { - std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType()); - - char element_name[64]; - ::snprintf (element_name, sizeof (element_name), "[%u]", idx); - - child_name.assign(element_name); - assert(field_type_info.first % 8 == 0); - child_byte_size = field_type_info.first / 8; - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return array->getElementType().getAsOpaquePtr(); - } - } - } - break; - - case clang::Type::Pointer: - { - const PointerType *pointer_type = cast<PointerType>(parent_qual_type.getTypePtr()); - QualType pointee_type = pointer_type->getPointeeType(); - - // Don't dereference "void *" pointers - if (pointee_type->isVoidType()) - return NULL; - - if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return GetChildClangTypeAtIndex (exe_ctx, - ast, - parent_name, - pointer_type->getPointeeType().getAsOpaquePtr(), - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent); - } - else - { - child_is_deref_of_parent = true; - - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0) - { - std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); - assert(clang_type_info.first % 8 == 0); - child_byte_size = clang_type_info.first / 8; - child_byte_offset = 0; - return pointee_type.getAsOpaquePtr(); - } - } - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const ReferenceType *reference_type = cast<ReferenceType>(parent_qual_type.getTypePtr()); - QualType pointee_type(reference_type->getPointeeType()); - clang_type_t pointee_clang_type = pointee_type.getAsOpaquePtr(); - if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_clang_type)) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return GetChildClangTypeAtIndex (exe_ctx, - ast, - parent_name, - pointee_clang_type, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent); - } - else - { - if (parent_name) - { - child_name.assign(1, '&'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0) - { - std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); - assert(clang_type_info.first % 8 == 0); - child_byte_size = clang_type_info.first / 8; - child_byte_offset = 0; - return pointee_type.getAsOpaquePtr(); - } - } - } - break; - - case clang::Type::Typedef: - return GetChildClangTypeAtIndex (exe_ctx, - ast, - parent_name, - cast<TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - break; - - case clang::Type::Elaborated: - return GetChildClangTypeAtIndex (exe_ctx, - ast, - parent_name, - cast<ElaboratedType>(parent_qual_type)->getNamedType().getAsOpaquePtr(), - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - - default: - break; - } - } - return NULL; -} - -static inline bool -BaseSpecifierIsEmpty (const CXXBaseSpecifier *b) -{ - return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false; -} - -static uint32_t -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; -} - - -static uint32_t -GetIndexForRecordBase -( - const RecordDecl *record_decl, - const CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes -) -{ - uint32_t child_idx = 0; - - const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); - -// const char *super_name = record_decl->getNameAsCString(); -// const char *base_name = base_spec->getType()->getAs<RecordType>()->getDecl()->getNameAsCString(); -// printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name); -// - 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) - { - if (omit_empty_base_classes) - { - if (BaseSpecifierIsEmpty (base_class)) - continue; - } - -// printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name, -// child_idx, -// base_class->getType()->getAs<RecordType>()->getDecl()->getNameAsCString()); -// -// - if (base_class == base_spec) - return child_idx; - ++child_idx; - } - } - - return UINT32_MAX; -} - - -static uint32_t -GetIndexForRecordChild -( - const RecordDecl *record_decl, - NamedDecl *canonical_decl, - bool omit_empty_base_classes -) -{ - uint32_t child_idx = GetNumBaseClasses (dyn_cast<CXXRecordDecl>(record_decl), omit_empty_base_classes); - -// const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); -// -//// printf ("GetIndexForRecordChild (%s, %s)\n", record_decl->getNameAsCString(), canonical_decl->getNameAsCString()); -// 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) -// { -// if (omit_empty_base_classes) -// { -// if (BaseSpecifierIsEmpty (base_class)) -// continue; -// } -// -//// printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", -//// record_decl->getNameAsCString(), -//// canonical_decl->getNameAsCString(), -//// child_idx, -//// base_class->getType()->getAs<RecordType>()->getDecl()->getNameAsCString()); -// -// -// CXXRecordDecl *curr_base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); -// if (curr_base_class_decl == canonical_decl) -// { -// return child_idx; -// } -// ++child_idx; -// } -// } -// -// const uint32_t num_bases = child_idx; - RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { -// printf ("GetIndexForRecordChild (%s, %s) field[%u] = %s\n", -// record_decl->getNameAsCString(), -// canonical_decl->getNameAsCString(), -// child_idx - num_bases, -// field->getNameAsCString()); - - if (field->getCanonicalDecl() == canonical_decl) - return child_idx; - } - - return UINT32_MAX; -} - -// Look for a child member (doesn't include base classes, but it does include -// their members) in the type hierarchy. Returns an index path into "clang_type" -// on how to reach the appropriate member. -// -// class A -// { -// public: -// int m_a; -// int m_b; -// }; -// -// class B -// { -// }; -// -// class C : -// public B, -// public A -// { -// }; -// -// If we have a clang type that describes "class C", and we wanted to looked -// "m_b" in it: -// -// With omit_empty_base_classes == false we would get an integer array back with: -// { 1, 1 } -// The first index 1 is the child index for "class A" within class C -// The second index 1 is the child index for "m_b" within class A -// -// With omit_empty_base_classes == true we would get an integer array back with: -// { 0, 1 } -// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count) -// The second index 1 is the child index for "m_b" within class A - -size_t -ClangASTContext::GetIndexOfChildMemberWithName -( - ASTContext *ast, - clang_type_t clang_type, - const char *name, - bool omit_empty_base_classes, - std::vector<uint32_t>& child_indexes -) -{ - if (clang_type && name && name[0]) - { - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr()); - const RecordDecl *record_decl = record_type->getDecl(); - - assert(record_decl); - uint32_t child_idx = 0; - - const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); - - // Try and find a field that matches NAME - RecordDecl::field_iterator field, field_end; - StringRef name_sref(name); - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - if (field->getName().equals (name_sref)) - { - // We have to add on the number of base classes to this index! - child_indexes.push_back (child_idx + GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes)); - return child_indexes.size(); - } - } - - if (cxx_record_decl) - { - const RecordDecl *parent_record_decl = cxx_record_decl; - - //printf ("parent = %s\n", parent_record_decl->getNameAsCString()); - - //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl(); - // Didn't find things easily, lets let clang do its thang... - IdentifierInfo & ident_ref = ast->Idents.get(name_sref); - DeclarationName decl_name(&ident_ref); - - CXXBasePaths paths; - if (cxx_record_decl->lookupInBases(CXXRecordDecl::FindOrdinaryMember, - decl_name.getAsOpaquePtr(), - paths)) - { - CXXBasePaths::const_paths_iterator path, path_end = paths.end(); - for (path = paths.begin(); path != path_end; ++path) - { - const size_t num_path_elements = path->size(); - for (size_t e=0; e<num_path_elements; ++e) - { - CXXBasePathElement elem = (*path)[e]; - - child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes); - if (child_idx == UINT32_MAX) - { - child_indexes.clear(); - return 0; - } - else - { - child_indexes.push_back (child_idx); - parent_record_decl = cast<RecordDecl>(elem.Base->getType()->getAs<RecordType>()->getDecl()); - } - } - DeclContext::lookup_iterator named_decl_pos; - for (named_decl_pos = path->Decls.first; - named_decl_pos != path->Decls.second && parent_record_decl; - ++named_decl_pos) - { - //printf ("path[%zu] = %s\n", child_indexes.size(), (*named_decl_pos)->getNameAsCString()); - - child_idx = GetIndexForRecordChild (parent_record_decl, *named_decl_pos, omit_empty_base_classes); - if (child_idx == UINT32_MAX) - { - child_indexes.clear(); - return 0; - } - else - { - child_indexes.push_back (child_idx); - } - } - } - return child_indexes.size(); - } - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, qual_type)) - { - StringRef name_sref(name); - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) - { - const ObjCIvarDecl* ivar_decl = *ivar_pos; - - if (ivar_decl->getName().equals (name_sref)) - { - if ((!omit_empty_base_classes && superclass_interface_decl) || - ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) - ++child_idx; - - child_indexes.push_back (child_idx); - return child_indexes.size(); - } - } - - if (superclass_interface_decl) - { - // The super class index is always zero for ObjC classes, - // so we push it onto the child indexes in case we find - // an ivar in our superclass... - child_indexes.push_back (0); - - if (GetIndexOfChildMemberWithName (ast, - ast->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(), - name, - omit_empty_base_classes, - child_indexes)) - { - // We did find an ivar in a superclass so just - // return the results! - return child_indexes.size(); - } - - // We didn't find an ivar matching "name" in our - // superclass, pop the superclass zero index that - // we pushed on above. - child_indexes.pop_back(); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - return GetIndexOfChildMemberWithName (ast, - cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(), - name, - omit_empty_base_classes, - child_indexes); - } - break; - - - case clang::Type::ConstantArray: - { -// const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr()); -// const uint64_t element_count = array->getSize().getLimitedValue(); -// -// if (idx < element_count) -// { -// std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType()); -// -// char element_name[32]; -// ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); -// -// child_name.assign(element_name); -// assert(field_type_info.first % 8 == 0); -// child_byte_size = field_type_info.first / 8; -// child_byte_offset = idx * child_byte_size; -// return array->getElementType().getAsOpaquePtr(); -// } - } - break; - -// case clang::Type::MemberPointerType: -// { -// MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr()); -// QualType pointee_type = mem_ptr_type->getPointeeType(); -// -// if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) -// { -// return GetIndexOfChildWithName (ast, -// mem_ptr_type->getPointeeType().getAsOpaquePtr(), -// name); -// } -// } -// break; -// - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr()); - QualType pointee_type = reference_type->getPointeeType(); - - if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - { - return GetIndexOfChildMemberWithName (ast, - reference_type->getPointeeType().getAsOpaquePtr(), - name, - omit_empty_base_classes, - child_indexes); - } - } - break; - - case clang::Type::Pointer: - { - const PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr()); - QualType pointee_type = pointer_type->getPointeeType(); - - if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - { - return GetIndexOfChildMemberWithName (ast, - pointer_type->getPointeeType().getAsOpaquePtr(), - name, - omit_empty_base_classes, - child_indexes); - } - else - { -// if (parent_name) -// { -// child_name.assign(1, '*'); -// child_name += parent_name; -// } -// -// // We have a pointer to an simple type -// if (idx == 0) -// { -// std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); -// assert(clang_type_info.first % 8 == 0); -// child_byte_size = clang_type_info.first / 8; -// child_byte_offset = 0; -// return pointee_type.getAsOpaquePtr(); -// } - } - } - break; - - case clang::Type::Typedef: - return GetIndexOfChildMemberWithName (ast, - cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - name, - omit_empty_base_classes, - child_indexes); - - default: - break; - } - } - return 0; -} - - -// Get the index of the child of "clang_type" whose name matches. This function -// doesn't descend into the children, but only looks one level deep and name -// matches can include base class names. - -uint32_t -ClangASTContext::GetIndexOfChildWithName -( - ASTContext *ast, - clang_type_t clang_type, - const char *name, - bool omit_empty_base_classes -) -{ - if (clang_type && name && name[0]) - { - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteQualType (ast, qual_type)) - { - const RecordType *record_type = cast<RecordType>(qual_type.getTypePtr()); - const RecordDecl *record_decl = record_type->getDecl(); - - assert(record_decl); - uint32_t child_idx = 0; - - 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) - { - // Skip empty base classes - CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); - if (omit_empty_base_classes && RecordHasFields(base_class_decl) == false) - continue; - - std::string base_class_type_name (ClangASTType::GetTypeNameForQualType(ast, base_class->getType())); - if (base_class_type_name.compare (name) == 0) - return child_idx; - ++child_idx; - } - } - - // Try and find a field that matches NAME - RecordDecl::field_iterator field, field_end; - StringRef name_sref(name); - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - if (field->getName().equals (name_sref)) - return child_idx; - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (ast, qual_type)) - { - StringRef name_sref(name); - const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos) - { - const ObjCIvarDecl* ivar_decl = *ivar_pos; - - if (ivar_decl->getName().equals (name_sref)) - { - if ((!omit_empty_base_classes && superclass_interface_decl) || - ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) - ++child_idx; - - return child_idx; - } - } - - if (superclass_interface_decl) - { - if (superclass_interface_decl->getName().equals (name_sref)) - return 0; - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - return GetIndexOfChildWithName (ast, - cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(), - name, - omit_empty_base_classes); - } - break; - - case clang::Type::ConstantArray: - { -// const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr()); -// const uint64_t element_count = array->getSize().getLimitedValue(); -// -// if (idx < element_count) -// { -// std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType()); -// -// char element_name[32]; -// ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); -// -// child_name.assign(element_name); -// assert(field_type_info.first % 8 == 0); -// child_byte_size = field_type_info.first / 8; -// child_byte_offset = idx * child_byte_size; -// return array->getElementType().getAsOpaquePtr(); -// } - } - break; - -// case clang::Type::MemberPointerType: -// { -// MemberPointerType *mem_ptr_type = cast<MemberPointerType>(qual_type.getTypePtr()); -// QualType pointee_type = mem_ptr_type->getPointeeType(); -// -// if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) -// { -// return GetIndexOfChildWithName (ast, -// mem_ptr_type->getPointeeType().getAsOpaquePtr(), -// name); -// } -// } -// break; -// - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr()); - QualType pointee_type = reference_type->getPointeeType(); - - if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - { - return GetIndexOfChildWithName (ast, - reference_type->getPointeeType().getAsOpaquePtr(), - name, - omit_empty_base_classes); - } - } - break; - - case clang::Type::Pointer: - { - const PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr()); - QualType pointee_type = pointer_type->getPointeeType(); - - if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - { - return GetIndexOfChildWithName (ast, - pointer_type->getPointeeType().getAsOpaquePtr(), - name, - omit_empty_base_classes); - } - else - { -// if (parent_name) -// { -// child_name.assign(1, '*'); -// child_name += parent_name; -// } -// -// // We have a pointer to an simple type -// if (idx == 0) -// { -// std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); -// assert(clang_type_info.first % 8 == 0); -// child_byte_size = clang_type_info.first / 8; -// child_byte_offset = 0; -// return pointee_type.getAsOpaquePtr(); -// } - } - } - break; - - case clang::Type::Typedef: - return GetIndexOfChildWithName (ast, - cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - name, - omit_empty_base_classes); - - default: - break; - } - } - return UINT32_MAX; -} - -#pragma mark TagType - -bool -ClangASTContext::SetTagTypeKind (clang_type_t tag_clang_type, int kind) -{ - if (tag_clang_type) - { - QualType tag_qual_type(QualType::getFromOpaquePtr(tag_clang_type)); - const clang::Type *clang_type = tag_qual_type.getTypePtr(); - if (clang_type) - { - const TagType *tag_type = dyn_cast<TagType>(clang_type); - if (tag_type) - { - TagDecl *tag_decl = dyn_cast<TagDecl>(tag_type->getDecl()); - if (tag_decl) - { - tag_decl->setTagKind ((TagDecl::TagKind)kind); - return true; - } - } - } - } - return false; -} - - -#pragma mark DeclContext Functions - -DeclContext * -ClangASTContext::GetDeclContextForType (clang_type_t clang_type) -{ - if (clang_type == NULL) - return NULL; - - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::UnaryTransform: break; - case clang::Type::FunctionNoProto: break; - case clang::Type::FunctionProto: break; - case clang::Type::IncompleteArray: break; - case clang::Type::VariableArray: break; - case clang::Type::ConstantArray: break; - case clang::Type::DependentSizedArray: break; - case clang::Type::ExtVector: break; - case clang::Type::DependentSizedExtVector: break; - case clang::Type::Vector: break; - case clang::Type::Builtin: break; - case clang::Type::BlockPointer: break; - case clang::Type::Pointer: break; - case clang::Type::LValueReference: break; - case clang::Type::RValueReference: break; - case clang::Type::MemberPointer: break; - case clang::Type::Complex: break; - case clang::Type::ObjCObject: break; - case clang::Type::ObjCInterface: return cast<ObjCObjectType>(qual_type.getTypePtr())->getInterface(); - case clang::Type::ObjCObjectPointer: return ClangASTContext::GetDeclContextForType (cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr()); - case clang::Type::Record: return cast<RecordType>(qual_type)->getDecl(); - case clang::Type::Enum: return cast<EnumType>(qual_type)->getDecl(); - case clang::Type::Typedef: return ClangASTContext::GetDeclContextForType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Elaborated: return ClangASTContext::GetDeclContextForType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::TypeOfExpr: break; - case clang::Type::TypeOf: break; - case clang::Type::Decltype: break; - //case clang::Type::QualifiedName: break; - case clang::Type::TemplateSpecialization: break; - case clang::Type::DependentTemplateSpecialization: break; - case clang::Type::TemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParmPack:break; - case clang::Type::PackExpansion: break; - case clang::Type::UnresolvedUsing: break; - case clang::Type::Paren: break; - case clang::Type::Attributed: break; - case clang::Type::Auto: break; - case clang::Type::InjectedClassName: break; - case clang::Type::DependentName: break; - case clang::Type::Atomic: break; - } - // No DeclContext in this type... - return NULL; -} - -#pragma mark Namespace Declarations - -NamespaceDecl * -ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx) -{ - NamespaceDecl *namespace_decl = NULL; - ASTContext *ast = getASTContext(); - TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl (); - if (decl_ctx == NULL) - 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 (clang::DeclContext::lookup_iterator pos = result.first, end = result.second; pos != end; ++pos) - { - namespace_decl = dyn_cast<clang::NamespaceDecl>(*pos); - if (namespace_decl) - return namespace_decl; - } - - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - &identifier_info, - NULL); - - 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(), - NULL, - NULL); - 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(), - NULL, - NULL); - 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, clang_type_t function_clang_type, int storage, bool is_inline) -{ - FunctionDecl *func_decl = NULL; - ASTContext *ast = getASTContext(); - if (decl_ctx == NULL) - decl_ctx = ast->getTranslationUnitDecl(); - - if (name && name[0]) - { - func_decl = FunctionDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - DeclarationName (&ast->Idents.get(name)), - QualType::getFromOpaquePtr(function_clang_type), - NULL, - (FunctionDecl::StorageClass)storage, - (FunctionDecl::StorageClass)storage, - is_inline); - } - else - { - func_decl = FunctionDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - DeclarationName (), - QualType::getFromOpaquePtr(function_clang_type), - NULL, - (FunctionDecl::StorageClass)storage, - (FunctionDecl::StorageClass)storage, - is_inline); - } - if (func_decl) - decl_ctx->addDecl (func_decl); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(func_decl); -#endif - - return func_decl; -} - -clang_type_t -ClangASTContext::CreateFunctionType (ASTContext *ast, - clang_type_t result_type, - clang_type_t *args, - unsigned num_args, - bool is_variadic, - unsigned type_quals) -{ - assert (ast != NULL); - std::vector<QualType> qual_type_args; - for (unsigned i=0; i<num_args; ++i) - qual_type_args.push_back (QualType::getFromOpaquePtr(args[i])); - - // TODO: Detect calling convention in DWARF? - FunctionProtoType::ExtProtoInfo proto_info; - proto_info.Variadic = is_variadic; - proto_info.ExceptionSpecType = EST_None; - proto_info.TypeQuals = type_quals; - proto_info.RefQualifier = RQ_None; - proto_info.NumExceptions = 0; - proto_info.Exceptions = NULL; - - return ast->getFunctionType (QualType::getFromOpaquePtr(result_type), - qual_type_args.empty() ? NULL : &qual_type_args.front(), - qual_type_args.size(), - proto_info).getAsOpaquePtr(); // NoReturn); -} - -ParmVarDecl * -ClangASTContext::CreateParameterDeclaration (const char *name, clang_type_t param_type, int storage) -{ - ASTContext *ast = getASTContext(); - assert (ast != NULL); - return ParmVarDecl::Create(*ast, - ast->getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : NULL, - QualType::getFromOpaquePtr(param_type), - NULL, - (VarDecl::StorageClass)storage, - (VarDecl::StorageClass)storage, - 0); -} - -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 - -clang_type_t -ClangASTContext::CreateArrayType (clang_type_t element_type, size_t element_count, uint32_t bit_stride) -{ - if (element_type) - { - ASTContext *ast = getASTContext(); - assert (ast != NULL); - llvm::APInt ap_element_count (64, element_count); - return ast->getConstantArrayType(QualType::getFromOpaquePtr(element_type), - ap_element_count, - ArrayType::Normal, - 0).getAsOpaquePtr(); // ElemQuals - } - return NULL; -} - - -#pragma mark TagDecl - -bool -ClangASTContext::StartTagDeclarationDefinition (clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const clang::Type *t = qual_type.getTypePtr(); - if (t) - { - const TagType *tag_type = dyn_cast<TagType>(t); - if (tag_type) - { - TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - tag_decl->startDefinition(); - return true; - } - } - - const ObjCObjectType *object_type = dyn_cast<ObjCObjectType>(t); - if (object_type) - { - ObjCInterfaceDecl *interface_decl = object_type->getInterface(); - if (interface_decl) - { - interface_decl->startDefinition(); - return true; - } - } - } - } - return false; -} - -bool -ClangASTContext::CompleteTagDeclarationDefinition (clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - - if (cxx_record_decl) - { - cxx_record_decl->completeDefinition(); - - return true; - } - - const EnumType *enum_type = dyn_cast<EnumType>(qual_type.getTypePtr()); - - if (enum_type) - { - EnumDecl *enum_decl = enum_type->getDecl(); - - if (enum_decl) - { - /// TODO This really needs to be fixed. - - unsigned NumPositiveBits = 1; - unsigned NumNegativeBits = 0; - - ASTContext *ast = getASTContext(); - - QualType promotion_qual_type; - // If the enum integer type is less than an integer in bit width, - // then we must promote it to an integer size. - if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy)) - { - if (enum_decl->getIntegerType()->isSignedIntegerType()) - promotion_qual_type = ast->IntTy; - else - promotion_qual_type = ast->UnsignedIntTy; - } - else - promotion_qual_type = enum_decl->getIntegerType(); - - enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); - return true; - } - } - } - return false; -} - - -#pragma mark Enumeration Types - -clang_type_t -ClangASTContext::CreateEnumerationType -( - const char *name, - DeclContext *decl_ctx, - const Declaration &decl, - clang_type_t integer_qual_type -) -{ - // TODO: Do something intelligent with the Declaration object passed in - // like maybe filling in the SourceLocation with it... - ASTContext *ast = getASTContext(); - assert (ast != NULL); - - // TODO: ask about these... -// const bool IsScoped = false; -// const bool IsFixed = false; - - EnumDecl *enum_decl = EnumDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : NULL, - NULL, - false, // IsScoped - false, // IsScopedUsingClassTag - false); // IsFixed - - - if (enum_decl) - { - // TODO: check if we should be setting the promotion type too? - enum_decl->setIntegerType(QualType::getFromOpaquePtr (integer_qual_type)); - - enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - - return ast->getTagDeclType(enum_decl).getAsOpaquePtr(); - } - return NULL; -} - -clang_type_t -ClangASTContext::GetEnumerationIntegerType (clang_type_t enum_clang_type) -{ - QualType enum_qual_type (QualType::getFromOpaquePtr(enum_clang_type)); - - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) - { - const EnumType *enum_type = dyn_cast<EnumType>(clang_type); - if (enum_type) - { - EnumDecl *enum_decl = enum_type->getDecl(); - if (enum_decl) - return enum_decl->getIntegerType().getAsOpaquePtr(); - } - } - return NULL; -} -bool -ClangASTContext::AddEnumerationValueToEnumerationType -( - clang_type_t enum_clang_type, - clang_type_t enumerator_clang_type, - const Declaration &decl, - const char *name, - int64_t enum_value, - uint32_t enum_value_bit_size -) -{ - if (enum_clang_type && enumerator_clang_type && name) - { - // TODO: Do something intelligent with the Declaration object passed in - // like maybe filling in the SourceLocation with it... - ASTContext *ast = getASTContext(); - IdentifierTable *identifier_table = getIdentifierTable(); - - assert (ast != NULL); - assert (identifier_table != NULL); - QualType enum_qual_type (QualType::getFromOpaquePtr(enum_clang_type)); - - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) - { - const EnumType *enum_type = dyn_cast<EnumType>(clang_type); - - if (enum_type) - { - llvm::APSInt enum_llvm_apsint(enum_value_bit_size, false); - enum_llvm_apsint = enum_value; - EnumConstantDecl *enumerator_decl = - EnumConstantDecl::Create (*ast, - enum_type->getDecl(), - SourceLocation(), - name ? &identifier_table->get(name) : NULL, // Identifier - QualType::getFromOpaquePtr(enumerator_clang_type), - NULL, - enum_llvm_apsint); - - if (enumerator_decl) - { - enum_type->getDecl()->addDecl(enumerator_decl); - -#ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(enumerator_decl); -#endif - - return true; - } - } - } - } - return false; -} - -#pragma mark Pointers & References - -clang_type_t -ClangASTContext::CreatePointerType (clang_type_t clang_type) -{ - return CreatePointerType (getASTContext(), clang_type); -} - -clang_type_t -ClangASTContext::CreatePointerType (clang::ASTContext *ast, clang_type_t clang_type) -{ - if (ast && clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - return ast->getObjCObjectPointerType(qual_type).getAsOpaquePtr(); - - default: - return ast->getPointerType(qual_type).getAsOpaquePtr(); - } - } - return NULL; -} - -clang_type_t -ClangASTContext::CreateLValueReferenceType (clang::ASTContext *ast, - clang_type_t clang_type) -{ - if (clang_type) - return ast->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr(); - return NULL; -} - -clang_type_t -ClangASTContext::CreateRValueReferenceType (clang::ASTContext *ast, - clang_type_t clang_type) -{ - if (clang_type) - return ast->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr(); - return NULL; -} - -clang_type_t -ClangASTContext::CreateMemberPointerType (clang_type_t clang_pointee_type, clang_type_t clang_class_type) -{ - if (clang_pointee_type && clang_pointee_type) - return getASTContext()->getMemberPointerType(QualType::getFromOpaquePtr(clang_pointee_type), - QualType::getFromOpaquePtr(clang_class_type).getTypePtr()).getAsOpaquePtr(); - return NULL; -} - -uint32_t -ClangASTContext::GetPointerBitSize () -{ - ASTContext *ast = getASTContext(); - return ast->getTypeSize(ast->VoidPtrTy); -} - -bool -ClangASTContext::IsPossibleDynamicType (clang::ASTContext *ast, - clang_type_t clang_type, - clang_type_t *dynamic_pointee_type, - bool check_cplusplus, - bool check_objc) -{ - QualType pointee_qual_type; - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - bool success = false; - switch (type_class) - { - case clang::Type::Builtin: - if (check_objc && cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId) - { - if (dynamic_pointee_type) - *dynamic_pointee_type = clang_type; - return true; - } - break; - - case clang::Type::ObjCObjectPointer: - if (check_objc) - { - if (dynamic_pointee_type) - *dynamic_pointee_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - } - break; - - case clang::Type::Pointer: - pointee_qual_type = cast<PointerType>(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - pointee_qual_type = cast<ReferenceType>(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::Typedef: - return ClangASTContext::IsPossibleDynamicType (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type); - - case clang::Type::Elaborated: - return ClangASTContext::IsPossibleDynamicType (ast, cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), dynamic_pointee_type); - - default: - break; - } - - if (success) - { - // Check to make sure what we are pointing too is a possible dynamic C++ type - // We currently accept any "void *" (in case we have a class that has been - // watered down to an opaque pointer) and virtual C++ classes. - const clang::Type::TypeClass pointee_type_class = pointee_qual_type->getTypeClass(); - switch (pointee_type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(pointee_qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - if (dynamic_pointee_type) - *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr(); - return true; - - case clang::BuiltinType::NullPtr: - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::Half: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::PseudoObject: - break; - } - break; - - case clang::Type::Record: - if (check_cplusplus) - { - CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - // Do NOT complete the type here like we used to do - // otherwise EVERY "class *" variable we have will try - // to fully complete itself and this will take a lot of - // time, memory and slow down debugging. If we have a complete - // type, then answer the question definitively, else we - // just say that a C++ class can possibly be dynamic... - if (cxx_record_decl->isCompleteDefinition()) - { - success = cxx_record_decl->isDynamicClass(); - } - else - { - // We failed to get the complete type, so we have to - // treat this as a void * which we might possibly be - // able to complete - success = true; - } - if (success) - { - if (dynamic_pointee_type) - *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr(); - return true; - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (check_objc) - { - if (dynamic_pointee_type) - *dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr(); - return true; - } - break; - - default: - break; - } - } - } - if (dynamic_pointee_type) - *dynamic_pointee_type = NULL; - return false; -} - - -bool -ClangASTContext::IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast, clang_type_t clang_type, clang_type_t *dynamic_pointee_type) -{ - return IsPossibleDynamicType (ast, - clang_type, - dynamic_pointee_type, - true, // Check for dynamic C++ types - false); // Check for dynamic ObjC types -} - -bool -ClangASTContext::IsReferenceType (clang_type_t clang_type, clang_type_t *target_type) -{ - if (clang_type == NULL) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - - switch (type_class) - { - case clang::Type::LValueReference: - if (target_type) - *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr(); - return true; - case clang::Type::RValueReference: - if (target_type) - *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr(); - return true; - case clang::Type::Typedef: - return ClangASTContext::IsReferenceType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return ClangASTContext::IsReferenceType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - default: - break; - } - - return false; -} - -bool -ClangASTContext::IsPointerOrReferenceType (clang_type_t clang_type, clang_type_t*target_type) -{ - if (clang_type == NULL) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(qual_type)->getKind()) - { - default: - break; - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - return true; - } - return false; - case clang::Type::ObjCObjectPointer: - if (target_type) - *target_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::BlockPointer: - if (target_type) - *target_type = cast<BlockPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::Pointer: - if (target_type) - *target_type = cast<PointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::MemberPointer: - if (target_type) - *target_type = cast<MemberPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::LValueReference: - if (target_type) - *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr(); - return true; - case clang::Type::RValueReference: - if (target_type) - *target_type = cast<LValueReferenceType>(qual_type)->desugar().getAsOpaquePtr(); - return true; - case clang::Type::Typedef: - return ClangASTContext::IsPointerOrReferenceType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return ClangASTContext::IsPointerOrReferenceType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - default: - break; - } - return false; -} - -bool -ClangASTContext::IsIntegerType (clang_type_t clang_type, bool &is_signed) -{ - if (!clang_type) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const BuiltinType *builtin_type = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal()); - - if (builtin_type) - { - if (builtin_type->isInteger()) - { - is_signed = builtin_type->isSignedInteger(); - return true; - } - } - - return false; -} - -bool -ClangASTContext::IsPointerType (clang_type_t clang_type, clang_type_t *target_type) -{ - if (target_type) - *target_type = NULL; - - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(qual_type)->getKind()) - { - default: - break; - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - return true; - } - return false; - case clang::Type::ObjCObjectPointer: - if (target_type) - *target_type = cast<ObjCObjectPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::BlockPointer: - if (target_type) - *target_type = cast<BlockPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::Pointer: - if (target_type) - *target_type = cast<PointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::MemberPointer: - if (target_type) - *target_type = cast<MemberPointerType>(qual_type)->getPointeeType().getAsOpaquePtr(); - return true; - case clang::Type::Typedef: - return ClangASTContext::IsPointerType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), target_type); - case clang::Type::Elaborated: - return ClangASTContext::IsPointerType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), target_type); - default: - break; - } - } - return false; -} - -bool -ClangASTContext::IsFloatingPointType (clang_type_t clang_type, uint32_t &count, bool &is_complex) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - if (const BuiltinType *BT = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal())) - { - clang::BuiltinType::Kind kind = BT->getKind(); - if (kind >= BuiltinType::Float && kind <= BuiltinType::LongDouble) - { - count = 1; - is_complex = false; - return true; - } - } - else if (const ComplexType *CT = dyn_cast<ComplexType>(qual_type->getCanonicalTypeInternal())) - { - if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count, is_complex)) - { - count = 2; - is_complex = true; - return true; - } - } - else if (const VectorType *VT = dyn_cast<VectorType>(qual_type->getCanonicalTypeInternal())) - { - if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count, is_complex)) - { - count = VT->getNumElements(); - is_complex = false; - return true; - } - } - } - return false; -} - -bool -ClangASTContext::IsScalarType (lldb::clang_type_t clang_type) -{ - bool is_signed; - if (ClangASTContext::IsIntegerType(clang_type, is_signed)) - return true; - - uint32_t count; - bool is_complex; - return ClangASTContext::IsFloatingPointType(clang_type, count, is_complex) && !is_complex; -} - -bool -ClangASTContext::IsPointerToScalarType (lldb::clang_type_t clang_type) -{ - if (!IsPointerType(clang_type)) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - lldb::clang_type_t pointee_type = qual_type.getTypePtr()->getPointeeType().getAsOpaquePtr(); - return IsScalarType(pointee_type); -} - -bool -ClangASTContext::IsArrayOfScalarType (lldb::clang_type_t clang_type) -{ - clang_type = GetAsArrayType(clang_type); - - if (clang_type == 0) - return false; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - lldb::clang_type_t item_type = cast<ArrayType>(qual_type.getTypePtr())->getElementType().getAsOpaquePtr(); - return IsScalarType(item_type); -} - - -bool -ClangASTContext::GetCXXClassName (clang_type_t clang_type, std::string &class_name) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - class_name.assign (cxx_record_decl->getIdentifier()->getNameStart()); - return true; - } - } - class_name.clear(); - return false; -} - - -bool -ClangASTContext::IsCXXClassType (clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - if (qual_type->getAsCXXRecordDecl() != NULL) - return true; - } - return false; -} - -bool -ClangASTContext::IsBeingDefined (lldb::clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - const clang::TagType *tag_type = dyn_cast<clang::TagType>(qual_type); - if (tag_type) - return tag_type->isBeingDefined(); - } - return false; -} - -bool -ClangASTContext::IsObjCClassType (clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - if (qual_type->isObjCObjectOrInterfaceType()) - return true; - } - return false; -} - -bool -ClangASTContext::IsObjCObjectPointerType (lldb::clang_type_t clang_type, clang_type_t *class_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - if (qual_type->isObjCObjectPointerType()) - { - if (class_type) - { - *class_type = NULL; - - if (!qual_type->isObjCClassType() && - !qual_type->isObjCIdType()) - { - const ObjCObjectPointerType *obj_pointer_type = dyn_cast<ObjCObjectPointerType>(qual_type); - if (!obj_pointer_type) - *class_type = NULL; - else - *class_type = QualType(obj_pointer_type->getInterfaceType(), 0).getAsOpaquePtr(); - } - } - return true; - } - } - return false; -} - -bool -ClangASTContext::GetObjCClassName (lldb::clang_type_t clang_type, - std::string &class_name) -{ - if (!clang_type) - return false; - - const ObjCObjectType *object_type = dyn_cast<ObjCObjectType>(QualType::getFromOpaquePtr(clang_type)); - if (!object_type) - return false; - - const ObjCInterfaceDecl *interface = object_type->getInterface(); - if (!interface) - return false; - - class_name = interface->getNameAsString(); - return true; -} - -bool -ClangASTContext::IsCharType (clang_type_t clang_type) -{ - if (clang_type) - return QualType::getFromOpaquePtr(clang_type)->isCharType(); - return false; -} - -bool -ClangASTContext::IsCStringType (clang_type_t clang_type, uint32_t &length) -{ - clang_type_t pointee_or_element_clang_type = NULL; - Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, NULL, &pointee_or_element_clang_type)); - - if (pointee_or_element_clang_type == NULL) - return false; - - if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer)) - { - QualType pointee_or_element_qual_type (QualType::getFromOpaquePtr (pointee_or_element_clang_type)); - - if (pointee_or_element_qual_type.getUnqualifiedType()->isCharType()) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - if (type_flags.Test (eTypeIsArray)) - { - // We know the size of the array and it could be a C string - // since it is an array of characters - length = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue(); - return true; - } - else - { - length = 0; - return true; - } - - } - } - return false; -} - -bool -ClangASTContext::IsFunctionPointerType (clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - if (qual_type->isFunctionPointerType()) - return true; - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return ClangASTContext::IsFunctionPointerType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return ClangASTContext::IsFunctionPointerType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const ReferenceType *reference_type = cast<ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return ClangASTContext::IsFunctionPointerType (reference_type->getPointeeType().getAsOpaquePtr()); - } - break; - } - } - return false; -} - -size_t -ClangASTContext::GetArraySize (clang_type_t clang_type) -{ - if (clang_type) - { - QualType qual_type(QualType::getFromOpaquePtr(clang_type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ConstantArray: - { - const ConstantArrayType *array = cast<ConstantArrayType>(QualType::getFromOpaquePtr(clang_type).getTypePtr()); - if (array) - return array->getSize().getLimitedValue(); - } - break; - - case clang::Type::Typedef: - return ClangASTContext::GetArraySize(cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - - case clang::Type::Elaborated: - return ClangASTContext::GetArraySize(cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - - default: - break; - } - } - return 0; -} - -clang_type_t -ClangASTContext::GetAsArrayType (clang_type_t clang_type, clang_type_t*member_type, uint64_t *size) -{ - if (!clang_type) - return 0; - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - - case clang::Type::ConstantArray: - if (member_type) - *member_type = cast<ConstantArrayType>(qual_type)->getElementType().getAsOpaquePtr(); - if (size) - *size = cast<ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX); - return clang_type; - - case clang::Type::IncompleteArray: - if (member_type) - *member_type = cast<IncompleteArrayType>(qual_type)->getElementType().getAsOpaquePtr(); - if (size) - *size = 0; - return clang_type; - - case clang::Type::VariableArray: - if (member_type) - *member_type = cast<VariableArrayType>(qual_type)->getElementType().getAsOpaquePtr(); - if (size) - *size = 0; - return clang_type; - - case clang::Type::DependentSizedArray: - if (member_type) - *member_type = cast<DependentSizedArrayType>(qual_type)->getElementType().getAsOpaquePtr(); - if (size) - *size = 0; - return clang_type; - - case clang::Type::Typedef: - return ClangASTContext::GetAsArrayType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - member_type, - size); - - case clang::Type::Elaborated: - return ClangASTContext::GetAsArrayType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - member_type, - size); - } - return 0; -} - - -#pragma mark Typedefs - -clang_type_t -ClangASTContext::CreateTypedefType (const char *name, clang_type_t clang_type, DeclContext *decl_ctx) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - ASTContext *ast = getASTContext(); - IdentifierTable *identifier_table = getIdentifierTable(); - assert (ast != NULL); - assert (identifier_table != NULL); - if (decl_ctx == NULL) - decl_ctx = ast->getTranslationUnitDecl(); - TypedefDecl *decl = TypedefDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - name ? &identifier_table->get(name) : NULL, // Identifier - ast->CreateTypeSourceInfo(qual_type)); - - //decl_ctx->addDecl (decl); - - decl->setAccess(AS_public); // TODO respect proper access specifier - - // Get a uniqued QualType for the typedef decl type - return ast->getTypedefType (decl).getAsOpaquePtr(); - } - return NULL; -} - -// 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; -//} - -size_t -ClangASTContext::ConvertStringToFloatValue (ASTContext *ast, clang_type_t clang_type, const char *s, uint8_t *dst, size_t dst_size) -{ - if (clang_type) - { - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - uint32_t count = 0; - bool is_complex = false; - if (ClangASTContext::IsFloatingPointType (clang_type, count, is_complex)) - { - // TODO: handle complex and vector types - if (count != 1) - return false; - - StringRef s_sref(s); - APFloat ap_float(ast->getFloatTypeSemantics(qual_type), s_sref); - - const uint64_t bit_size = ast->getTypeSize (qual_type); - const uint64_t byte_size = bit_size / 8; - if (dst_size >= byte_size) - { - if (bit_size == sizeof(float)*8) - { - float float32 = ap_float.convertToFloat(); - ::memcpy (dst, &float32, byte_size); - return byte_size; - } - else if (bit_size >= 64) - { - llvm::APInt ap_int(ap_float.bitcastToAPInt()); - ::memcpy (dst, ap_int.getRawData(), byte_size); - return byte_size; - } - } - } - } - return 0; -} - -unsigned -ClangASTContext::GetTypeQualifiers(clang_type_t clang_type) -{ - assert (clang_type); - - QualType qual_type (QualType::getFromOpaquePtr(clang_type)); - - return qual_type.getQualifiers().getCVRQualifiers(); -} - -bool -ClangASTContext::GetCompleteType (clang::ASTContext *ast, lldb::clang_type_t clang_type) -{ - if (clang_type == NULL) - return false; - - return GetCompleteQualType (ast, clang::QualType::getFromOpaquePtr(clang_type)); -} - - -bool -ClangASTContext::GetCompleteType (clang_type_t clang_type) -{ - return ClangASTContext::GetCompleteType (getASTContext(), clang_type); -} - -bool -ClangASTContext::IsCompleteType (clang::ASTContext *ast, lldb::clang_type_t clang_type) -{ - if (clang_type == NULL) - return false; - - return GetCompleteQualType (ast, clang::QualType::getFromOpaquePtr(clang_type), false); // just check but don't let it actually complete -} - - -bool -ClangASTContext::IsCompleteType (clang_type_t clang_type) -{ - return ClangASTContext::IsCompleteType (getASTContext(), clang_type); -} - -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::SetMetadata (clang::ASTContext *ast, - uintptr_t object, - uint64_t metadata) -{ - ClangExternalASTSourceCommon *external_source = - static_cast<ClangExternalASTSourceCommon*>(ast->getExternalSource()); - - if (external_source) - external_source->SetMetadata(object, metadata); -} - -uint64_t -ClangASTContext::GetMetadata (clang::ASTContext *ast, - uintptr_t object) -{ - ClangExternalASTSourceCommon *external_source = - static_cast<ClangExternalASTSourceCommon*>(ast->getExternalSource()); - - if (external_source && external_source->HasMetadata(object)) - return external_source->GetMetadata(object); - else - return 0; -} - -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); -} - |
