summaryrefslogtreecommitdiff
path: root/lldb/source/Symbol
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol')
-rw-r--r--lldb/source/Symbol/ArmUnwindInfo.cpp4
-rw-r--r--lldb/source/Symbol/Block.cpp2
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp9298
-rw-r--r--lldb/source/Symbol/ClangASTImporter.cpp1165
-rw-r--r--lldb/source/Symbol/ClangASTMetadata.cpp35
-rw-r--r--lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp45
-rw-r--r--lldb/source/Symbol/ClangUtil.cpp82
-rw-r--r--lldb/source/Symbol/CompactUnwindInfo.cpp2
-rw-r--r--lldb/source/Symbol/CompileUnit.cpp2
-rw-r--r--lldb/source/Symbol/CompilerDecl.cpp2
-rw-r--r--lldb/source/Symbol/CompilerDeclContext.cpp2
-rw-r--r--lldb/source/Symbol/CompilerType.cpp45
-rw-r--r--lldb/source/Symbol/CxxModuleHandler.cpp289
-rw-r--r--lldb/source/Symbol/DWARFCallFrameInfo.cpp4
-rw-r--r--lldb/source/Symbol/DebugMacros.cpp2
-rw-r--r--lldb/source/Symbol/DeclVendor.cpp2
-rw-r--r--lldb/source/Symbol/Declaration.cpp2
-rw-r--r--lldb/source/Symbol/FuncUnwinders.cpp2
-rw-r--r--lldb/source/Symbol/Function.cpp95
-rw-r--r--lldb/source/Symbol/LineEntry.cpp2
-rw-r--r--lldb/source/Symbol/LineTable.cpp26
-rw-r--r--lldb/source/Symbol/LocateSymbolFile.cpp2
-rw-r--r--lldb/source/Symbol/LocateSymbolFileMacOSX.cpp72
-rw-r--r--lldb/source/Symbol/ObjectFile.cpp13
-rw-r--r--lldb/source/Symbol/PostfixExpression.cpp2
-rw-r--r--lldb/source/Symbol/Symbol.cpp21
-rw-r--r--lldb/source/Symbol/SymbolContext.cpp22
-rw-r--r--lldb/source/Symbol/SymbolFile.cpp8
-rw-r--r--lldb/source/Symbol/SymbolVendor.cpp4
-rw-r--r--lldb/source/Symbol/Symtab.cpp6
-rw-r--r--lldb/source/Symbol/Type.cpp37
-rw-r--r--lldb/source/Symbol/TypeList.cpp5
-rw-r--r--lldb/source/Symbol/TypeMap.cpp9
-rw-r--r--lldb/source/Symbol/TypeSystem.cpp25
-rw-r--r--lldb/source/Symbol/UnwindPlan.cpp14
-rw-r--r--lldb/source/Symbol/UnwindTable.cpp16
-rw-r--r--lldb/source/Symbol/Variable.cpp17
-rw-r--r--lldb/source/Symbol/VariableList.cpp2
38 files changed, 244 insertions, 11139 deletions
diff --git a/lldb/source/Symbol/ArmUnwindInfo.cpp b/lldb/source/Symbol/ArmUnwindInfo.cpp
index fdf4e30b2db5..f2887035e5cf 100644
--- a/lldb/source/Symbol/ArmUnwindInfo.cpp
+++ b/lldb/source/Symbol/ArmUnwindInfo.cpp
@@ -1,4 +1,4 @@
-//===-- ArmUnwindInfo.cpp ---------------------------------------*- C++ -*-===//
+//===-- ArmUnwindInfo.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -29,7 +29,7 @@
using namespace lldb;
using namespace lldb_private;
-// Converts a prel31 avlue to lldb::addr_t with sign extension
+// Converts a prel31 value to lldb::addr_t with sign extension
static addr_t Prel31ToAddr(uint32_t prel31) {
addr_t res = prel31;
if (prel31 & (1 << 30))
diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp
index bf380064200a..afcdf3e21e19 100644
--- a/lldb/source/Symbol/Block.cpp
+++ b/lldb/source/Symbol/Block.cpp
@@ -1,4 +1,4 @@
-//===-- Block.cpp -----------------------------------------------*- C++ -*-===//
+//===-- Block.cpp ---------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
deleted file mode 100644
index ac3bce179d9e..000000000000
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ /dev/null
@@ -1,9298 +0,0 @@
-//===-- ClangASTContext.cpp -------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangASTContext.h"
-
-#include "llvm/Support/FormatAdapters.h"
-#include "llvm/Support/FormatVariadic.h"
-
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTImporter.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/CXXInheritance.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Mangle.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/VTableBuilder.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/LangStandard.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/TargetOptions.h"
-#include "clang/Frontend/FrontendOptions.h"
-#include "clang/Sema/Sema.h"
-
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/Threading.h"
-
-#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h"
-#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
-#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h"
-#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h"
-#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/Flags.h"
-
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/ThreadSafeDenseMap.h"
-#include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Language.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/RegularExpression.h"
-#include "lldb/Utility/Scalar.h"
-
-#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
-#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
-#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
-
-#include <stdio.h>
-
-#include <mutex>
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace clang;
-using llvm::StringSwitch;
-
-namespace {
-#ifdef LLDB_CONFIGURATION_DEBUG
-static void VerifyDecl(clang::Decl *decl) {
- assert(decl && "VerifyDecl called with nullptr?");
- decl->getAccess();
-}
-#endif
-
-static inline bool
-ClangASTContextSupportsLanguage(lldb::LanguageType language) {
- return language == eLanguageTypeUnknown || // Clang is the default type system
- lldb_private::Language::LanguageIsC(language) ||
- lldb_private::Language::LanguageIsCPlusPlus(language) ||
- lldb_private::Language::LanguageIsObjC(language) ||
- lldb_private::Language::LanguageIsPascal(language) ||
- // Use Clang for Rust until there is a proper language plugin for it
- language == eLanguageTypeRust ||
- language == eLanguageTypeExtRenderScript ||
- // Use Clang for D until there is a proper language plugin for it
- language == eLanguageTypeD ||
- // Open Dylan compiler debug info is designed to be Clang-compatible
- language == eLanguageTypeDylan;
-}
-
-// Checks whether m1 is an overload of m2 (as opposed to an override). This is
-// called by addOverridesForMethod to distinguish overrides (which share a
-// vtable entry) from overloads (which require distinct entries).
-bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
- // FIXME: This should detect covariant return types, but currently doesn't.
- lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
- "Methods should have the same AST context");
- clang::ASTContext &context = m1->getASTContext();
-
- const auto *m1Type = llvm::cast<clang::FunctionProtoType>(
- context.getCanonicalType(m1->getType()));
-
- const auto *m2Type = llvm::cast<clang::FunctionProtoType>(
- context.getCanonicalType(m2->getType()));
-
- auto compareArgTypes = [&context](const clang::QualType &m1p,
- const clang::QualType &m2p) {
- return context.hasSameType(m1p.getUnqualifiedType(),
- m2p.getUnqualifiedType());
- };
-
- // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
- // as a fourth parameter to std::equal().
- return (m1->getNumParams() != m2->getNumParams()) ||
- !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
- m2Type->param_type_begin(), compareArgTypes);
-}
-
-// If decl is a virtual method, walk the base classes looking for methods that
-// decl overrides. This table of overridden methods is used by IRGen to
-// determine the vtable layout for decl's parent class.
-void addOverridesForMethod(clang::CXXMethodDecl *decl) {
- if (!decl->isVirtual())
- return;
-
- clang::CXXBasePaths paths;
-
- auto find_overridden_methods =
- [decl](const clang::CXXBaseSpecifier *specifier,
- clang::CXXBasePath &path) {
- if (auto *base_record = llvm::dyn_cast<clang::CXXRecordDecl>(
- specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
-
- clang::DeclarationName name = decl->getDeclName();
-
- // If this is a destructor, check whether the base class destructor is
- // virtual.
- if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
- if (auto *baseDtorDecl = base_record->getDestructor()) {
- if (baseDtorDecl->isVirtual()) {
- path.Decls = baseDtorDecl;
- return true;
- } else
- return false;
- }
-
- // Otherwise, search for name in the base class.
- for (path.Decls = base_record->lookup(name); !path.Decls.empty();
- path.Decls = path.Decls.slice(1)) {
- if (auto *method_decl =
- llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
- if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
- path.Decls = method_decl;
- return true;
- }
- }
- }
-
- return false;
- };
-
- if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
- for (auto *overridden_decl : paths.found_decls())
- decl->addOverriddenMethod(
- llvm::cast<clang::CXXMethodDecl>(overridden_decl));
- }
-}
-}
-
-static lldb::addr_t GetVTableAddress(Process &process,
- VTableContextBase &vtable_ctx,
- ValueObject &valobj,
- const ASTRecordLayout &record_layout) {
- // Retrieve type info
- CompilerType pointee_type;
- CompilerType this_type(valobj.GetCompilerType());
- uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
- if (!type_info)
- return LLDB_INVALID_ADDRESS;
-
- // Check if it's a pointer or reference
- bool ptr_or_ref = false;
- if (type_info & (eTypeIsPointer | eTypeIsReference)) {
- ptr_or_ref = true;
- type_info = pointee_type.GetTypeInfo();
- }
-
- // We process only C++ classes
- const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus;
- if ((type_info & cpp_class) != cpp_class)
- return LLDB_INVALID_ADDRESS;
-
- // Calculate offset to VTable pointer
- lldb::offset_t vbtable_ptr_offset =
- vtable_ctx.isMicrosoft() ? record_layout.getVBPtrOffset().getQuantity()
- : 0;
-
- if (ptr_or_ref) {
- // We have a pointer / ref to object, so read
- // VTable pointer from process memory
-
- if (valobj.GetAddressTypeOfChildren() != eAddressTypeLoad)
- return LLDB_INVALID_ADDRESS;
-
- auto vbtable_ptr_addr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- if (vbtable_ptr_addr == LLDB_INVALID_ADDRESS)
- return LLDB_INVALID_ADDRESS;
-
- vbtable_ptr_addr += vbtable_ptr_offset;
-
- Status err;
- return process.ReadPointerFromMemory(vbtable_ptr_addr, err);
- }
-
- // We have an object already read from process memory,
- // so just extract VTable pointer from it
-
- DataExtractor data;
- Status err;
- auto size = valobj.GetData(data, err);
- if (err.Fail() || vbtable_ptr_offset + data.GetAddressByteSize() > size)
- return LLDB_INVALID_ADDRESS;
-
- return data.GetPointer(&vbtable_ptr_offset);
-}
-
-static int64_t ReadVBaseOffsetFromVTable(Process &process,
- VTableContextBase &vtable_ctx,
- lldb::addr_t vtable_ptr,
- const CXXRecordDecl *cxx_record_decl,
- const CXXRecordDecl *base_class_decl) {
- if (vtable_ctx.isMicrosoft()) {
- clang::MicrosoftVTableContext &msoft_vtable_ctx =
- static_cast<clang::MicrosoftVTableContext &>(vtable_ctx);
-
- // Get the index into the virtual base table. The
- // index is the index in uint32_t from vbtable_ptr
- const unsigned vbtable_index =
- msoft_vtable_ctx.getVBTableIndex(cxx_record_decl, base_class_decl);
- const lldb::addr_t base_offset_addr = vtable_ptr + vbtable_index * 4;
- Status err;
- return process.ReadSignedIntegerFromMemory(base_offset_addr, 4, INT64_MAX,
- err);
- }
-
- clang::ItaniumVTableContext &itanium_vtable_ctx =
- static_cast<clang::ItaniumVTableContext &>(vtable_ctx);
-
- clang::CharUnits base_offset_offset =
- itanium_vtable_ctx.getVirtualBaseOffsetOffset(cxx_record_decl,
- base_class_decl);
- const lldb::addr_t base_offset_addr =
- vtable_ptr + base_offset_offset.getQuantity();
- const uint32_t base_offset_size = process.GetAddressByteSize();
- Status err;
- return process.ReadSignedIntegerFromMemory(base_offset_addr, base_offset_size,
- INT64_MAX, err);
-}
-
-static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx,
- ValueObject &valobj,
- const ASTRecordLayout &record_layout,
- const CXXRecordDecl *cxx_record_decl,
- const CXXRecordDecl *base_class_decl,
- int32_t &bit_offset) {
- ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
- Process *process = exe_ctx.GetProcessPtr();
- if (!process)
- return false;
-
- lldb::addr_t vtable_ptr =
- GetVTableAddress(*process, vtable_ctx, valobj, record_layout);
- if (vtable_ptr == LLDB_INVALID_ADDRESS)
- return false;
-
- auto base_offset = ReadVBaseOffsetFromVTable(
- *process, vtable_ctx, vtable_ptr, cxx_record_decl, base_class_decl);
- if (base_offset == INT64_MAX)
- return false;
-
- bit_offset = base_offset * 8;
-
- return true;
-}
-
-typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext *>
- ClangASTMap;
-
-static ClangASTMap &GetASTMap() {
- static ClangASTMap *g_map_ptr = nullptr;
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, []() {
- g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins
- });
- return *g_map_ptr;
-}
-
-char ClangASTContext::ID;
-
-bool ClangASTContext::IsOperator(llvm::StringRef name,
- clang::OverloadedOperatorKind &op_kind) {
- // All operators have to start with "operator".
- if (!name.consume_front("operator"))
- return false;
-
- // Remember if there was a space after "operator". This is necessary to
- // check for collisions with strangely named functions like "operatorint()".
- bool space_after_operator = name.consume_front(" ");
-
- op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
- .Case("+", clang::OO_Plus)
- .Case("+=", clang::OO_PlusEqual)
- .Case("++", clang::OO_PlusPlus)
- .Case("-", clang::OO_Minus)
- .Case("-=", clang::OO_MinusEqual)
- .Case("--", clang::OO_MinusMinus)
- .Case("->", clang::OO_Arrow)
- .Case("->*", clang::OO_ArrowStar)
- .Case("*", clang::OO_Star)
- .Case("*=", clang::OO_StarEqual)
- .Case("/", clang::OO_Slash)
- .Case("/=", clang::OO_SlashEqual)
- .Case("%", clang::OO_Percent)
- .Case("%=", clang::OO_PercentEqual)
- .Case("^", clang::OO_Caret)
- .Case("^=", clang::OO_CaretEqual)
- .Case("&", clang::OO_Amp)
- .Case("&=", clang::OO_AmpEqual)
- .Case("&&", clang::OO_AmpAmp)
- .Case("|", clang::OO_Pipe)
- .Case("|=", clang::OO_PipeEqual)
- .Case("||", clang::OO_PipePipe)
- .Case("~", clang::OO_Tilde)
- .Case("!", clang::OO_Exclaim)
- .Case("!=", clang::OO_ExclaimEqual)
- .Case("=", clang::OO_Equal)
- .Case("==", clang::OO_EqualEqual)
- .Case("<", clang::OO_Less)
- .Case("<<", clang::OO_LessLess)
- .Case("<<=", clang::OO_LessLessEqual)
- .Case("<=", clang::OO_LessEqual)
- .Case(">", clang::OO_Greater)
- .Case(">>", clang::OO_GreaterGreater)
- .Case(">>=", clang::OO_GreaterGreaterEqual)
- .Case(">=", clang::OO_GreaterEqual)
- .Case("()", clang::OO_Call)
- .Case("[]", clang::OO_Subscript)
- .Case(",", clang::OO_Comma)
- .Default(clang::NUM_OVERLOADED_OPERATORS);
-
- // We found a fitting operator, so we can exit now.
- if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
- return true;
-
- // After the "operator " or "operator" part is something unknown. This means
- // it's either one of the named operators (new/delete), a conversion operator
- // (e.g. operator bool) or a function which name starts with "operator"
- // (e.g. void operatorbool).
-
- // If it's a function that starts with operator it can't have a space after
- // "operator" because identifiers can't contain spaces.
- // E.g. "operator int" (conversion operator)
- // vs. "operatorint" (function with colliding name).
- if (!space_after_operator)
- return false; // not an operator.
-
- // Now the operator is either one of the named operators or a conversion
- // operator.
- op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
- .Case("new", clang::OO_New)
- .Case("new[]", clang::OO_Array_New)
- .Case("delete", clang::OO_Delete)
- .Case("delete[]", clang::OO_Array_Delete)
- // conversion operators hit this case.
- .Default(clang::NUM_OVERLOADED_OPERATORS);
-
- return true;
-}
-
-clang::AccessSpecifier
-ClangASTContext::ConvertAccessTypeToAccessSpecifier(AccessType access) {
- switch (access) {
- default:
- break;
- case eAccessNone:
- return AS_none;
- case eAccessPublic:
- return AS_public;
- case eAccessPrivate:
- return AS_private;
- case eAccessProtected:
- return AS_protected;
- }
- return AS_none;
-}
-
-static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
- // FIXME: Cleanup per-file based stuff.
-
- // Set some properties which depend solely 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.getLanguage() == clang::Language::Asm) {
- Opts.AsmPreprocessor = 1;
- } else if (IK.isObjectiveC()) {
- Opts.ObjC = 1;
- }
-
- LangStandard::Kind LangStd = LangStandard::lang_unspecified;
-
- if (LangStd == LangStandard::lang_unspecified) {
- // Based on the base language, pick one.
- switch (IK.getLanguage()) {
- case clang::Language::Unknown:
- case clang::Language::LLVM_IR:
- case clang::Language::RenderScript:
- llvm_unreachable("Invalid input kind!");
- case clang::Language::OpenCL:
- LangStd = LangStandard::lang_opencl10;
- break;
- case clang::Language::CUDA:
- LangStd = LangStandard::lang_cuda;
- break;
- case clang::Language::Asm:
- case clang::Language::C:
- case clang::Language::ObjC:
- LangStd = LangStandard::lang_gnu99;
- break;
- case clang::Language::CXX:
- case clang::Language::ObjCXX:
- LangStd = LangStandard::lang_gnucxx98;
- break;
- case clang::Language::HIP:
- LangStd = LangStandard::lang_hip;
- break;
- }
- }
-
- const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
- Opts.LineComment = Std.hasLineComments();
- Opts.C99 = Std.isC99();
- Opts.CPlusPlus = Std.isCPlusPlus();
- Opts.CPlusPlus11 = Std.isCPlusPlus11();
- Opts.Digraphs = Std.hasDigraphs();
- Opts.GNUMode = Std.isGNUMode();
- Opts.GNUInline = !Std.isC99();
- Opts.HexFloats = Std.hasHexFloats();
- Opts.ImplicitInt = Std.hasImplicitInt();
-
- Opts.WChar = true;
-
- // OpenCL has some additional defaults.
- if (LangStd == LangStandard::lang_opencl10) {
- Opts.OpenCL = 1;
- Opts.AltiVec = 1;
- Opts.CXXOperatorNames = 1;
- Opts.setLaxVectorConversions(LangOptions::LaxVectorConversionKind::All);
- }
-
- // OpenCL and C++ both have bool, true, false keywords.
- Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
-
- Opts.setValueVisibilityMode(DefaultVisibility);
-
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs is
- // specified, or -std is set to a conforming mode.
- Opts.Trigraphs = !Opts.GNUMode;
- Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault();
- Opts.OptimizeSize = 0;
-
- // FIXME: Eliminate this dependency.
- // unsigned Opt =
- // Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
- // Opts.Optimize = Opt != 0;
- unsigned Opt = 0;
-
- // This is the __NO_INLINE__ define, which just depends on things like the
- // optimization level and -fno-inline, not actually whether the backend has
- // inlining enabled.
- //
- // FIXME: This is affected by other options (-fno-inline).
- Opts.NoInlineDefine = !Opt;
-}
-
-ClangASTContext::ClangASTContext(llvm::Triple target_triple) {
- if (!target_triple.str().empty())
- SetTargetTriple(target_triple.str());
- // The caller didn't pass an ASTContext so create a new one for this
- // ClangASTContext.
- CreateASTContext();
-}
-
-ClangASTContext::ClangASTContext(ASTContext &existing_ctxt) {
- SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str());
-
- m_ast_up.reset(&existing_ctxt);
- GetASTMap().Insert(&existing_ctxt, this);
-}
-
-// Destructor
-ClangASTContext::~ClangASTContext() { Finalize(); }
-
-ConstString ClangASTContext::GetPluginNameStatic() {
- return ConstString("clang");
-}
-
-ConstString ClangASTContext::GetPluginName() {
- return ClangASTContext::GetPluginNameStatic();
-}
-
-uint32_t ClangASTContext::GetPluginVersion() { return 1; }
-
-lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language,
- lldb_private::Module *module,
- Target *target) {
- if (!ClangASTContextSupportsLanguage(language))
- return lldb::TypeSystemSP();
- ArchSpec arch;
- if (module)
- arch = module->GetArchitecture();
- else if (target)
- arch = target->GetArchitecture();
-
- if (!arch.IsValid())
- return lldb::TypeSystemSP();
-
- llvm::Triple triple = arch.GetTriple();
- // LLVM wants this to be set to iOS or MacOSX; if we're working on
- // a bare-boards type image, change the triple for llvm's benefit.
- if (triple.getVendor() == llvm::Triple::Apple &&
- triple.getOS() == llvm::Triple::UnknownOS) {
- if (triple.getArch() == llvm::Triple::arm ||
- triple.getArch() == llvm::Triple::aarch64 ||
- triple.getArch() == llvm::Triple::aarch64_32 ||
- triple.getArch() == llvm::Triple::thumb) {
- triple.setOS(llvm::Triple::IOS);
- } else {
- triple.setOS(llvm::Triple::MacOSX);
- }
- }
-
- if (module)
- return std::make_shared<ClangASTContext>(triple);
- else if (target && target->IsValid())
- return std::make_shared<ClangASTContextForExpressions>(*target, triple);
- return lldb::TypeSystemSP();
-}
-
-LanguageSet ClangASTContext::GetSupportedLanguagesForTypes() {
- LanguageSet languages;
- languages.Insert(lldb::eLanguageTypeC89);
- languages.Insert(lldb::eLanguageTypeC);
- languages.Insert(lldb::eLanguageTypeC11);
- languages.Insert(lldb::eLanguageTypeC_plus_plus);
- languages.Insert(lldb::eLanguageTypeC99);
- languages.Insert(lldb::eLanguageTypeObjC);
- languages.Insert(lldb::eLanguageTypeObjC_plus_plus);
- languages.Insert(lldb::eLanguageTypeC_plus_plus_03);
- languages.Insert(lldb::eLanguageTypeC_plus_plus_11);
- languages.Insert(lldb::eLanguageTypeC11);
- languages.Insert(lldb::eLanguageTypeC_plus_plus_14);
- return languages;
-}
-
-LanguageSet ClangASTContext::GetSupportedLanguagesForExpressions() {
- LanguageSet languages;
- languages.Insert(lldb::eLanguageTypeC_plus_plus);
- languages.Insert(lldb::eLanguageTypeObjC_plus_plus);
- languages.Insert(lldb::eLanguageTypeC_plus_plus_03);
- languages.Insert(lldb::eLanguageTypeC_plus_plus_11);
- languages.Insert(lldb::eLanguageTypeC_plus_plus_14);
- return languages;
-}
-
-void ClangASTContext::Initialize() {
- PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "clang base AST context plug-in", CreateInstance,
- GetSupportedLanguagesForTypes(), GetSupportedLanguagesForExpressions());
-}
-
-void ClangASTContext::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-void ClangASTContext::Finalize() {
- assert(m_ast_up);
- GetASTMap().Erase(m_ast_up.get());
- if (!m_ast_owned)
- m_ast_up.release();
-
- m_builtins_up.reset();
- m_selector_table_up.reset();
- m_identifier_table_up.reset();
- m_target_info_up.reset();
- m_target_options_rp.reset();
- m_diagnostics_engine_up.reset();
- m_source_manager_up.reset();
- m_language_options_up.reset();
-}
-
-void ClangASTContext::setSema(Sema *s) {
- // Ensure that the new sema actually belongs to our ASTContext.
- assert(s == nullptr || &s->getASTContext() == m_ast_up.get());
- m_sema = s;
-}
-
-const char *ClangASTContext::GetTargetTriple() {
- return m_target_triple.c_str();
-}
-
-void ClangASTContext::SetTargetTriple(llvm::StringRef target_triple) {
- m_target_triple = target_triple.str();
-}
-
-void ClangASTContext::SetExternalSource(
- llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
- ASTContext &ast = getASTContext();
- ast.setExternalSource(ast_source_up);
- ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
-}
-
-ASTContext &ClangASTContext::getASTContext() {
- assert(m_ast_up);
- return *m_ast_up;
-}
-
-class NullDiagnosticConsumer : public DiagnosticConsumer {
-public:
- NullDiagnosticConsumer() {
- m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- }
-
- void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const clang::Diagnostic &info) override {
- if (m_log) {
- llvm::SmallVector<char, 32> diag_str(10);
- info.FormatDiagnostic(diag_str);
- diag_str.push_back('\0');
- LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data());
- }
- }
-
- DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
- return new NullDiagnosticConsumer();
- }
-
-private:
- Log *m_log;
-};
-
-void ClangASTContext::CreateASTContext() {
- assert(!m_ast_up);
- m_ast_owned = true;
-
- m_language_options_up.reset(new LangOptions());
- ParseLangArgs(*m_language_options_up, clang::Language::ObjCXX,
- GetTargetTriple());
-
- m_identifier_table_up.reset(
- new IdentifierTable(*m_language_options_up, nullptr));
- m_builtins_up.reset(new Builtin::Context());
-
- m_selector_table_up.reset(new SelectorTable());
-
- clang::FileSystemOptions file_system_options;
- m_file_manager_up.reset(new clang::FileManager(
- file_system_options, FileSystem::Instance().GetVirtualFileSystem()));
-
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs());
- m_diagnostics_engine_up.reset(
- new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions()));
-
- m_source_manager_up.reset(
- new clang::SourceManager(*m_diagnostics_engine_up, *m_file_manager_up));
- m_ast_up.reset(new ASTContext(*m_language_options_up, *m_source_manager_up,
- *m_identifier_table_up, *m_selector_table_up,
- *m_builtins_up));
-
- m_diagnostic_consumer_up.reset(new NullDiagnosticConsumer);
- m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);
-
- // This can be NULL if we don't know anything about the architecture or if
- // the target for an architecture isn't enabled in the llvm/clang that we
- // built
- TargetInfo *target_info = getTargetInfo();
- if (target_info)
- m_ast_up->InitBuiltinTypes(*target_info);
-
- GetASTMap().Insert(m_ast_up.get(), this);
-
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_up(
- new ClangExternalASTSourceCallbacks(*this));
- SetExternalSource(ast_source_up);
-}
-
-ClangASTContext *ClangASTContext::GetASTContext(clang::ASTContext *ast) {
- ClangASTContext *clang_ast = GetASTMap().Lookup(ast);
- return clang_ast;
-}
-
-clang::MangleContext *ClangASTContext::getMangleContext() {
- if (m_mangle_ctx_up == nullptr)
- m_mangle_ctx_up.reset(getASTContext().createMangleContext());
- return m_mangle_ctx_up.get();
-}
-
-std::shared_ptr<clang::TargetOptions> &ClangASTContext::getTargetOptions() {
- if (m_target_options_rp == nullptr && !m_target_triple.empty()) {
- m_target_options_rp = std::make_shared<clang::TargetOptions>();
- if (m_target_options_rp != nullptr)
- m_target_options_rp->Triple = m_target_triple;
- }
- return m_target_options_rp;
-}
-
-TargetInfo *ClangASTContext::getTargetInfo() {
- // target_triple should be something like "x86_64-apple-macosx"
- if (m_target_info_up == nullptr && !m_target_triple.empty())
- m_target_info_up.reset(TargetInfo::CreateTargetInfo(
- getASTContext().getDiagnostics(), getTargetOptions()));
- return m_target_info_up.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);
- return qual_type_bit_size == bit_size;
-}
-
-CompilerType
-ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
- size_t bit_size) {
- ASTContext &ast = getASTContext();
- switch (encoding) {
- case eEncodingInvalid:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
- return GetType(ast.VoidPtrTy);
- break;
-
- case eEncodingUint:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
- return GetType(ast.UnsignedCharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
- return GetType(ast.UnsignedShortTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
- return GetType(ast.UnsignedIntTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
- return GetType(ast.UnsignedLongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
- return GetType(ast.UnsignedLongLongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
- return GetType(ast.UnsignedInt128Ty);
- break;
-
- case eEncodingSint:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
- return GetType(ast.SignedCharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
- return GetType(ast.ShortTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
- return GetType(ast.IntTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
- return GetType(ast.LongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
- return GetType(ast.LongLongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
- return GetType(ast.Int128Ty);
- break;
-
- case eEncodingIEEE754:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
- return GetType(ast.FloatTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
- return GetType(ast.DoubleTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
- return GetType(ast.LongDoubleTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
- return GetType(ast.HalfTy);
- break;
-
- case eEncodingVector:
- // Sanity check that bit_size is a multiple of 8's.
- if (bit_size && !(bit_size & 0x7u))
- return GetType(ast.getExtVectorType(ast.UnsignedCharTy, bit_size / 8));
- break;
- }
-
- return CompilerType();
-}
-
-lldb::BasicType
-ClangASTContext::GetBasicTypeEnumeration(ConstString name) {
- if (name) {
- typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap;
- static TypeNameToBasicTypeMap g_type_map;
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, []() {
- // "void"
- g_type_map.Append(ConstString("void"), eBasicTypeVoid);
-
- // "char"
- g_type_map.Append(ConstString("char"), eBasicTypeChar);
- g_type_map.Append(ConstString("signed char"), eBasicTypeSignedChar);
- g_type_map.Append(ConstString("unsigned char"), eBasicTypeUnsignedChar);
- g_type_map.Append(ConstString("wchar_t"), eBasicTypeWChar);
- g_type_map.Append(ConstString("signed wchar_t"), eBasicTypeSignedWChar);
- g_type_map.Append(ConstString("unsigned wchar_t"),
- eBasicTypeUnsignedWChar);
- // "short"
- g_type_map.Append(ConstString("short"), eBasicTypeShort);
- g_type_map.Append(ConstString("short int"), eBasicTypeShort);
- g_type_map.Append(ConstString("unsigned short"), eBasicTypeUnsignedShort);
- g_type_map.Append(ConstString("unsigned short int"),
- eBasicTypeUnsignedShort);
-
- // "int"
- g_type_map.Append(ConstString("int"), eBasicTypeInt);
- g_type_map.Append(ConstString("signed int"), eBasicTypeInt);
- g_type_map.Append(ConstString("unsigned int"), eBasicTypeUnsignedInt);
- g_type_map.Append(ConstString("unsigned"), eBasicTypeUnsignedInt);
-
- // "long"
- g_type_map.Append(ConstString("long"), eBasicTypeLong);
- g_type_map.Append(ConstString("long int"), eBasicTypeLong);
- g_type_map.Append(ConstString("unsigned long"), eBasicTypeUnsignedLong);
- g_type_map.Append(ConstString("unsigned long int"),
- eBasicTypeUnsignedLong);
-
- // "long long"
- g_type_map.Append(ConstString("long long"), eBasicTypeLongLong);
- g_type_map.Append(ConstString("long long int"), eBasicTypeLongLong);
- g_type_map.Append(ConstString("unsigned long long"),
- eBasicTypeUnsignedLongLong);
- g_type_map.Append(ConstString("unsigned long long int"),
- eBasicTypeUnsignedLongLong);
-
- // "int128"
- g_type_map.Append(ConstString("__int128_t"), eBasicTypeInt128);
- g_type_map.Append(ConstString("__uint128_t"), eBasicTypeUnsignedInt128);
-
- // Miscellaneous
- g_type_map.Append(ConstString("bool"), eBasicTypeBool);
- g_type_map.Append(ConstString("float"), eBasicTypeFloat);
- g_type_map.Append(ConstString("double"), eBasicTypeDouble);
- g_type_map.Append(ConstString("long double"), eBasicTypeLongDouble);
- g_type_map.Append(ConstString("id"), eBasicTypeObjCID);
- g_type_map.Append(ConstString("SEL"), eBasicTypeObjCSel);
- g_type_map.Append(ConstString("nullptr"), eBasicTypeNullPtr);
- g_type_map.Sort();
- });
-
- return g_type_map.Find(name, eBasicTypeInvalid);
- }
- return eBasicTypeInvalid;
-}
-
-uint32_t ClangASTContext::GetPointerByteSize() {
- if (m_pointer_byte_size == 0)
- if (auto size = GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType()
- .GetByteSize(nullptr))
- m_pointer_byte_size = *size;
- return m_pointer_byte_size;
-}
-
-CompilerType ClangASTContext::GetBasicType(lldb::BasicType basic_type) {
- clang::ASTContext &ast = getASTContext();
-
- lldb::opaque_compiler_type_t clang_type =
- GetOpaqueCompilerType(&ast, basic_type);
-
- if (clang_type)
- return CompilerType(this, clang_type);
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize(
- llvm::StringRef type_name, uint32_t dw_ate, uint32_t bit_size) {
- ASTContext &ast = getASTContext();
-
- switch (dw_ate) {
- default:
- break;
-
- case DW_ATE_address:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.VoidPtrTy))
- return GetType(ast.VoidPtrTy);
- break;
-
- case DW_ATE_boolean:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.BoolTy))
- return GetType(ast.BoolTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
- return GetType(ast.UnsignedCharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
- return GetType(ast.UnsignedShortTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
- return GetType(ast.UnsignedIntTy);
- break;
-
- case DW_ATE_lo_user:
- // This has been seen to mean DW_AT_complex_integer
- if (type_name.contains("complex")) {
- CompilerType complex_int_clang_type =
- GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed,
- bit_size / 2);
- return GetType(
- ast.getComplexType(ClangUtil::GetQualType(complex_int_clang_type)));
- }
- break;
-
- case DW_ATE_complex_float:
- if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatComplexTy))
- return GetType(ast.FloatComplexTy);
- else if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleComplexTy))
- return GetType(ast.DoubleComplexTy);
- else if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleComplexTy))
- return GetType(ast.LongDoubleComplexTy);
- else {
- CompilerType complex_float_clang_type =
- GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float,
- bit_size / 2);
- return GetType(
- ast.getComplexType(ClangUtil::GetQualType(complex_float_clang_type)));
- }
- break;
-
- case DW_ATE_float:
- if (type_name == "float" &&
- QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
- return GetType(ast.FloatTy);
- if (type_name == "double" &&
- QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
- return GetType(ast.DoubleTy);
- if (type_name == "long double" &&
- QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
- return GetType(ast.LongDoubleTy);
- // Fall back to not requiring a name match
- if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy))
- return GetType(ast.FloatTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.DoubleTy))
- return GetType(ast.DoubleTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy))
- return GetType(ast.LongDoubleTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy))
- return GetType(ast.HalfTy);
- break;
-
- case DW_ATE_signed:
- if (!type_name.empty()) {
- if (type_name == "wchar_t" &&
- QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
- (getTargetInfo() &&
- TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
- return GetType(ast.WCharTy);
- if (type_name == "void" &&
- QualTypeMatchesBitSize(bit_size, ast, ast.VoidTy))
- return GetType(ast.VoidTy);
- if (type_name.contains("long long") &&
- QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
- return GetType(ast.LongLongTy);
- if (type_name.contains("long") &&
- QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
- return GetType(ast.LongTy);
- if (type_name.contains("short") &&
- QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
- return GetType(ast.ShortTy);
- if (type_name.contains("char")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
- return GetType(ast.CharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
- return GetType(ast.SignedCharTy);
- }
- if (type_name.contains("int")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
- return GetType(ast.IntTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
- return GetType(ast.Int128Ty);
- }
- }
- // We weren't able to match up a type name, just search by size
- if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
- return GetType(ast.CharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.ShortTy))
- return GetType(ast.ShortTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.IntTy))
- return GetType(ast.IntTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.LongTy))
- return GetType(ast.LongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.LongLongTy))
- return GetType(ast.LongLongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.Int128Ty))
- return GetType(ast.Int128Ty);
- break;
-
- case DW_ATE_signed_char:
- if (ast.getLangOpts().CharIsSigned && type_name == "char") {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
- return GetType(ast.CharTy);
- }
- if (QualTypeMatchesBitSize(bit_size, ast, ast.SignedCharTy))
- return GetType(ast.SignedCharTy);
- break;
-
- case DW_ATE_unsigned:
- if (!type_name.empty()) {
- if (type_name == "wchar_t") {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
- if (!(getTargetInfo() &&
- TargetInfo::isTypeSigned(getTargetInfo()->getWCharType())))
- return GetType(ast.WCharTy);
- }
- }
- if (type_name.contains("long long")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
- return GetType(ast.UnsignedLongLongTy);
- } else if (type_name.contains("long")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
- return GetType(ast.UnsignedLongTy);
- } else if (type_name.contains("short")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
- return GetType(ast.UnsignedShortTy);
- } else if (type_name.contains("char")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
- return GetType(ast.UnsignedCharTy);
- } else if (type_name.contains("int")) {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
- return GetType(ast.UnsignedIntTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
- return GetType(ast.UnsignedInt128Ty);
- }
- }
- // We weren't able to match up a type name, just search by size
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
- return GetType(ast.UnsignedCharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
- return GetType(ast.UnsignedShortTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedIntTy))
- return GetType(ast.UnsignedIntTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongTy))
- return GetType(ast.UnsignedLongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedLongLongTy))
- return GetType(ast.UnsignedLongLongTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedInt128Ty))
- return GetType(ast.UnsignedInt128Ty);
- break;
-
- case DW_ATE_unsigned_char:
- if (!ast.getLangOpts().CharIsSigned && type_name == "char") {
- if (QualTypeMatchesBitSize(bit_size, ast, ast.CharTy))
- return GetType(ast.CharTy);
- }
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedCharTy))
- return GetType(ast.UnsignedCharTy);
- if (QualTypeMatchesBitSize(bit_size, ast, ast.UnsignedShortTy))
- return GetType(ast.UnsignedShortTy);
- break;
-
- case DW_ATE_imaginary_float:
- break;
-
- case DW_ATE_UTF:
- if (!type_name.empty()) {
- if (type_name == "char16_t")
- return GetType(ast.Char16Ty);
- if (type_name == "char32_t")
- return GetType(ast.Char32Ty);
- if (type_name == "char8_t")
- return GetType(ast.Char8Ty);
- }
- 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.empty()) {
- std::string type_name_str = type_name.str();
- 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_str.c_str(), 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 CompilerType();
-}
-
-CompilerType ClangASTContext::GetCStringType(bool is_const) {
- ASTContext &ast = getASTContext();
- QualType char_type(ast.CharTy);
-
- if (is_const)
- char_type.addConst();
-
- return GetType(ast.getPointerType(char_type));
-}
-
-bool ClangASTContext::AreTypesSame(CompilerType type1, CompilerType type2,
- bool ignore_qualifiers) {
- ClangASTContext *ast =
- llvm::dyn_cast_or_null<ClangASTContext>(type1.GetTypeSystem());
- if (!ast || ast != type2.GetTypeSystem())
- return false;
-
- if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType())
- return true;
-
- QualType type1_qual = ClangUtil::GetQualType(type1);
- QualType type2_qual = ClangUtil::GetQualType(type2);
-
- if (ignore_qualifiers) {
- type1_qual = type1_qual.getUnqualifiedType();
- type2_qual = type2_qual.getUnqualifiedType();
- }
-
- return ast->getASTContext().hasSameType(type1_qual, type2_qual);
-}
-
-CompilerType ClangASTContext::GetTypeForDecl(void *opaque_decl) {
- if (!opaque_decl)
- return CompilerType();
-
- clang::Decl *decl = static_cast<clang::Decl *>(opaque_decl);
- if (auto *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl))
- return GetTypeForDecl(named_decl);
- return CompilerType();
-}
-
-CompilerDeclContext ClangASTContext::CreateDeclContext(DeclContext *ctx) {
- // Check that the DeclContext actually belongs to this ASTContext.
- assert(&ctx->getParentASTContext() == &getASTContext());
- return CompilerDeclContext(this, ctx);
-}
-
-CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) {
- if (clang::ObjCInterfaceDecl *interface_decl =
- llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
- return GetTypeForDecl(interface_decl);
- if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
- return GetTypeForDecl(tag_decl);
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) {
- return GetType(getASTContext().getTagDeclType(decl));
-}
-
-CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) {
- return GetType(getASTContext().getObjCInterfaceType(decl));
-}
-
-#pragma mark Structure, Unions, Classes
-
-CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
- AccessType access_type,
- llvm::StringRef name, int kind,
- LanguageType language,
- ClangASTMetadata *metadata,
- bool exports_symbols) {
- ASTContext &ast = getASTContext();
-
- if (decl_ctx == nullptr)
- 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.
-
- bool has_name = !name.empty();
-
- CXXRecordDecl *decl = CXXRecordDecl::Create(
- ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), SourceLocation(),
- has_name ? &ast.Idents.get(name) : nullptr);
-
- if (!has_name) {
- // In C++ a lambda is also represented as an unnamed class. This is
- // different from an *anonymous class* that the user wrote:
- //
- // struct A {
- // // anonymous class (GNU/MSVC extension)
- // struct {
- // int x;
- // };
- // // unnamed class within a class
- // struct {
- // int y;
- // } B;
- // };
- //
- // void f() {
- // // unammed class outside of a class
- // struct {
- // int z;
- // } C;
- // }
- //
- // Anonymous classes is a GNU/MSVC extension that clang supports. It
- // requires the anonymous class be embedded within a class. So the new
- // heuristic verifies this condition.
- if (isa<CXXRecordDecl>(decl_ctx) && exports_symbols)
- decl->setAnonymousStructOrUnion(true);
- }
-
- if (decl) {
- if (metadata)
- SetMetadata(decl, *metadata);
-
- if (access_type != eAccessNone)
- decl->setAccess(ConvertAccessTypeToAccessSpecifier(access_type));
-
- if (decl_ctx)
- decl_ctx->addDecl(decl);
-
- return GetType(ast.getTagDeclType(decl));
- }
- return CompilerType();
-}
-
-namespace {
- bool IsValueParam(const clang::TemplateArgument &argument) {
- return argument.getKind() == TemplateArgument::Integral;
- }
-}
-
-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.args.size();
- DeclContext *const decl_context =
- ast->getTranslationUnitDecl(); // Is this the right decl context?,
- for (size_t i = 0; i < num_template_params; ++i) {
- const char *name = template_param_infos.names[i];
-
- IdentifierInfo *identifier_info = nullptr;
- if (name && name[0])
- identifier_info = &ast->Idents.get(name);
- if (IsValueParam(template_param_infos.args[i])) {
- template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
- *ast, decl_context,
- SourceLocation(), SourceLocation(), depth, i, identifier_info,
- template_param_infos.args[i].getIntegralType(), parameter_pack,
- nullptr));
-
- } else {
- template_param_decls.push_back(TemplateTypeParmDecl::Create(
- *ast, decl_context,
- SourceLocation(), SourceLocation(), depth, i, identifier_info,
- is_typename, parameter_pack));
- }
- }
-
- if (template_param_infos.packed_args) {
- IdentifierInfo *identifier_info = nullptr;
- if (template_param_infos.pack_name && template_param_infos.pack_name[0])
- identifier_info = &ast->Idents.get(template_param_infos.pack_name);
- const bool parameter_pack_true = true;
-
- if (!template_param_infos.packed_args->args.empty() &&
- IsValueParam(template_param_infos.packed_args->args[0])) {
- template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
- *ast, decl_context, SourceLocation(), SourceLocation(), depth,
- num_template_params, identifier_info,
- template_param_infos.packed_args->args[0].getIntegralType(),
- parameter_pack_true, nullptr));
- } else {
- template_param_decls.push_back(TemplateTypeParmDecl::Create(
- *ast, decl_context, SourceLocation(), SourceLocation(), depth,
- num_template_params, identifier_info, is_typename,
- parameter_pack_true));
- }
- }
- clang::Expr *const requires_clause = nullptr; // TODO: Concepts
- TemplateParameterList *template_param_list = TemplateParameterList::Create(
- *ast, SourceLocation(), SourceLocation(), template_param_decls,
- SourceLocation(), requires_clause);
- return template_param_list;
-}
-
-clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl(
- clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl,
- const char *name, const TemplateParameterInfos &template_param_infos) {
- // /// 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);
- }
- // Function templates inside a record need to have an access specifier.
- // It doesn't matter what access specifier we give the template as LLDB
- // anyway allows accessing everything inside a record.
- if (decl_ctx->isRecord())
- func_tmpl_decl->setAccess(clang::AccessSpecifier::AS_public);
-
- return func_tmpl_decl;
-}
-
-void ClangASTContext::CreateFunctionTemplateSpecializationInfo(
- FunctionDecl *func_decl, clang::FunctionTemplateDecl *func_tmpl_decl,
- const TemplateParameterInfos &infos) {
- TemplateArgumentList *template_args_ptr =
- TemplateArgumentList::CreateCopy(func_decl->getASTContext(), infos.args);
-
- func_decl->setFunctionTemplateSpecialization(func_tmpl_decl,
- template_args_ptr, nullptr);
-}
-
-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 = nullptr;
- if (decl_ctx == nullptr)
- decl_ctx = ast.getTranslationUnitDecl();
-
- IdentifierInfo &identifier_info = ast.Idents.get(class_name);
- DeclarationName decl_name(&identifier_info);
-
- clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
-
- for (NamedDecl *decl : result) {
- class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl);
- if (class_template_decl)
- return class_template_decl;
- }
-
- llvm::SmallVector<NamedDecl *, 8> template_param_decls;
-
- TemplateParameterList *template_param_list = CreateTemplateParameterList(
- &ast, template_param_infos, template_param_decls);
-
- CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create(
- ast, (TagDecl::TagKind)kind,
- decl_ctx, // What decl context do we use here? TU? The actual decl
- // context?
- SourceLocation(), SourceLocation(), &identifier_info);
-
- for (size_t i = 0, template_param_decl_count = template_param_decls.size();
- i < template_param_decl_count; ++i) {
- template_param_decls[i]->setDeclContext(template_cxx_decl);
- }
-
- // With templated classes, we say that a class is templated with
- // specializations, but that the bare class has no functions.
- // template_cxx_decl->startDefinition();
- // template_cxx_decl->completeDefinition();
-
- class_template_decl = ClassTemplateDecl::Create(
- ast,
- decl_ctx, // What decl context do we use here? TU? The actual decl
- // context?
- SourceLocation(), decl_name, template_param_list, template_cxx_decl);
- template_cxx_decl->setDescribedClassTemplate(class_template_decl);
-
- 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;
-}
-
-TemplateTemplateParmDecl *
-ClangASTContext::CreateTemplateTemplateParmDecl(const char *template_name) {
- ASTContext &ast = getASTContext();
-
- auto *decl_ctx = ast.getTranslationUnitDecl();
-
- IdentifierInfo &identifier_info = ast.Idents.get(template_name);
- llvm::SmallVector<NamedDecl *, 8> template_param_decls;
-
- ClangASTContext::TemplateParameterInfos template_param_infos;
- TemplateParameterList *template_param_list = CreateTemplateParameterList(
- &ast, template_param_infos, template_param_decls);
-
- // LLDB needs to create those decls only to be able to display a
- // type that includes a template template argument. Only the name matters for
- // this purpose, so we use dummy values for the other characterisitcs of the
- // type.
- return TemplateTemplateParmDecl::Create(
- ast, decl_ctx, SourceLocation(),
- /*Depth*/ 0, /*Position*/ 0,
- /*IsParameterPack*/ false, &identifier_info, template_param_list);
-}
-
-ClassTemplateSpecializationDecl *
-ClangASTContext::CreateClassTemplateSpecializationDecl(
- DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
- const TemplateParameterInfos &template_param_infos) {
- ASTContext &ast = getASTContext();
- llvm::SmallVector<clang::TemplateArgument, 2> args(
- template_param_infos.args.size() +
- (template_param_infos.packed_args ? 1 : 0));
- std::copy(template_param_infos.args.begin(), template_param_infos.args.end(),
- args.begin());
- if (template_param_infos.packed_args) {
- args[args.size() - 1] = TemplateArgument::CreatePackCopy(
- ast, template_param_infos.packed_args->args);
- }
- ClassTemplateSpecializationDecl *class_template_specialization_decl =
- ClassTemplateSpecializationDecl::Create(
- ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
- SourceLocation(), class_template_decl, args, nullptr);
-
- class_template_specialization_decl->setSpecializationKind(
- TSK_ExplicitSpecialization);
-
- return class_template_specialization_decl;
-}
-
-CompilerType ClangASTContext::CreateClassTemplateSpecializationType(
- ClassTemplateSpecializationDecl *class_template_specialization_decl) {
- if (class_template_specialization_decl) {
- ASTContext &ast = getASTContext();
- return GetType(ast.getTagDeclType(class_template_specialization_decl));
- }
- return CompilerType();
-}
-
-static inline bool check_op_param(bool is_method,
- clang::OverloadedOperatorKind 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 doesn't include "this"
- if (is_method)
- ++num_params;
- if (num_params == 1)
- return unary;
- if (num_params == 2)
- return binary;
- else
- return false;
-}
-
-bool ClangASTContext::CheckOverloadedOperatorKindParameterCount(
- bool is_method, clang::OverloadedOperatorKind 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(is_method, op_kind, Unary, Binary, num_params);
- switch (op_kind) {
-#include "clang/Basic/OperatorKinds.def"
- default:
- break;
- }
- return false;
-}
-
-clang::AccessSpecifier
-ClangASTContext::UnifyAccessSpecifiers(clang::AccessSpecifier lhs,
- clang::AccessSpecifier rhs) {
- // Make the access equal to the stricter of the field and the nested field's
- // access
- if (lhs == AS_none || rhs == AS_none)
- return AS_none;
- if (lhs == AS_private || rhs == AS_private)
- return AS_private;
- if (lhs == AS_protected || rhs == AS_protected)
- return AS_protected;
- return AS_public;
-}
-
-bool ClangASTContext::FieldIsBitfield(FieldDecl *field,
- uint32_t &bitfield_bit_size) {
- ASTContext &ast = getASTContext();
- if (field == nullptr)
- 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 == nullptr)
- return false;
-
- if (!record_decl->field_empty())
- return true;
-
- // No fields, lets check this is a CXX record and check the base classes
- const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
- if (cxx_record_decl) {
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(),
- base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end; ++base_class) {
- const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(
- base_class->getType()->getAs<RecordType>()->getDecl());
- if (RecordHasFields(base_class_decl))
- return true;
- }
- }
- return false;
-}
-
-#pragma mark Objective-C Classes
-
-CompilerType ClangASTContext::CreateObjCClass(llvm::StringRef name,
- DeclContext *decl_ctx,
- bool isForwardDecl,
- bool isInternal,
- ClangASTMetadata *metadata) {
- ASTContext &ast = getASTContext();
- assert(!name.empty());
- if (decl_ctx == nullptr)
- decl_ctx = ast.getTranslationUnitDecl();
-
- ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create(
- ast, decl_ctx, SourceLocation(), &ast.Idents.get(name), nullptr, nullptr,
- SourceLocation(),
- /*isForwardDecl,*/
- isInternal);
-
- if (decl && metadata)
- SetMetadata(decl, *metadata);
-
- return GetType(ast.getObjCInterfaceType(decl));
-}
-
-static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) {
- return !ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl());
-}
-
-uint32_t
-ClangASTContext::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl,
- bool omit_empty_base_classes) {
- uint32_t num_bases = 0;
- if (cxx_record_decl) {
- if (omit_empty_base_classes) {
- CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(),
- base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end; ++base_class) {
- // Skip empty base classes
- if (omit_empty_base_classes) {
- if (BaseSpecifierIsEmpty(base_class))
- continue;
- }
- ++num_bases;
- }
- } else
- num_bases = cxx_record_decl->getNumBases();
- }
- return num_bases;
-}
-
-#pragma mark Namespace Declarations
-
-NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
- const char *name, DeclContext *decl_ctx, bool is_inline) {
- NamespaceDecl *namespace_decl = nullptr;
- ASTContext &ast = getASTContext();
- TranslationUnitDecl *translation_unit_decl = ast.getTranslationUnitDecl();
- if (decl_ctx == nullptr)
- decl_ctx = translation_unit_decl;
-
- if (name) {
- IdentifierInfo &identifier_info = ast.Idents.get(name);
- DeclarationName decl_name(&identifier_info);
- clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
- for (NamedDecl *decl : result) {
- namespace_decl = dyn_cast<clang::NamespaceDecl>(decl);
- if (namespace_decl)
- return namespace_decl;
- }
-
- namespace_decl =
- NamespaceDecl::Create(ast, decl_ctx, is_inline, SourceLocation(),
- SourceLocation(), &identifier_info, nullptr);
-
- 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(), nullptr, nullptr);
- 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(), nullptr, nullptr);
- parent_namespace_decl->setAnonymousNamespace(namespace_decl);
- parent_namespace_decl->addDecl(namespace_decl);
- assert(namespace_decl ==
- parent_namespace_decl->getAnonymousNamespace());
- } else {
- assert(false && "GetUniqueNamespaceDeclaration called with no name and "
- "no namespace as decl_ctx");
- }
- }
- }
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(namespace_decl);
-#endif
- return namespace_decl;
-}
-
-clang::BlockDecl *
-ClangASTContext::CreateBlockDeclaration(clang::DeclContext *ctx) {
- if (ctx != nullptr) {
- clang::BlockDecl *decl =
- clang::BlockDecl::Create(getASTContext(), ctx, clang::SourceLocation());
- ctx->addDecl(decl);
- return decl;
- }
- return nullptr;
-}
-
-clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left,
- clang::DeclContext *right,
- clang::DeclContext *root) {
- if (root == nullptr)
- return nullptr;
-
- std::set<clang::DeclContext *> path_left;
- for (clang::DeclContext *d = left; d != nullptr; d = d->getParent())
- path_left.insert(d);
-
- for (clang::DeclContext *d = right; d != nullptr; d = d->getParent())
- if (path_left.find(d) != path_left.end())
- return d;
-
- return nullptr;
-}
-
-clang::UsingDirectiveDecl *ClangASTContext::CreateUsingDirectiveDeclaration(
- clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) {
- if (decl_ctx != nullptr && ns_decl != nullptr) {
- auto *translation_unit = getASTContext().getTranslationUnitDecl();
- clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(
- getASTContext(), decl_ctx, clang::SourceLocation(),
- clang::SourceLocation(), clang::NestedNameSpecifierLoc(),
- clang::SourceLocation(), ns_decl,
- FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit));
- decl_ctx->addDecl(using_decl);
- return using_decl;
- }
- return nullptr;
-}
-
-clang::UsingDecl *
-ClangASTContext::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
- clang::NamedDecl *target) {
- if (current_decl_ctx != nullptr && target != nullptr) {
- clang::UsingDecl *using_decl = clang::UsingDecl::Create(
- getASTContext(), current_decl_ctx, clang::SourceLocation(),
- clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
- clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
- getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
- target);
- using_decl->addShadowDecl(shadow_decl);
- current_decl_ctx->addDecl(using_decl);
- return using_decl;
- }
- return nullptr;
-}
-
-clang::VarDecl *ClangASTContext::CreateVariableDeclaration(
- clang::DeclContext *decl_context, const char *name, clang::QualType type) {
- if (decl_context != nullptr) {
- clang::VarDecl *var_decl = clang::VarDecl::Create(
- getASTContext(), decl_context, clang::SourceLocation(),
- clang::SourceLocation(),
- name && name[0] ? &getASTContext().Idents.getOwn(name) : nullptr, type,
- nullptr, clang::SC_None);
- var_decl->setAccess(clang::AS_public);
- decl_context->addDecl(var_decl);
- return var_decl;
- }
- return nullptr;
-}
-
-lldb::opaque_compiler_type_t
-ClangASTContext::GetOpaqueCompilerType(clang::ASTContext *ast,
- lldb::BasicType basic_type) {
- switch (basic_type) {
- case eBasicTypeVoid:
- return ast->VoidTy.getAsOpaquePtr();
- case eBasicTypeChar:
- return ast->CharTy.getAsOpaquePtr();
- case eBasicTypeSignedChar:
- return ast->SignedCharTy.getAsOpaquePtr();
- case eBasicTypeUnsignedChar:
- return ast->UnsignedCharTy.getAsOpaquePtr();
- case eBasicTypeWChar:
- return ast->getWCharType().getAsOpaquePtr();
- case eBasicTypeSignedWChar:
- return ast->getSignedWCharType().getAsOpaquePtr();
- case eBasicTypeUnsignedWChar:
- return ast->getUnsignedWCharType().getAsOpaquePtr();
- case eBasicTypeChar16:
- return ast->Char16Ty.getAsOpaquePtr();
- case eBasicTypeChar32:
- return ast->Char32Ty.getAsOpaquePtr();
- case eBasicTypeShort:
- return ast->ShortTy.getAsOpaquePtr();
- case eBasicTypeUnsignedShort:
- return ast->UnsignedShortTy.getAsOpaquePtr();
- case eBasicTypeInt:
- return ast->IntTy.getAsOpaquePtr();
- case eBasicTypeUnsignedInt:
- return ast->UnsignedIntTy.getAsOpaquePtr();
- case eBasicTypeLong:
- return ast->LongTy.getAsOpaquePtr();
- case eBasicTypeUnsignedLong:
- return ast->UnsignedLongTy.getAsOpaquePtr();
- case eBasicTypeLongLong:
- return ast->LongLongTy.getAsOpaquePtr();
- case eBasicTypeUnsignedLongLong:
- return ast->UnsignedLongLongTy.getAsOpaquePtr();
- case eBasicTypeInt128:
- return ast->Int128Ty.getAsOpaquePtr();
- case eBasicTypeUnsignedInt128:
- return ast->UnsignedInt128Ty.getAsOpaquePtr();
- case eBasicTypeBool:
- return ast->BoolTy.getAsOpaquePtr();
- case eBasicTypeHalf:
- return ast->HalfTy.getAsOpaquePtr();
- case eBasicTypeFloat:
- return ast->FloatTy.getAsOpaquePtr();
- case eBasicTypeDouble:
- return ast->DoubleTy.getAsOpaquePtr();
- case eBasicTypeLongDouble:
- return ast->LongDoubleTy.getAsOpaquePtr();
- case eBasicTypeFloatComplex:
- return ast->FloatComplexTy.getAsOpaquePtr();
- case eBasicTypeDoubleComplex:
- return ast->DoubleComplexTy.getAsOpaquePtr();
- case eBasicTypeLongDoubleComplex:
- return ast->LongDoubleComplexTy.getAsOpaquePtr();
- case eBasicTypeObjCID:
- return ast->getObjCIdType().getAsOpaquePtr();
- case eBasicTypeObjCClass:
- return ast->getObjCClassType().getAsOpaquePtr();
- case eBasicTypeObjCSel:
- return ast->getObjCSelType().getAsOpaquePtr();
- case eBasicTypeNullPtr:
- return ast->NullPtrTy.getAsOpaquePtr();
- default:
- return nullptr;
- }
-}
-
-#pragma mark Function Types
-
-clang::DeclarationName
-ClangASTContext::GetDeclarationName(const char *name,
- const CompilerType &function_clang_type) {
- if (!name || !name[0])
- return clang::DeclarationName();
-
- clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
- if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS)
- return DeclarationName(&getASTContext().Idents.get(
- name)); // Not operator, but a regular function.
-
- // 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 method
- // and add it to the class, clang will assert and crash, so we need to make
- // sure things are acceptable.
- clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type));
- const clang::FunctionProtoType *function_type =
- llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr());
- if (function_type == nullptr)
- return clang::DeclarationName();
-
- const bool is_method = false;
- const unsigned int num_params = function_type->getNumParams();
- if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(
- is_method, op_kind, num_params))
- return clang::DeclarationName();
-
- return getASTContext().DeclarationNames.getCXXOperatorName(op_kind);
-}
-
-FunctionDecl *ClangASTContext::CreateFunctionDeclaration(
- DeclContext *decl_ctx, const char *name,
- const CompilerType &function_clang_type, int storage, bool is_inline) {
- FunctionDecl *func_decl = nullptr;
- ASTContext &ast = getASTContext();
- if (decl_ctx == nullptr)
- decl_ctx = ast.getTranslationUnitDecl();
-
- const bool hasWrittenPrototype = true;
- const bool isConstexprSpecified = false;
-
- clang::DeclarationName declarationName =
- GetDeclarationName(name, function_clang_type);
- func_decl = FunctionDecl::Create(
- ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName,
- ClangUtil::GetQualType(function_clang_type), nullptr,
- (clang::StorageClass)storage, is_inline, hasWrittenPrototype,
- isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
- if (func_decl)
- decl_ctx->addDecl(func_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(func_decl);
-#endif
-
- return func_decl;
-}
-
-CompilerType
-ClangASTContext::CreateFunctionType(const CompilerType &result_type,
- const CompilerType *args, unsigned num_args,
- bool is_variadic, unsigned type_quals,
- clang::CallingConv cc) {
- if (!result_type || !ClangUtil::IsClangType(result_type))
- return CompilerType(); // invalid return type
-
- std::vector<QualType> qual_type_args;
- if (num_args > 0 && args == nullptr)
- return CompilerType(); // invalid argument array passed in
-
- // Verify that all arguments are valid and the right type
- for (unsigned i = 0; i < num_args; ++i) {
- if (args[i]) {
- // Make sure we have a clang type in args[i] and not a type from another
- // language whose name might match
- const bool is_clang_type = ClangUtil::IsClangType(args[i]);
- lldbassert(is_clang_type);
- if (is_clang_type)
- qual_type_args.push_back(ClangUtil::GetQualType(args[i]));
- else
- return CompilerType(); // invalid argument type (must be a clang type)
- } else
- return CompilerType(); // invalid argument type (empty)
- }
-
- // TODO: Detect calling convention in DWARF?
- FunctionProtoType::ExtProtoInfo proto_info;
- proto_info.ExtInfo = cc;
- proto_info.Variadic = is_variadic;
- proto_info.ExceptionSpec = EST_None;
- proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals);
- proto_info.RefQualifier = RQ_None;
-
- return GetType(getASTContext().getFunctionType(
- ClangUtil::GetQualType(result_type), qual_type_args, proto_info));
-}
-
-ParmVarDecl *ClangASTContext::CreateParameterDeclaration(
- clang::DeclContext *decl_ctx, const char *name,
- const CompilerType &param_type, int storage, bool add_decl) {
- ASTContext &ast = getASTContext();
- auto *decl =
- ParmVarDecl::Create(ast, decl_ctx, SourceLocation(), SourceLocation(),
- name && name[0] ? &ast.Idents.get(name) : nullptr,
- ClangUtil::GetQualType(param_type), nullptr,
- (clang::StorageClass)storage, nullptr);
- if (add_decl)
- decl_ctx->addDecl(decl);
-
- return decl;
-}
-
-void ClangASTContext::SetFunctionParameters(FunctionDecl *function_decl,
- ParmVarDecl **params,
- unsigned num_params) {
- if (function_decl)
- function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params));
-}
-
-CompilerType
-ClangASTContext::CreateBlockPointerType(const CompilerType &function_type) {
- QualType block_type = m_ast_up->getBlockPointerType(
- clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType()));
-
- return GetType(block_type);
-}
-
-#pragma mark Array Types
-
-CompilerType ClangASTContext::CreateArrayType(const CompilerType &element_type,
- size_t element_count,
- bool is_vector) {
- if (element_type.IsValid()) {
- ASTContext &ast = getASTContext();
-
- if (is_vector) {
- return GetType(ast.getExtVectorType(ClangUtil::GetQualType(element_type),
- element_count));
- } else {
-
- llvm::APInt ap_element_count(64, element_count);
- if (element_count == 0) {
- return GetType(ast.getIncompleteArrayType(
- ClangUtil::GetQualType(element_type), clang::ArrayType::Normal, 0));
- } else {
- return GetType(ast.getConstantArrayType(
- ClangUtil::GetQualType(element_type), ap_element_count, nullptr,
- clang::ArrayType::Normal, 0));
- }
- }
- }
- return CompilerType();
-}
-
-CompilerType ClangASTContext::CreateStructForIdentifier(
- ConstString type_name,
- const std::initializer_list<std::pair<const char *, CompilerType>>
- &type_fields,
- bool packed) {
- CompilerType type;
- if (!type_name.IsEmpty() &&
- (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name))
- .IsValid()) {
- lldbassert(0 && "Trying to create a type for an existing name");
- return type;
- }
-
- type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(),
- clang::TTK_Struct, lldb::eLanguageTypeC);
- StartTagDeclarationDefinition(type);
- for (const auto &field : type_fields)
- AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic,
- 0);
- if (packed)
- SetIsPacked(type);
- CompleteTagDeclarationDefinition(type);
- return type;
-}
-
-CompilerType ClangASTContext::GetOrCreateStructForIdentifier(
- ConstString type_name,
- const std::initializer_list<std::pair<const char *, CompilerType>>
- &type_fields,
- bool packed) {
- CompilerType type;
- if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid())
- return type;
-
- return CreateStructForIdentifier(type_name, type_fields, packed);
-}
-
-#pragma mark Enumeration Types
-
-CompilerType
-ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
- const Declaration &decl,
- const CompilerType &integer_clang_type,
- bool is_scoped) {
- // TODO: Do something intelligent with the Declaration object passed in
- // like maybe filling in the SourceLocation with it...
- ASTContext &ast = getASTContext();
-
- // TODO: ask about these...
- // const bool IsFixed = false;
-
- EnumDecl *enum_decl = EnumDecl::Create(
- ast, decl_ctx, SourceLocation(), SourceLocation(),
- name && name[0] ? &ast.Idents.get(name) : nullptr, nullptr,
- is_scoped, // IsScoped
- is_scoped, // IsScopedUsingClassTag
- false); // IsFixed
-
- if (enum_decl) {
- if (decl_ctx)
- decl_ctx->addDecl(enum_decl);
-
- // TODO: check if we should be setting the promotion type too?
- enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type));
-
- enum_decl->setAccess(AS_public); // TODO respect what's in the debug info
-
- return GetType(ast.getTagDeclType(enum_decl));
- }
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetIntTypeFromBitSize(size_t bit_size,
- bool is_signed) {
- clang::ASTContext &ast = getASTContext();
-
- if (is_signed) {
- if (bit_size == ast.getTypeSize(ast.SignedCharTy))
- return GetType(ast.SignedCharTy);
-
- if (bit_size == ast.getTypeSize(ast.ShortTy))
- return GetType(ast.ShortTy);
-
- if (bit_size == ast.getTypeSize(ast.IntTy))
- return GetType(ast.IntTy);
-
- if (bit_size == ast.getTypeSize(ast.LongTy))
- return GetType(ast.LongTy);
-
- if (bit_size == ast.getTypeSize(ast.LongLongTy))
- return GetType(ast.LongLongTy);
-
- if (bit_size == ast.getTypeSize(ast.Int128Ty))
- return GetType(ast.Int128Ty);
- } else {
- if (bit_size == ast.getTypeSize(ast.UnsignedCharTy))
- return GetType(ast.UnsignedCharTy);
-
- if (bit_size == ast.getTypeSize(ast.UnsignedShortTy))
- return GetType(ast.UnsignedShortTy);
-
- if (bit_size == ast.getTypeSize(ast.UnsignedIntTy))
- return GetType(ast.UnsignedIntTy);
-
- if (bit_size == ast.getTypeSize(ast.UnsignedLongTy))
- return GetType(ast.UnsignedLongTy);
-
- if (bit_size == ast.getTypeSize(ast.UnsignedLongLongTy))
- return GetType(ast.UnsignedLongLongTy);
-
- if (bit_size == ast.getTypeSize(ast.UnsignedInt128Ty))
- return GetType(ast.UnsignedInt128Ty);
- }
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetPointerSizedIntType(bool is_signed) {
- return GetIntTypeFromBitSize(
- getASTContext().getTypeSize(getASTContext().VoidPtrTy), is_signed);
-}
-
-void ClangASTContext::DumpDeclContextHiearchy(clang::DeclContext *decl_ctx) {
- if (decl_ctx) {
- DumpDeclContextHiearchy(decl_ctx->getParent());
-
- clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx);
- if (named_decl) {
- printf("%20s: %s\n", decl_ctx->getDeclKindName(),
- named_decl->getDeclName().getAsString().c_str());
- } else {
- printf("%20s\n", decl_ctx->getDeclKindName());
- }
- }
-}
-
-void ClangASTContext::DumpDeclHiearchy(clang::Decl *decl) {
- if (decl == nullptr)
- return;
- DumpDeclContextHiearchy(decl->getDeclContext());
-
- clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl);
- if (record_decl) {
- printf("%20s: %s%s\n", decl->getDeclKindName(),
- record_decl->getDeclName().getAsString().c_str(),
- record_decl->isInjectedClassName() ? " (injected class name)" : "");
-
- } else {
- clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl);
- if (named_decl) {
- printf("%20s: %s\n", decl->getDeclKindName(),
- named_decl->getDeclName().getAsString().c_str());
- } else {
- printf("%20s\n", decl->getDeclKindName());
- }
- }
-}
-
-bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl,
- clang::Decl *rhs_decl) {
- if (lhs_decl && rhs_decl) {
- // Make sure the decl kinds match first
- const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind();
- const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind();
-
- if (lhs_decl_kind == rhs_decl_kind) {
- // Now check that the decl contexts kinds are all equivalent before we
- // have to check any names of the decl contexts...
- clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
- clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
- if (lhs_decl_ctx && rhs_decl_ctx) {
- while (true) {
- if (lhs_decl_ctx && rhs_decl_ctx) {
- const clang::Decl::Kind lhs_decl_ctx_kind =
- lhs_decl_ctx->getDeclKind();
- const clang::Decl::Kind rhs_decl_ctx_kind =
- rhs_decl_ctx->getDeclKind();
- if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) {
- lhs_decl_ctx = lhs_decl_ctx->getParent();
- rhs_decl_ctx = rhs_decl_ctx->getParent();
-
- if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr)
- break;
- } else
- return false;
- } else
- return false;
- }
-
- // Now make sure the name of the decls match
- clang::NamedDecl *lhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(lhs_decl);
- clang::NamedDecl *rhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(rhs_decl);
- if (lhs_named_decl && rhs_named_decl) {
- clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
- clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
- if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
- if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
- return false;
- } else
- return false;
- } else
- return false;
-
- // We know that the decl context kinds all match, so now we need to
- // make sure the names match as well
- lhs_decl_ctx = lhs_decl->getDeclContext();
- rhs_decl_ctx = rhs_decl->getDeclContext();
- while (true) {
- switch (lhs_decl_ctx->getDeclKind()) {
- case clang::Decl::TranslationUnit:
- // We don't care about the translation unit names
- return true;
- default: {
- clang::NamedDecl *lhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx);
- clang::NamedDecl *rhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx);
- if (lhs_named_decl && rhs_named_decl) {
- clang::DeclarationName lhs_decl_name =
- lhs_named_decl->getDeclName();
- clang::DeclarationName rhs_decl_name =
- rhs_named_decl->getDeclName();
- if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
- if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
- return false;
- } else
- return false;
- } else
- return false;
- } break;
- }
- lhs_decl_ctx = lhs_decl_ctx->getParent();
- rhs_decl_ctx = rhs_decl_ctx->getParent();
- }
- }
- }
- }
- return false;
-}
-bool ClangASTContext::GetCompleteDecl(clang::ASTContext *ast,
- clang::Decl *decl) {
- if (!decl)
- return false;
-
- ExternalASTSource *ast_source = ast->getExternalSource();
-
- if (!ast_source)
- return false;
-
- if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) {
- if (tag_decl->isCompleteDefinition())
- return true;
-
- if (!tag_decl->hasExternalLexicalStorage())
- return false;
-
- ast_source->CompleteType(tag_decl);
-
- return !tag_decl->getTypeForDecl()->isIncompleteType();
- } else if (clang::ObjCInterfaceDecl *objc_interface_decl =
- llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) {
- if (objc_interface_decl->getDefinition())
- return true;
-
- if (!objc_interface_decl->hasExternalLexicalStorage())
- return false;
-
- ast_source->CompleteType(objc_interface_decl);
-
- return !objc_interface_decl->getTypeForDecl()->isIncompleteType();
- } else {
- return false;
- }
-}
-
-void ClangASTContext::SetMetadataAsUserID(const clang::Decl *decl,
- user_id_t user_id) {
- ClangASTMetadata meta_data;
- meta_data.SetUserID(user_id);
- SetMetadata(decl, meta_data);
-}
-
-void ClangASTContext::SetMetadataAsUserID(const clang::Type *type,
- user_id_t user_id) {
- ClangASTMetadata meta_data;
- meta_data.SetUserID(user_id);
- SetMetadata(type, meta_data);
-}
-
-void ClangASTContext::SetMetadata(const clang::Decl *object,
- ClangASTMetadata &metadata) {
- m_decl_metadata[object] = metadata;
-}
-
-void ClangASTContext::SetMetadata(const clang::Type *object,
- ClangASTMetadata &metadata) {
- m_type_metadata[object] = metadata;
-}
-
-ClangASTMetadata *ClangASTContext::GetMetadata(const clang::Decl *object) {
- auto It = m_decl_metadata.find(object);
- if (It != m_decl_metadata.end())
- return &It->second;
- return nullptr;
-}
-
-ClangASTMetadata *ClangASTContext::GetMetadata(const clang::Type *object) {
- auto It = m_type_metadata.find(object);
- if (It != m_type_metadata.end())
- return &It->second;
- return nullptr;
-}
-
-bool ClangASTContext::SetTagTypeKind(clang::QualType tag_qual_type,
- int kind) const {
- const clang::Type *clang_type = tag_qual_type.getTypePtr();
- if (clang_type) {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
- if (tag_type) {
- clang::TagDecl *tag_decl =
- llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
- if (tag_decl) {
- tag_decl->setTagKind((clang::TagDecl::TagKind)kind);
- return true;
- }
- }
- }
- return false;
-}
-
-bool ClangASTContext::SetDefaultAccessForRecordFields(
- clang::RecordDecl *record_decl, int default_accessibility,
- int *assigned_accessibilities, size_t num_assigned_accessibilities) {
- if (record_decl) {
- uint32_t field_idx;
- clang::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((clang::AccessSpecifier)default_accessibility);
- }
- return true;
- }
- return false;
-}
-
-clang::DeclContext *
-ClangASTContext::GetDeclContextForType(const CompilerType &type) {
- return GetDeclContextForType(ClangUtil::GetQualType(type));
-}
-
-/// Aggressively desugar the provided type, skipping past various kinds of
-/// syntactic sugar and other constructs one typically wants to ignore.
-/// The \p mask argument allows one to skip certain kinds of simplifications,
-/// when one wishes to handle a certain kind of type directly.
-static QualType
-RemoveWrappingTypes(QualType type, ArrayRef<clang::Type::TypeClass> mask = {}) {
- while (true) {
- if (find(mask, type->getTypeClass()) != mask.end())
- return type;
- switch (type->getTypeClass()) {
- // This is not fully correct as _Atomic is more than sugar, but it is
- // sufficient for the purposes we care about.
- case clang::Type::Atomic:
- type = cast<clang::AtomicType>(type)->getValueType();
- break;
- case clang::Type::Auto:
- case clang::Type::Decltype:
- case clang::Type::Elaborated:
- case clang::Type::Paren:
- case clang::Type::Typedef:
- case clang::Type::TypeOf:
- case clang::Type::TypeOfExpr:
- type = type->getLocallyUnqualifiedSingleStepDesugaredType();
- break;
- default:
- return type;
- }
- }
-}
-
-clang::DeclContext *
-ClangASTContext::GetDeclContextForType(clang::QualType type) {
- if (type.isNull())
- return nullptr;
-
- clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::ObjCInterface:
- return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())
- ->getInterface();
- case clang::Type::ObjCObjectPointer:
- return GetDeclContextForType(
- llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
- ->getPointeeType());
- case clang::Type::Record:
- return llvm::cast<clang::RecordType>(qual_type)->getDecl();
- case clang::Type::Enum:
- return llvm::cast<clang::EnumType>(qual_type)->getDecl();
- default:
- break;
- }
- // No DeclContext in this type...
- return nullptr;
-}
-
-static bool GetCompleteQualType(clang::ASTContext *ast,
- clang::QualType qual_type,
- bool allow_completion = true) {
- qual_type = RemoveWrappingTypes(qual_type);
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::ConstantArray:
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray: {
- const clang::ArrayType *array_type =
- llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
-
- if (array_type)
- return GetCompleteQualType(ast, array_type->getElementType(),
- allow_completion);
- } break;
- case clang::Type::Record: {
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- if (cxx_record_decl->hasExternalLexicalStorage()) {
- const bool is_complete = cxx_record_decl->isCompleteDefinition();
- const bool fields_loaded =
- cxx_record_decl->hasLoadedFieldsFromExternalStorage();
- if (is_complete && fields_loaded)
- return true;
-
- if (!allow_completion)
- return false;
-
- // Call the field_begin() accessor to for it to use the external source
- // to load the fields...
- clang::ExternalASTSource *external_ast_source =
- ast->getExternalSource();
- if (external_ast_source) {
- external_ast_source->CompleteType(cxx_record_decl);
- if (cxx_record_decl->isCompleteDefinition()) {
- cxx_record_decl->field_begin();
- cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
- }
- }
- }
- }
- const clang::TagType *tag_type =
- llvm::cast<clang::TagType>(qual_type.getTypePtr());
- return !tag_type->isIncompleteType();
- } break;
-
- case clang::Type::Enum: {
- const clang::TagType *tag_type =
- llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl) {
- if (tag_decl->getDefinition())
- return true;
-
- if (!allow_completion)
- return false;
-
- if (tag_decl->hasExternalLexicalStorage()) {
- if (ast) {
- clang::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 =
- llvm::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) {
- clang::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::Attributed:
- return GetCompleteQualType(
- ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(),
- allow_completion);
-
- default:
- break;
- }
-
- return true;
-}
-
-static clang::ObjCIvarDecl::AccessControl
-ConvertAccessTypeToObjCIvarAccessControl(AccessType access) {
- switch (access) {
- case eAccessNone:
- return clang::ObjCIvarDecl::None;
- case eAccessPublic:
- return clang::ObjCIvarDecl::Public;
- case eAccessPrivate:
- return clang::ObjCIvarDecl::Private;
- case eAccessProtected:
- return clang::ObjCIvarDecl::Protected;
- case eAccessPackage:
- return clang::ObjCIvarDecl::Package;
- }
- return clang::ObjCIvarDecl::None;
-}
-
-// Tests
-
-bool ClangASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(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;
- default:
- break;
- }
- // The clang type does have a value
- return false;
-}
-
-bool ClangASTContext::IsAnonymousType(lldb::opaque_compiler_type_t type) {
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record: {
- if (const clang::RecordType *record_type =
- llvm::dyn_cast_or_null<clang::RecordType>(
- qual_type.getTypePtrOrNull())) {
- if (const clang::RecordDecl *record_decl = record_type->getDecl()) {
- return record_decl->isAnonymousStructOrUnion();
- }
- }
- break;
- }
- default:
- break;
- }
- // The clang type does have a value
- return false;
-}
-
-bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type_ptr,
- uint64_t *size, bool *is_incomplete) {
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- default:
- break;
-
- case clang::Type::ConstantArray:
- if (element_type_ptr)
- element_type_ptr->SetCompilerType(
- this, llvm::cast<clang::ConstantArrayType>(qual_type)
- ->getElementType()
- .getAsOpaquePtr());
- if (size)
- *size = llvm::cast<clang::ConstantArrayType>(qual_type)
- ->getSize()
- .getLimitedValue(ULLONG_MAX);
- if (is_incomplete)
- *is_incomplete = false;
- return true;
-
- case clang::Type::IncompleteArray:
- if (element_type_ptr)
- element_type_ptr->SetCompilerType(
- this, llvm::cast<clang::IncompleteArrayType>(qual_type)
- ->getElementType()
- .getAsOpaquePtr());
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = true;
- return true;
-
- case clang::Type::VariableArray:
- if (element_type_ptr)
- element_type_ptr->SetCompilerType(
- this, llvm::cast<clang::VariableArrayType>(qual_type)
- ->getElementType()
- .getAsOpaquePtr());
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = false;
- return true;
-
- case clang::Type::DependentSizedArray:
- if (element_type_ptr)
- element_type_ptr->SetCompilerType(
- this, llvm::cast<clang::DependentSizedArrayType>(qual_type)
- ->getElementType()
- .getAsOpaquePtr());
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = false;
- return true;
- }
- if (element_type_ptr)
- element_type_ptr->Clear();
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = false;
- return false;
-}
-
-bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) {
- clang::QualType qual_type(GetCanonicalQualType(type));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Vector: {
- const clang::VectorType *vector_type =
- qual_type->getAs<clang::VectorType>();
- if (vector_type) {
- if (size)
- *size = vector_type->getNumElements();
- if (element_type)
- *element_type = GetType(vector_type->getElementType());
- }
- return true;
- } break;
- case clang::Type::ExtVector: {
- const clang::ExtVectorType *ext_vector_type =
- qual_type->getAs<clang::ExtVectorType>();
- if (ext_vector_type) {
- if (size)
- *size = ext_vector_type->getNumElements();
- if (element_type)
- *element_type =
- CompilerType(this, ext_vector_type->getElementType().getAsOpaquePtr());
- }
- return true;
- }
- default:
- break;
- }
- return false;
-}
-
-bool ClangASTContext::IsRuntimeGeneratedType(
- lldb::opaque_compiler_type_t type) {
- clang::DeclContext *decl_ctx = GetDeclContextForType(GetQualType(type));
- if (!decl_ctx)
- return false;
-
- if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx))
- return false;
-
- clang::ObjCInterfaceDecl *result_iface_decl =
- llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
-
- ClangASTMetadata *ast_metadata = GetMetadata(result_iface_decl);
- if (!ast_metadata)
- return false;
- return (ast_metadata->GetISAPtr() != 0);
-}
-
-bool ClangASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
- return GetQualType(type).getUnqualifiedType()->isCharType();
-}
-
-bool ClangASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
- const bool allow_completion = false;
- return GetCompleteQualType(&getASTContext(), GetQualType(type),
- allow_completion);
-}
-
-bool ClangASTContext::IsConst(lldb::opaque_compiler_type_t type) {
- return GetQualType(type).isConstQualified();
-}
-
-bool ClangASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) {
- CompilerType pointee_or_element_clang_type;
- length = 0;
- Flags type_flags(GetTypeInfo(type, &pointee_or_element_clang_type));
-
- if (!pointee_or_element_clang_type.IsValid())
- return false;
-
- if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer)) {
- if (pointee_or_element_clang_type.IsCharType()) {
- 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 = llvm::cast<clang::ConstantArrayType>(
- GetCanonicalQualType(type).getTypePtr())
- ->getSize()
- .getLimitedValue();
- }
- return true;
- }
- }
- return false;
-}
-
-bool ClangASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr) {
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
- if (qual_type->isFunctionType()) {
- if (is_variadic_ptr) {
- const clang::FunctionProtoType *function_proto_type =
- llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (function_proto_type)
- *is_variadic_ptr = function_proto_type->isVariadic();
- else
- *is_variadic_ptr = false;
- }
- return true;
- }
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- default:
- break;
- case clang::Type::LValueReference:
- case clang::Type::RValueReference: {
- const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- if (reference_type)
- return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(),
- nullptr);
- } break;
- }
- }
- return false;
-}
-
-// Used to detect "Homogeneous Floating-point Aggregates"
-uint32_t
-ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) {
- if (!type)
- return 0;
-
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- if (cxx_record_decl->getNumBases() || cxx_record_decl->isDynamicClass())
- return 0;
- }
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- if (record_type) {
- const clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl) {
- // We are looking for a structure that contains only floating point
- // types
- clang::RecordDecl::field_iterator field_pos,
- field_end = record_decl->field_end();
- uint32_t num_fields = 0;
- bool is_hva = false;
- bool is_hfa = false;
- clang::QualType base_qual_type;
- uint64_t base_bitwidth = 0;
- for (field_pos = record_decl->field_begin(); field_pos != field_end;
- ++field_pos) {
- clang::QualType field_qual_type = field_pos->getType();
- uint64_t field_bitwidth = getASTContext().getTypeSize(qual_type);
- if (field_qual_type->isFloatingType()) {
- if (field_qual_type->isComplexType())
- return 0;
- else {
- if (num_fields == 0)
- base_qual_type = field_qual_type;
- else {
- if (is_hva)
- return 0;
- is_hfa = true;
- if (field_qual_type.getTypePtr() !=
- base_qual_type.getTypePtr())
- return 0;
- }
- }
- } else if (field_qual_type->isVectorType() ||
- field_qual_type->isExtVectorType()) {
- if (num_fields == 0) {
- base_qual_type = field_qual_type;
- base_bitwidth = field_bitwidth;
- } else {
- if (is_hfa)
- return 0;
- is_hva = true;
- if (base_bitwidth != field_bitwidth)
- return 0;
- if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
- return 0;
- }
- } else
- return 0;
- ++num_fields;
- }
- if (base_type_ptr)
- *base_type_ptr = CompilerType(this, base_qual_type.getAsOpaquePtr());
- return num_fields;
- }
- }
- }
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-size_t ClangASTContext::GetNumberOfFunctionArguments(
- lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::FunctionProtoType *func =
- llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (func)
- return func->getNumParams();
- }
- return 0;
-}
-
-CompilerType
-ClangASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) {
- if (type) {
- clang::QualType qual_type(GetQualType(type));
- const clang::FunctionProtoType *func =
- llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (func) {
- if (index < func->getNumParams())
- return CompilerType(this, func->getParamType(index).getAsOpaquePtr());
- }
- }
- return CompilerType();
-}
-
-bool ClangASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
- if (qual_type->isFunctionPointerType())
- return true;
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- default:
- break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference: {
- const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- if (reference_type)
- return IsFunctionPointerType(
- reference_type->getPointeeType().getAsOpaquePtr());
- } break;
- }
- }
- return false;
-}
-
-bool ClangASTContext::IsBlockPointerType(
- lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) {
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
- if (qual_type->isBlockPointerType()) {
- if (function_pointer_type_ptr) {
- const clang::BlockPointerType *block_pointer_type =
- qual_type->getAs<clang::BlockPointerType>();
- QualType pointee_type = block_pointer_type->getPointeeType();
- QualType function_pointer_type = m_ast_up->getPointerType(pointee_type);
- *function_pointer_type_ptr =
- CompilerType(this, function_pointer_type.getAsOpaquePtr());
- }
- return true;
- }
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- default:
- break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference: {
- const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- if (reference_type)
- return IsBlockPointerType(
- reference_type->getPointeeType().getAsOpaquePtr(),
- function_pointer_type_ptr);
- } break;
- }
- }
- return false;
-}
-
-bool ClangASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) {
- if (!type)
- return false;
-
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::BuiltinType *builtin_type =
- llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
-
- if (builtin_type) {
- if (builtin_type->isInteger()) {
- is_signed = builtin_type->isSignedInteger();
- return true;
- }
- }
-
- return false;
-}
-
-bool ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type,
- bool &is_signed) {
- if (type) {
- const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(
- GetCanonicalQualType(type)->getCanonicalTypeInternal());
-
- if (enum_type) {
- IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(),
- is_signed);
- return true;
- }
- }
-
- return false;
-}
-
-bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type) {
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Builtin:
- switch (llvm::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 (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- case clang::Type::BlockPointer:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::BlockPointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- case clang::Type::Pointer:
- if (pointee_type)
- pointee_type->SetCompilerType(this,
- llvm::cast<clang::PointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- case clang::Type::MemberPointer:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::MemberPointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- default:
- break;
- }
- }
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool ClangASTContext::IsPointerOrReferenceType(
- lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Builtin:
- switch (llvm::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 (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
- ->getPointeeType().getAsOpaquePtr());
- return true;
- case clang::Type::BlockPointer:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::BlockPointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- case clang::Type::Pointer:
- if (pointee_type)
- pointee_type->SetCompilerType(this,
- llvm::cast<clang::PointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- case clang::Type::MemberPointer:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::MemberPointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- case clang::Type::LValueReference:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::LValueReferenceType>(qual_type)
- ->desugar()
- .getAsOpaquePtr());
- return true;
- case clang::Type::RValueReference:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::RValueReferenceType>(qual_type)
- ->desugar()
- .getAsOpaquePtr());
- return true;
- default:
- break;
- }
- }
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool ClangASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type,
- bool *is_rvalue) {
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
- switch (type_class) {
- case clang::Type::LValueReference:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::LValueReferenceType>(qual_type)
- ->desugar()
- .getAsOpaquePtr());
- if (is_rvalue)
- *is_rvalue = false;
- return true;
- case clang::Type::RValueReference:
- if (pointee_type)
- pointee_type->SetCompilerType(
- this, llvm::cast<clang::RValueReferenceType>(qual_type)
- ->desugar()
- .getAsOpaquePtr());
- if (is_rvalue)
- *is_rvalue = true;
- return true;
-
- default:
- break;
- }
- }
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool ClangASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
- uint32_t &count, bool &is_complex) {
- if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
-
- if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(
- qual_type->getCanonicalTypeInternal())) {
- clang::BuiltinType::Kind kind = BT->getKind();
- if (kind >= clang::BuiltinType::Float &&
- kind <= clang::BuiltinType::LongDouble) {
- count = 1;
- is_complex = false;
- return true;
- }
- } else if (const clang::ComplexType *CT =
- llvm::dyn_cast<clang::ComplexType>(
- qual_type->getCanonicalTypeInternal())) {
- if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count,
- is_complex)) {
- count = 2;
- is_complex = true;
- return true;
- }
- } else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(
- qual_type->getCanonicalTypeInternal())) {
- if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count,
- is_complex)) {
- count = VT->getNumElements();
- is_complex = false;
- return true;
- }
- }
- }
- count = 0;
- is_complex = false;
- return false;
-}
-
-bool ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
-
- clang::QualType qual_type(GetQualType(type));
- const clang::TagType *tag_type =
- llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- return tag_decl->isCompleteDefinition();
- return false;
- } else {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
- if (class_interface_decl)
- return class_interface_decl->getDefinition() != nullptr;
- return false;
- }
- }
- return true;
-}
-
-bool ClangASTContext::IsObjCClassType(const CompilerType &type) {
- if (ClangUtil::IsClangType(type)) {
- clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
-
- const clang::ObjCObjectPointerType *obj_pointer_type =
- llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
-
- if (obj_pointer_type)
- return obj_pointer_type->isObjCClassType();
- }
- return false;
-}
-
-bool ClangASTContext::IsObjCObjectOrInterfaceType(const CompilerType &type) {
- if (ClangUtil::IsClangType(type))
- return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
- return false;
-}
-
-bool ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- return (type_class == clang::Type::Record);
-}
-
-bool ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- return (type_class == clang::Type::Enum);
-}
-
-bool ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl) {
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- return cxx_record_decl->isPolymorphic();
- }
- }
- break;
-
- default:
- break;
- }
- }
- return false;
-}
-
-bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
- CompilerType *dynamic_pointee_type,
- bool check_cplusplus,
- bool check_objc) {
- clang::QualType pointee_qual_type;
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- bool success = false;
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Builtin:
- if (check_objc &&
- llvm::cast<clang::BuiltinType>(qual_type)->getKind() ==
- clang::BuiltinType::ObjCId) {
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetCompilerType(this, type);
- return true;
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (check_objc) {
- if (auto objc_pointee_type =
- qual_type->getPointeeType().getTypePtrOrNull()) {
- if (auto objc_object_type =
- llvm::dyn_cast_or_null<clang::ObjCObjectType>(
- objc_pointee_type)) {
- if (objc_object_type->isObjCClass())
- return false;
- }
- }
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetCompilerType(
- this, llvm::cast<clang::ObjCObjectPointerType>(qual_type)
- ->getPointeeType()
- .getAsOpaquePtr());
- return true;
- }
- break;
-
- case clang::Type::Pointer:
- pointee_qual_type =
- llvm::cast<clang::PointerType>(qual_type)->getPointeeType();
- success = true;
- break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- pointee_qual_type =
- llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType();
- success = true;
- break;
-
- 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.getCanonicalType()->getTypeClass();
- switch (pointee_type_class) {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind()) {
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::Void:
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetCompilerType(
- this, pointee_qual_type.getAsOpaquePtr());
- return true;
- default:
- break;
- }
- break;
-
- case clang::Type::Record:
- if (check_cplusplus) {
- clang::CXXRecordDecl *cxx_record_decl =
- pointee_qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- bool is_complete = cxx_record_decl->isCompleteDefinition();
-
- if (is_complete)
- success = cxx_record_decl->isDynamicClass();
- else {
- ClangASTMetadata *metadata = GetMetadata(cxx_record_decl);
- if (metadata)
- success = metadata->GetIsDynamicCXXType();
- else {
- is_complete = GetType(pointee_qual_type).GetCompleteType();
- if (is_complete)
- success = cxx_record_decl->isDynamicClass();
- else
- success = false;
- }
- }
-
- if (success) {
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetCompilerType(
- this, 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->SetCompilerType(
- this, pointee_qual_type.getAsOpaquePtr());
- return true;
- }
- break;
-
- default:
- break;
- }
- }
- }
- if (dynamic_pointee_type)
- dynamic_pointee_type->Clear();
- return false;
-}
-
-bool ClangASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
-
- return (GetTypeInfo(type, nullptr) & eTypeIsScalar) != 0;
-}
-
-bool ClangASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- return GetQualType(type)->getTypeClass() == clang::Type::Typedef;
-}
-
-bool ClangASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- return GetCanonicalQualType(type)->isVoidType();
-}
-
-bool ClangASTContext::CanPassInRegisters(const CompilerType &type) {
- if (auto *record_decl =
- ClangASTContext::GetAsRecordDecl(type)) {
- return record_decl->canPassInRegisters();
- }
- return false;
-}
-
-bool ClangASTContext::SupportsLanguage(lldb::LanguageType language) {
- return ClangASTContextSupportsLanguage(language);
-}
-
-Optional<std::string>
-ClangASTContext::GetCXXClassName(const CompilerType &type) {
- if (!type)
- return llvm::None;
-
- clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
- if (qual_type.isNull())
- return llvm::None;
-
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (!cxx_record_decl)
- return llvm::None;
-
- return std::string(cxx_record_decl->getIdentifier()->getNameStart());
-}
-
-bool ClangASTContext::IsCXXClassType(const CompilerType &type) {
- if (!type)
- return false;
-
- clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
- return !qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr;
-}
-
-bool ClangASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type);
- if (tag_type)
- return tag_type->isBeingDefined();
- return false;
-}
-
-bool ClangASTContext::IsObjCObjectPointerType(const CompilerType &type,
- CompilerType *class_type_ptr) {
- if (!ClangUtil::IsClangType(type))
- return false;
-
- clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
-
- if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) {
- if (class_type_ptr) {
- if (!qual_type->isObjCClassType() && !qual_type->isObjCIdType()) {
- const clang::ObjCObjectPointerType *obj_pointer_type =
- llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
- if (obj_pointer_type == nullptr)
- class_type_ptr->Clear();
- else
- class_type_ptr->SetCompilerType(
- type.GetTypeSystem(),
- clang::QualType(obj_pointer_type->getInterfaceType(), 0)
- .getAsOpaquePtr());
- }
- }
- return true;
- }
- if (class_type_ptr)
- class_type_ptr->Clear();
- return false;
-}
-
-// Type Completion
-
-bool ClangASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- const bool allow_completion = true;
- return GetCompleteQualType(&getASTContext(), GetQualType(type),
- allow_completion);
-}
-
-ConstString ClangASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
- std::string type_name;
- if (type) {
- clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
- clang::QualType qual_type(GetQualType(type));
- printing_policy.SuppressTagKeyword = true;
- const clang::TypedefType *typedef_type =
- qual_type->getAs<clang::TypedefType>();
- if (typedef_type) {
- const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
- type_name = typedef_decl->getQualifiedNameAsString();
- } else {
- type_name = qual_type.getAsString(printing_policy);
- }
- }
- return ConstString(type_name);
-}
-
-uint32_t
-ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_clang_type) {
- if (!type)
- return 0;
-
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->Clear();
-
- clang::QualType qual_type =
- RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Attributed:
- return GetTypeInfo(
- qual_type->getAs<clang::AttributedType>()
- ->getModifiedType().getAsOpaquePtr(),
- pointee_or_element_clang_type);
- case clang::Type::Builtin: {
- const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(
- qual_type->getCanonicalTypeInternal());
-
- uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
- switch (builtin_type->getKind()) {
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetCompilerType(
- this, getASTContext().ObjCBuiltinClassTy.getAsOpaquePtr());
- builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
- break;
-
- case clang::BuiltinType::ObjCSel:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetCompilerType(
- this, getASTContext().CharTy.getAsOpaquePtr());
- builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
- 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:
- builtin_type_flags |= eTypeIsScalar;
- if (builtin_type->isInteger()) {
- builtin_type_flags |= eTypeIsInteger;
- if (builtin_type->isSignedInteger())
- builtin_type_flags |= eTypeIsSigned;
- } else if (builtin_type->isFloatingPoint())
- builtin_type_flags |= eTypeIsFloat;
- break;
- default:
- break;
- }
- return builtin_type_flags;
- }
-
- case clang::Type::BlockPointer:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetCompilerType(
- this, qual_type->getPointeeType().getAsOpaquePtr());
- return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock;
-
- case clang::Type::Complex: {
- uint32_t complex_type_flags =
- eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex;
- const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(
- qual_type->getCanonicalTypeInternal());
- if (complex_type) {
- clang::QualType complex_element_type(complex_type->getElementType());
- if (complex_element_type->isIntegerType())
- complex_type_flags |= eTypeIsFloat;
- else if (complex_element_type->isFloatingType())
- complex_type_flags |= eTypeIsInteger;
- }
- return complex_type_flags;
- } break;
-
- 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->SetCompilerType(
- this, llvm::cast<clang::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::Enum:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetCompilerType(
- this, llvm::cast<clang::EnumType>(qual_type)
- ->getDecl()
- ->getIntegerType()
- .getAsOpaquePtr());
- return eTypeIsEnumeration | eTypeHasValue;
-
- 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->SetCompilerType(
- this, llvm::cast<clang::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->SetCompilerType(
- this, 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->SetCompilerType(
- this, 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 | GetType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType())
- .GetTypeInfo(pointee_or_element_clang_type);
- case clang::Type::UnresolvedUsing:
- return 0;
-
- case clang::Type::ExtVector:
- case clang::Type::Vector: {
- uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector;
- const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(
- qual_type->getCanonicalTypeInternal());
- if (vector_type) {
- if (vector_type->isIntegerType())
- vector_type_flags |= eTypeIsFloat;
- else if (vector_type->isFloatingType())
- vector_type_flags |= eTypeIsInteger;
- }
- return vector_type_flags;
- }
- default:
- return 0;
- }
- return 0;
-}
-
-lldb::LanguageType
-ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
- if (!type)
- return lldb::eLanguageTypeC;
-
- // If the type is a reference, then resolve it to what it refers to first:
- clang::QualType qual_type(GetCanonicalQualType(type).getNonReferenceType());
- if (qual_type->isAnyPointerType()) {
- if (qual_type->isObjCObjectPointerType())
- return lldb::eLanguageTypeObjC;
- if (qual_type->getPointeeCXXRecordDecl())
- return lldb::eLanguageTypeC_plus_plus;
-
- clang::QualType pointee_type(qual_type->getPointeeType());
- if (pointee_type->getPointeeCXXRecordDecl())
- return lldb::eLanguageTypeC_plus_plus;
- if (pointee_type->isObjCObjectOrInterfaceType())
- return lldb::eLanguageTypeObjC;
- if (pointee_type->isObjCClassType())
- return lldb::eLanguageTypeObjC;
- if (pointee_type.getTypePtr() ==
- getASTContext().ObjCBuiltinIdTy.getTypePtr())
- return lldb::eLanguageTypeObjC;
- } else {
- if (qual_type->isObjCObjectOrInterfaceType())
- return lldb::eLanguageTypeObjC;
- if (qual_type->getAsCXXRecordDecl())
- return lldb::eLanguageTypeC_plus_plus;
- switch (qual_type->getTypeClass()) {
- default:
- break;
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
- default:
- case clang::BuiltinType::Void:
- 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:
- break;
-
- case clang::BuiltinType::NullPtr:
- return eLanguageTypeC_plus_plus;
-
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- return eLanguageTypeObjC;
-
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::UnknownAny:
- break;
- }
- break;
- case clang::Type::Typedef:
- return GetType(llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType())
- .GetMinimumLanguage();
- }
- }
- return lldb::eLanguageTypeC;
-}
-
-lldb::TypeClass
-ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
- if (!type)
- return lldb::eTypeClassInvalid;
-
- clang::QualType qual_type =
- RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
-
- switch (qual_type->getTypeClass()) {
- case clang::Type::Atomic:
- case clang::Type::Auto:
- case clang::Type::Decltype:
- case clang::Type::Elaborated:
- case clang::Type::Paren:
- case clang::Type::TypeOf:
- case clang::Type::TypeOfExpr:
- llvm_unreachable("Handled in RemoveWrappingTypes!");
- case clang::Type::UnaryTransform:
- break;
- case clang::Type::FunctionNoProto:
- return lldb::eTypeClassFunction;
- case clang::Type::FunctionProto:
- return lldb::eTypeClassFunction;
- case clang::Type::IncompleteArray:
- return lldb::eTypeClassArray;
- case clang::Type::VariableArray:
- return lldb::eTypeClassArray;
- case clang::Type::ConstantArray:
- return lldb::eTypeClassArray;
- case clang::Type::DependentSizedArray:
- return lldb::eTypeClassArray;
- case clang::Type::DependentSizedExtVector:
- return lldb::eTypeClassVector;
- case clang::Type::DependentVector:
- return lldb::eTypeClassVector;
- case clang::Type::ExtVector:
- return lldb::eTypeClassVector;
- case clang::Type::Vector:
- return lldb::eTypeClassVector;
- case clang::Type::Builtin:
- return lldb::eTypeClassBuiltin;
- case clang::Type::ObjCObjectPointer:
- return lldb::eTypeClassObjCObjectPointer;
- case clang::Type::BlockPointer:
- return lldb::eTypeClassBlockPointer;
- case clang::Type::Pointer:
- return lldb::eTypeClassPointer;
- case clang::Type::LValueReference:
- return lldb::eTypeClassReference;
- case clang::Type::RValueReference:
- return lldb::eTypeClassReference;
- case clang::Type::MemberPointer:
- return lldb::eTypeClassMemberPointer;
- case clang::Type::Complex:
- if (qual_type->isComplexType())
- return lldb::eTypeClassComplexFloat;
- else
- return lldb::eTypeClassComplexInteger;
- case clang::Type::ObjCObject:
- return lldb::eTypeClassObjCObject;
- case clang::Type::ObjCInterface:
- return lldb::eTypeClassObjCInterface;
- case clang::Type::Record: {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl->isUnion())
- return lldb::eTypeClassUnion;
- else if (record_decl->isStruct())
- return lldb::eTypeClassStruct;
- else
- return lldb::eTypeClassClass;
- } break;
- case clang::Type::Enum:
- return lldb::eTypeClassEnumeration;
- case clang::Type::Typedef:
- return lldb::eTypeClassTypedef;
- case clang::Type::UnresolvedUsing:
- break;
-
- case clang::Type::Attributed:
- break;
- case clang::Type::TemplateTypeParm:
- break;
- case clang::Type::SubstTemplateTypeParm:
- break;
- case clang::Type::SubstTemplateTypeParmPack:
- break;
- case clang::Type::InjectedClassName:
- break;
- case clang::Type::DependentName:
- break;
- case clang::Type::DependentTemplateSpecialization:
- break;
- case clang::Type::PackExpansion:
- break;
-
- case clang::Type::TemplateSpecialization:
- break;
- case clang::Type::DeducedTemplateSpecialization:
- break;
- case clang::Type::Pipe:
- break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed:
- break;
- case clang::Type::Adjusted:
- break;
- case clang::Type::ObjCTypeParam:
- break;
-
- case clang::Type::DependentAddressSpace:
- break;
- case clang::Type::MacroQualified:
- break;
- }
- // We don't know hot to display this type...
- return lldb::eTypeClassOther;
-}
-
-unsigned ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
- if (type)
- return GetQualType(type).getQualifiers().getCVRQualifiers();
- return 0;
-}
-
-// Creating related types
-
-CompilerType
-ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride) {
- if (type) {
- clang::QualType qual_type(GetQualType(type));
-
- const clang::Type *array_eletype =
- qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
-
- if (!array_eletype)
- return CompilerType();
-
- CompilerType element_type = GetType(clang::QualType(array_eletype, 0));
-
- // TODO: the real stride will be >= this value.. find the real one!
- if (stride)
- if (Optional<uint64_t> size = element_type.GetByteSize(nullptr))
- *stride = *size;
-
- return element_type;
- }
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type,
- uint64_t size) {
- if (type) {
- clang::QualType qual_type(GetCanonicalQualType(type));
- clang::ASTContext &ast_ctx = getASTContext();
- if (size != 0)
- return GetType(ast_ctx.getConstantArrayType(
- qual_type, llvm::APInt(64, size), nullptr,
- clang::ArrayType::ArraySizeModifier::Normal, 0));
- else
- return GetType(ast_ctx.getIncompleteArrayType(
- qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0));
- }
-
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
- if (type)
- return GetType(GetCanonicalQualType(type));
- return CompilerType();
-}
-
-static clang::QualType GetFullyUnqualifiedType_Impl(clang::ASTContext *ast,
- clang::QualType qual_type) {
- if (qual_type->isPointerType())
- qual_type = ast->getPointerType(
- GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType()));
- else
- qual_type = qual_type.getUnqualifiedType();
- qual_type.removeLocalConst();
- qual_type.removeLocalRestrict();
- qual_type.removeLocalVolatile();
- return qual_type;
-}
-
-CompilerType
-ClangASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
- if (type)
- return GetType(
- GetFullyUnqualifiedType_Impl(&getASTContext(), GetQualType(type)));
- return CompilerType();
-}
-
-int ClangASTContext::GetFunctionArgumentCount(
- lldb::opaque_compiler_type_t type) {
- if (type) {
- const clang::FunctionProtoType *func =
- llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type));
- if (func)
- return func->getNumParams();
- }
- return -1;
-}
-
-CompilerType ClangASTContext::GetFunctionArgumentTypeAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx) {
- if (type) {
- const clang::FunctionProtoType *func =
- llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type));
- if (func) {
- const uint32_t num_args = func->getNumParams();
- if (idx < num_args)
- return GetType(func->getParamType(idx));
- }
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type(GetQualType(type));
- const clang::FunctionProtoType *func =
- llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (func)
- return GetType(func->getReturnType());
- }
- return CompilerType();
-}
-
-size_t
-ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
- size_t num_functions = 0;
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- switch (qual_type->getTypeClass()) {
- case clang::Type::Record:
- if (GetCompleteQualType(&getASTContext(), qual_type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- num_functions = std::distance(cxx_record_decl->method_begin(),
- cxx_record_decl->method_end());
- }
- break;
-
- case clang::Type::ObjCObjectPointer: {
- const clang::ObjCObjectPointerType *objc_class_type =
- qual_type->getAs<clang::ObjCObjectPointerType>();
- const clang::ObjCInterfaceType *objc_interface_type =
- objc_class_type->getInterfaceType();
- if (objc_interface_type &&
- GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
- const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_interface_type->getDecl();
- if (class_interface_decl) {
- num_functions = std::distance(class_interface_decl->meth_begin(),
- class_interface_decl->meth_end());
- }
- }
- break;
- }
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
- if (class_interface_decl)
- num_functions = std::distance(class_interface_decl->meth_begin(),
- class_interface_decl->meth_end());
- }
- }
- break;
-
- default:
- break;
- }
- }
- return num_functions;
-}
-
-TypeMemberFunctionImpl
-ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) {
- std::string name;
- MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown);
- CompilerType clang_type;
- CompilerDecl clang_decl;
- if (type) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- switch (qual_type->getTypeClass()) {
- case clang::Type::Record:
- if (GetCompleteQualType(&getASTContext(), qual_type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl) {
- auto method_iter = cxx_record_decl->method_begin();
- auto method_end = cxx_record_decl->method_end();
- if (idx <
- static_cast<size_t>(std::distance(method_iter, method_end))) {
- std::advance(method_iter, idx);
- clang::CXXMethodDecl *cxx_method_decl =
- method_iter->getCanonicalDecl();
- if (cxx_method_decl) {
- name = cxx_method_decl->getDeclName().getAsString();
- if (cxx_method_decl->isStatic())
- kind = lldb::eMemberFunctionKindStaticMethod;
- else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl))
- kind = lldb::eMemberFunctionKindConstructor;
- else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl))
- kind = lldb::eMemberFunctionKindDestructor;
- else
- kind = lldb::eMemberFunctionKindInstanceMethod;
- clang_type = GetType(cxx_method_decl->getType());
- clang_decl = CompilerDecl(this, cxx_method_decl);
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer: {
- const clang::ObjCObjectPointerType *objc_class_type =
- qual_type->getAs<clang::ObjCObjectPointerType>();
- const clang::ObjCInterfaceType *objc_interface_type =
- objc_class_type->getInterfaceType();
- if (objc_interface_type &&
- GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
- const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_interface_type->getDecl();
- if (class_interface_decl) {
- auto method_iter = class_interface_decl->meth_begin();
- auto method_end = class_interface_decl->meth_end();
- if (idx <
- static_cast<size_t>(std::distance(method_iter, method_end))) {
- std::advance(method_iter, idx);
- clang::ObjCMethodDecl *objc_method_decl =
- method_iter->getCanonicalDecl();
- if (objc_method_decl) {
- clang_decl = CompilerDecl(this, objc_method_decl);
- name = objc_method_decl->getSelector().getAsString();
- if (objc_method_decl->isClassMethod())
- kind = lldb::eMemberFunctionKindStaticMethod;
- else
- kind = lldb::eMemberFunctionKindInstanceMethod;
- }
- }
- }
- }
- break;
- }
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
- if (class_interface_decl) {
- auto method_iter = class_interface_decl->meth_begin();
- auto method_end = class_interface_decl->meth_end();
- if (idx <
- static_cast<size_t>(std::distance(method_iter, method_end))) {
- std::advance(method_iter, idx);
- clang::ObjCMethodDecl *objc_method_decl =
- method_iter->getCanonicalDecl();
- if (objc_method_decl) {
- clang_decl = CompilerDecl(this, objc_method_decl);
- name = objc_method_decl->getSelector().getAsString();
- if (objc_method_decl->isClassMethod())
- kind = lldb::eMemberFunctionKindStaticMethod;
- else
- kind = lldb::eMemberFunctionKindInstanceMethod;
- }
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
-
- if (kind == eMemberFunctionKindUnknown)
- return TypeMemberFunctionImpl();
- else
- return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind);
-}
-
-CompilerType
-ClangASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
- if (type)
- return GetType(GetQualType(type).getNonReferenceType());
- return CompilerType();
-}
-
-CompilerType ClangASTContext::CreateTypedefType(
- const CompilerType &type, const char *typedef_name,
- const CompilerDeclContext &compiler_decl_ctx) {
- if (type && typedef_name && typedef_name[0]) {
- ClangASTContext *ast =
- llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return CompilerType();
- clang::ASTContext &clang_ast = ast->getASTContext();
- clang::QualType qual_type(ClangUtil::GetQualType(type));
-
- clang::DeclContext *decl_ctx =
- ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx);
- if (decl_ctx == nullptr)
- decl_ctx = ast->getASTContext().getTranslationUnitDecl();
-
- clang::TypedefDecl *decl = clang::TypedefDecl::Create(
- clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
- &clang_ast.Idents.get(typedef_name),
- clang_ast.getTrivialTypeSourceInfo(qual_type));
-
- decl->setAccess(clang::AS_public); // TODO respect proper access specifier
-
- decl_ctx->addDecl(decl);
-
- // Get a uniqued clang::QualType for the typedef decl type
- return ast->GetType(clang_ast.getTypedefType(decl));
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type(GetQualType(type));
- return GetType(qual_type.getTypePtr()->getPointeeType());
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type(GetQualType(type));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- return GetType(getASTContext().getObjCObjectPointerType(qual_type));
-
- default:
- return GetType(getASTContext().getPointerType(qual_type));
- }
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
- if (type)
- return GetType(getASTContext().getLValueReferenceType(GetQualType(type)));
- else
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
- if (type)
- return GetType(getASTContext().getRValueReferenceType(GetQualType(type)));
- else
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetAtomicType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return CompilerType();
- return GetType(getASTContext().getAtomicType(GetQualType(type)));
-}
-
-CompilerType
-ClangASTContext::AddConstModifier(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType result(GetQualType(type));
- result.addConst();
- return GetType(result);
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType result(GetQualType(type));
- result.addVolatile();
- return GetType(result);
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType result(GetQualType(type));
- result.addRestrict();
- return GetType(result);
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::CreateTypedef(lldb::opaque_compiler_type_t type,
- const char *typedef_name,
- const CompilerDeclContext &compiler_decl_ctx) {
- if (type) {
- clang::ASTContext &clang_ast = getASTContext();
- clang::QualType qual_type(GetQualType(type));
-
- clang::DeclContext *decl_ctx =
- ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx);
- if (decl_ctx == nullptr)
- decl_ctx = getASTContext().getTranslationUnitDecl();
-
- clang::TypedefDecl *decl = clang::TypedefDecl::Create(
- clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
- &clang_ast.Idents.get(typedef_name),
- clang_ast.getTrivialTypeSourceInfo(qual_type));
-
- clang::TagDecl *tdecl = nullptr;
- if (!qual_type.isNull()) {
- if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>())
- tdecl = rt->getDecl();
- if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>())
- tdecl = et->getDecl();
- }
-
- // Check whether this declaration is an anonymous struct, union, or enum,
- // hidden behind a typedef. If so, we try to check whether we have a
- // typedef tag to attach to the original record declaration
- if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl())
- tdecl->setTypedefNameForAnonDecl(decl);
-
- decl->setAccess(clang::AS_public); // TODO respect proper access specifier
-
- // Get a uniqued clang::QualType for the typedef decl type
- return GetType(clang_ast.getTypedefType(decl));
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
- if (type) {
- const clang::TypedefType *typedef_type =
- llvm::dyn_cast<clang::TypedefType>(GetQualType(type));
- if (typedef_type)
- return GetType(typedef_type->getDecl()->getUnderlyingType());
- }
- return CompilerType();
-}
-
-// Create related types using the current type's AST
-
-CompilerType ClangASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
- return ClangASTContext::GetBasicType(basic_type);
-}
-// Exploring the type
-
-const llvm::fltSemantics &
-ClangASTContext::GetFloatTypeSemantics(size_t byte_size) {
- clang::ASTContext &ast = getASTContext();
- const size_t bit_size = byte_size * 8;
- if (bit_size == ast.getTypeSize(ast.FloatTy))
- return ast.getFloatTypeSemantics(ast.FloatTy);
- else if (bit_size == ast.getTypeSize(ast.DoubleTy))
- return ast.getFloatTypeSemantics(ast.DoubleTy);
- else if (bit_size == ast.getTypeSize(ast.LongDoubleTy))
- return ast.getFloatTypeSemantics(ast.LongDoubleTy);
- else if (bit_size == ast.getTypeSize(ast.HalfTy))
- return ast.getFloatTypeSemantics(ast.HalfTy);
- return llvm::APFloatBase::Bogus();
-}
-
-Optional<uint64_t>
-ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) {
- if (GetCompleteType(type)) {
- clang::QualType qual_type(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type))
- return getASTContext().getTypeSize(qual_type);
- else
- return None;
- break;
-
- case clang::Type::ObjCInterface:
- case clang::Type::ObjCObject: {
- ExecutionContext exe_ctx(exe_scope);
- Process *process = exe_ctx.GetProcessPtr();
- if (process) {
- ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
- if (objc_runtime) {
- uint64_t bit_size = 0;
- if (objc_runtime->GetTypeBitSize(GetType(qual_type), bit_size))
- return bit_size;
- }
- } else {
- static bool g_printed = false;
- if (!g_printed) {
- StreamString s;
- DumpTypeDescription(type, &s);
-
- llvm::outs() << "warning: trying to determine the size of type ";
- llvm::outs() << s.GetString() << "\n";
- llvm::outs() << "without a valid ExecutionContext. this is not "
- "reliable. please file a bug against LLDB.\n";
- llvm::outs() << "backtrace:\n";
- llvm::sys::PrintStackTrace(llvm::outs());
- llvm::outs() << "\n";
- g_printed = true;
- }
- }
- }
- LLVM_FALLTHROUGH;
- default:
- const uint32_t bit_size = getASTContext().getTypeSize(qual_type);
- if (bit_size == 0) {
- if (qual_type->isIncompleteArrayType())
- return getASTContext().getTypeSize(
- qual_type->getArrayElementTypeNoTypeQual()
- ->getCanonicalTypeUnqualified());
- }
- if (qual_type->isObjCObjectOrInterfaceType())
- return bit_size +
- getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy);
- // Function types actually have a size of 0, that's not an error.
- if (qual_type->isFunctionProtoType())
- return bit_size;
- if (bit_size)
- return bit_size;
- }
- }
- return None;
-}
-
-llvm::Optional<size_t>
-ClangASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) {
- if (GetCompleteType(type))
- return getASTContext().getTypeAlign(GetQualType(type));
- return {};
-}
-
-lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) {
- if (!type)
- return lldb::eEncodingInvalid;
-
- count = 1;
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
- switch (qual_type->getTypeClass()) {
- case clang::Type::Atomic:
- case clang::Type::Auto:
- case clang::Type::Decltype:
- case clang::Type::Elaborated:
- case clang::Type::Paren:
- case clang::Type::Typedef:
- case clang::Type::TypeOf:
- case clang::Type::TypeOfExpr:
- llvm_unreachable("Handled in RemoveWrappingTypes!");
-
- case clang::Type::UnaryTransform:
- break;
-
- case clang::Type::FunctionNoProto:
- case clang::Type::FunctionProto:
- break;
-
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- break;
-
- case clang::Type::ConstantArray:
- break;
-
- case clang::Type::DependentVector:
- case clang::Type::ExtVector:
- case clang::Type::Vector:
- // TODO: Set this to more than one???
- break;
-
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
- case clang::BuiltinType::Void:
- break;
-
- case clang::BuiltinType::Bool:
- 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:
- return lldb::eEncodingSint;
-
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char8:
- 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:
- return lldb::eEncodingUint;
-
- // Fixed point types. Note that they are currently ignored.
- case clang::BuiltinType::ShortAccum:
- case clang::BuiltinType::Accum:
- case clang::BuiltinType::LongAccum:
- case clang::BuiltinType::UShortAccum:
- case clang::BuiltinType::UAccum:
- case clang::BuiltinType::ULongAccum:
- case clang::BuiltinType::ShortFract:
- case clang::BuiltinType::Fract:
- case clang::BuiltinType::LongFract:
- case clang::BuiltinType::UShortFract:
- case clang::BuiltinType::UFract:
- case clang::BuiltinType::ULongFract:
- case clang::BuiltinType::SatShortAccum:
- case clang::BuiltinType::SatAccum:
- case clang::BuiltinType::SatLongAccum:
- case clang::BuiltinType::SatUShortAccum:
- case clang::BuiltinType::SatUAccum:
- case clang::BuiltinType::SatULongAccum:
- case clang::BuiltinType::SatShortFract:
- case clang::BuiltinType::SatFract:
- case clang::BuiltinType::SatLongFract:
- case clang::BuiltinType::SatUShortFract:
- case clang::BuiltinType::SatUFract:
- case clang::BuiltinType::SatULongFract:
- break;
-
- case clang::BuiltinType::Half:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Float16:
- case clang::BuiltinType::Float128:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble:
- return lldb::eEncodingIEEE754;
-
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCSel:
- return lldb::eEncodingUint;
-
- case clang::BuiltinType::NullPtr:
- return lldb::eEncodingUint;
-
- case clang::BuiltinType::Kind::ARCUnbridgedCast:
- case clang::BuiltinType::Kind::BoundMember:
- case clang::BuiltinType::Kind::BuiltinFn:
- case clang::BuiltinType::Kind::Dependent:
- case clang::BuiltinType::Kind::OCLClkEvent:
- case clang::BuiltinType::Kind::OCLEvent:
- case clang::BuiltinType::Kind::OCLImage1dRO:
- case clang::BuiltinType::Kind::OCLImage1dWO:
- case clang::BuiltinType::Kind::OCLImage1dRW:
- case clang::BuiltinType::Kind::OCLImage1dArrayRO:
- case clang::BuiltinType::Kind::OCLImage1dArrayWO:
- case clang::BuiltinType::Kind::OCLImage1dArrayRW:
- case clang::BuiltinType::Kind::OCLImage1dBufferRO:
- case clang::BuiltinType::Kind::OCLImage1dBufferWO:
- case clang::BuiltinType::Kind::OCLImage1dBufferRW:
- case clang::BuiltinType::Kind::OCLImage2dRO:
- case clang::BuiltinType::Kind::OCLImage2dWO:
- case clang::BuiltinType::Kind::OCLImage2dRW:
- case clang::BuiltinType::Kind::OCLImage2dArrayRO:
- case clang::BuiltinType::Kind::OCLImage2dArrayWO:
- case clang::BuiltinType::Kind::OCLImage2dArrayRW:
- case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO:
- case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO:
- case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW:
- case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO:
- case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO:
- case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW:
- case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO:
- case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO:
- case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW:
- case clang::BuiltinType::Kind::OCLImage2dDepthRO:
- case clang::BuiltinType::Kind::OCLImage2dDepthWO:
- case clang::BuiltinType::Kind::OCLImage2dDepthRW:
- case clang::BuiltinType::Kind::OCLImage2dMSAARO:
- case clang::BuiltinType::Kind::OCLImage2dMSAAWO:
- case clang::BuiltinType::Kind::OCLImage2dMSAARW:
- case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO:
- case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO:
- case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW:
- case clang::BuiltinType::Kind::OCLImage3dRO:
- case clang::BuiltinType::Kind::OCLImage3dWO:
- case clang::BuiltinType::Kind::OCLImage3dRW:
- case clang::BuiltinType::Kind::OCLQueue:
- case clang::BuiltinType::Kind::OCLReserveID:
- case clang::BuiltinType::Kind::OCLSampler:
- case clang::BuiltinType::Kind::OMPArraySection:
- case clang::BuiltinType::Kind::Overload:
- case clang::BuiltinType::Kind::PseudoObject:
- case clang::BuiltinType::Kind::UnknownAny:
- break;
-
- case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
- case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
- case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
- break;
-
- case clang::BuiltinType::SveBool:
- case clang::BuiltinType::SveInt8:
- case clang::BuiltinType::SveInt16:
- case clang::BuiltinType::SveInt32:
- case clang::BuiltinType::SveInt64:
- case clang::BuiltinType::SveUint8:
- case clang::BuiltinType::SveUint16:
- case clang::BuiltinType::SveUint32:
- case clang::BuiltinType::SveUint64:
- case clang::BuiltinType::SveFloat16:
- case clang::BuiltinType::SveFloat32:
- case clang::BuiltinType::SveFloat64:
- break;
- }
- break;
- // All pointer types are represented as unsigned integer encodings. We may
- // nee to add a eEncodingPointer if we ever need to know the difference
- case clang::Type::ObjCObjectPointer:
- case clang::Type::BlockPointer:
- case clang::Type::Pointer:
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- case clang::Type::MemberPointer:
- return lldb::eEncodingUint;
- case clang::Type::Complex: {
- lldb::Encoding encoding = lldb::eEncodingIEEE754;
- if (qual_type->isComplexType())
- encoding = lldb::eEncodingIEEE754;
- else {
- const clang::ComplexType *complex_type =
- qual_type->getAsComplexIntegerType();
- if (complex_type)
- encoding = GetType(complex_type->getElementType()).GetEncoding(count);
- else
- encoding = lldb::eEncodingSint;
- }
- count = 2;
- return encoding;
- }
-
- case clang::Type::ObjCInterface:
- break;
- case clang::Type::Record:
- break;
- case clang::Type::Enum:
- return lldb::eEncodingSint;
- case clang::Type::DependentSizedArray:
- case clang::Type::DependentSizedExtVector:
- case clang::Type::UnresolvedUsing:
- case clang::Type::Attributed:
- case clang::Type::TemplateTypeParm:
- case clang::Type::SubstTemplateTypeParm:
- case clang::Type::SubstTemplateTypeParmPack:
- case clang::Type::InjectedClassName:
- case clang::Type::DependentName:
- case clang::Type::DependentTemplateSpecialization:
- case clang::Type::PackExpansion:
- case clang::Type::ObjCObject:
-
- case clang::Type::TemplateSpecialization:
- case clang::Type::DeducedTemplateSpecialization:
- case clang::Type::Adjusted:
- case clang::Type::Pipe:
- break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed:
- break;
- case clang::Type::ObjCTypeParam:
- break;
-
- case clang::Type::DependentAddressSpace:
- break;
- case clang::Type::MacroQualified:
- break;
- }
- count = 0;
- return lldb::eEncodingInvalid;
-}
-
-lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
- if (!type)
- return lldb::eFormatDefault;
-
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
- switch (qual_type->getTypeClass()) {
- case clang::Type::Atomic:
- case clang::Type::Auto:
- case clang::Type::Decltype:
- case clang::Type::Elaborated:
- case clang::Type::Paren:
- case clang::Type::Typedef:
- case clang::Type::TypeOf:
- case clang::Type::TypeOfExpr:
- llvm_unreachable("Handled in RemoveWrappingTypes!");
- case clang::Type::UnaryTransform:
- break;
-
- case clang::Type::FunctionNoProto:
- case clang::Type::FunctionProto:
- break;
-
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- break;
-
- case clang::Type::ConstantArray:
- return lldb::eFormatVoid; // no value
-
- case clang::Type::DependentVector:
- case clang::Type::ExtVector:
- case clang::Type::Vector:
- break;
-
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
- // default: assert(0 && "Unknown builtin type!");
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::Void:
- case clang::BuiltinType::BoundMember:
- break;
-
- case clang::BuiltinType::Bool:
- return lldb::eFormatBoolean;
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- return lldb::eFormatChar;
- case clang::BuiltinType::Char16:
- return lldb::eFormatUnicode16;
- case clang::BuiltinType::Char32:
- return lldb::eFormatUnicode32;
- case clang::BuiltinType::UShort:
- return lldb::eFormatUnsigned;
- case clang::BuiltinType::Short:
- return lldb::eFormatDecimal;
- case clang::BuiltinType::UInt:
- return lldb::eFormatUnsigned;
- case clang::BuiltinType::Int:
- return lldb::eFormatDecimal;
- case clang::BuiltinType::ULong:
- return lldb::eFormatUnsigned;
- case clang::BuiltinType::Long:
- return lldb::eFormatDecimal;
- case clang::BuiltinType::ULongLong:
- return lldb::eFormatUnsigned;
- case clang::BuiltinType::LongLong:
- return lldb::eFormatDecimal;
- case clang::BuiltinType::UInt128:
- return lldb::eFormatUnsigned;
- case clang::BuiltinType::Int128:
- return lldb::eFormatDecimal;
- case clang::BuiltinType::Half:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble:
- return lldb::eFormatFloat;
- default:
- return lldb::eFormatHex;
- }
- break;
- case clang::Type::ObjCObjectPointer:
- return lldb::eFormatHex;
- case clang::Type::BlockPointer:
- return lldb::eFormatHex;
- case clang::Type::Pointer:
- return lldb::eFormatHex;
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- return lldb::eFormatHex;
- case clang::Type::MemberPointer:
- break;
- case clang::Type::Complex: {
- if (qual_type->isComplexType())
- return lldb::eFormatComplex;
- else
- return lldb::eFormatComplexInteger;
- }
- case clang::Type::ObjCInterface:
- break;
- case clang::Type::Record:
- break;
- case clang::Type::Enum:
- return lldb::eFormatEnum;
- case clang::Type::DependentSizedArray:
- case clang::Type::DependentSizedExtVector:
- case clang::Type::UnresolvedUsing:
- case clang::Type::Attributed:
- case clang::Type::TemplateTypeParm:
- case clang::Type::SubstTemplateTypeParm:
- case clang::Type::SubstTemplateTypeParmPack:
- case clang::Type::InjectedClassName:
- case clang::Type::DependentName:
- case clang::Type::DependentTemplateSpecialization:
- case clang::Type::PackExpansion:
- case clang::Type::ObjCObject:
-
- case clang::Type::TemplateSpecialization:
- case clang::Type::DeducedTemplateSpecialization:
- case clang::Type::Adjusted:
- case clang::Type::Pipe:
- break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed:
- break;
- case clang::Type::ObjCTypeParam:
- break;
-
- case clang::Type::DependentAddressSpace:
- break;
- case clang::Type::MacroQualified:
- break;
- }
- // We don't know hot to display this type...
- return lldb::eFormatBytes;
-}
-
-static bool ObjCDeclHasIVars(clang::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;
-}
-
-static Optional<SymbolFile::ArrayInfo>
-GetDynamicArrayInfo(ClangASTContext &ast, SymbolFile *sym_file,
- clang::QualType qual_type,
- const ExecutionContext *exe_ctx) {
- if (qual_type->isIncompleteArrayType())
- if (auto *metadata = ast.GetMetadata(qual_type.getTypePtr()))
- return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(),
- exe_ctx);
- return llvm::None;
-}
-
-uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes,
- const ExecutionContext *exe_ctx) {
- if (!type)
- return 0;
-
- uint32_t num_children = 0;
- clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type)));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Builtin:
- switch (llvm::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(&getASTContext(), qual_type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::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.
- clang::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 clang::CXXRecordDecl *base_class_decl =
- llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()
- ->getAs<clang::RecordType>()
- ->getDecl());
-
- // Skip empty base classes
- if (!ClangASTContext::RecordHasFields(base_class_decl))
- continue;
-
- num_children++;
- }
- } else {
- // Include all base classes
- num_children += cxx_record_decl->getNumBases();
- }
- }
- clang::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(&getASTContext(), qual_type)) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl) {
-
- clang::ObjCInterfaceDecl *superclass_interface_decl =
- class_interface_decl->getSuperClass();
- if (superclass_interface_decl) {
- if (omit_empty_base_classes) {
- if (ObjCDeclHasIVars(superclass_interface_decl, true))
- ++num_children;
- } else
- ++num_children;
- }
-
- num_children += class_interface_decl->ivar_size();
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer: {
- const clang::ObjCObjectPointerType *pointer_type =
- llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
- clang::QualType pointee_type = pointer_type->getPointeeType();
- uint32_t num_pointee_children =
- GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
- // 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::Vector:
- case clang::Type::ExtVector:
- num_children =
- llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements();
- break;
-
- case clang::Type::ConstantArray:
- num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())
- ->getSize()
- .getLimitedValue();
- break;
- case clang::Type::IncompleteArray:
- if (auto array_info =
- GetDynamicArrayInfo(*this, GetSymbolFile(), qual_type, exe_ctx))
- // Only 1-dimensional arrays are supported.
- num_children = array_info->element_orders.size()
- ? array_info->element_orders.back()
- : 0;
- break;
-
- case clang::Type::Pointer: {
- const clang::PointerType *pointer_type =
- llvm::cast<clang::PointerType>(qual_type.getTypePtr());
- clang::QualType pointee_type(pointer_type->getPointeeType());
- uint32_t num_pointee_children =
- GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
- 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 = GetNumPointeeChildren(pointee_type);
- } else
- num_children = num_pointee_children;
- } break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference: {
- const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- clang::QualType pointee_type = reference_type->getPointeeType();
- uint32_t num_pointee_children =
- GetType(pointee_type).GetNumChildren(omit_empty_base_classes, exe_ctx);
- // 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;
-
- default:
- break;
- }
- return num_children;
-}
-
-CompilerType ClangASTContext::GetBuiltinTypeByName(ConstString name) {
- return GetBasicType(GetBasicTypeEnumeration(name));
-}
-
-lldb::BasicType
-ClangASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
- if (type) {
- clang::QualType qual_type(GetQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- if (type_class == clang::Type::Builtin) {
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
- case clang::BuiltinType::Void:
- return eBasicTypeVoid;
- case clang::BuiltinType::Bool:
- return eBasicTypeBool;
- case clang::BuiltinType::Char_S:
- return eBasicTypeSignedChar;
- case clang::BuiltinType::Char_U:
- return eBasicTypeUnsignedChar;
- case clang::BuiltinType::Char16:
- return eBasicTypeChar16;
- case clang::BuiltinType::Char32:
- return eBasicTypeChar32;
- case clang::BuiltinType::UChar:
- return eBasicTypeUnsignedChar;
- case clang::BuiltinType::SChar:
- return eBasicTypeSignedChar;
- case clang::BuiltinType::WChar_S:
- return eBasicTypeSignedWChar;
- case clang::BuiltinType::WChar_U:
- return eBasicTypeUnsignedWChar;
- case clang::BuiltinType::Short:
- return eBasicTypeShort;
- case clang::BuiltinType::UShort:
- return eBasicTypeUnsignedShort;
- case clang::BuiltinType::Int:
- return eBasicTypeInt;
- case clang::BuiltinType::UInt:
- return eBasicTypeUnsignedInt;
- case clang::BuiltinType::Long:
- return eBasicTypeLong;
- case clang::BuiltinType::ULong:
- return eBasicTypeUnsignedLong;
- case clang::BuiltinType::LongLong:
- return eBasicTypeLongLong;
- case clang::BuiltinType::ULongLong:
- return eBasicTypeUnsignedLongLong;
- case clang::BuiltinType::Int128:
- return eBasicTypeInt128;
- case clang::BuiltinType::UInt128:
- return eBasicTypeUnsignedInt128;
-
- case clang::BuiltinType::Half:
- return eBasicTypeHalf;
- case clang::BuiltinType::Float:
- return eBasicTypeFloat;
- case clang::BuiltinType::Double:
- return eBasicTypeDouble;
- case clang::BuiltinType::LongDouble:
- return eBasicTypeLongDouble;
-
- case clang::BuiltinType::NullPtr:
- return eBasicTypeNullPtr;
- case clang::BuiltinType::ObjCId:
- return eBasicTypeObjCID;
- case clang::BuiltinType::ObjCClass:
- return eBasicTypeObjCClass;
- case clang::BuiltinType::ObjCSel:
- return eBasicTypeObjCSel;
- default:
- return eBasicTypeOther;
- }
- }
- }
- return eBasicTypeInvalid;
-}
-
-void ClangASTContext::ForEachEnumerator(
- lldb::opaque_compiler_type_t type,
- std::function<bool(const CompilerType &integer_type,
- ConstString name,
- const llvm::APSInt &value)> const &callback) {
- const clang::EnumType *enum_type =
- llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type));
- if (enum_type) {
- const clang::EnumDecl *enum_decl = enum_type->getDecl();
- if (enum_decl) {
- CompilerType integer_type = GetType(enum_decl->getIntegerType());
-
- clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
- for (enum_pos = enum_decl->enumerator_begin(),
- enum_end_pos = enum_decl->enumerator_end();
- enum_pos != enum_end_pos; ++enum_pos) {
- ConstString name(enum_pos->getNameAsString().c_str());
- if (!callback(integer_type, name, enum_pos->getInitVal()))
- break;
- }
- }
- }
-}
-
-#pragma mark Aggregate Types
-
-uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
- if (!type)
- return 0;
-
- uint32_t count = 0;
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr());
- if (record_type) {
- clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl) {
- uint32_t field_idx = 0;
- clang::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::ObjCObjectPointer: {
- const clang::ObjCObjectPointerType *objc_class_type =
- qual_type->getAs<clang::ObjCObjectPointerType>();
- const clang::ObjCInterfaceType *objc_interface_type =
- objc_class_type->getInterfaceType();
- if (objc_interface_type &&
- GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
- const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_interface_type->getDecl();
- if (class_interface_decl) {
- count = class_interface_decl->ivar_size();
- }
- }
- break;
- }
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl)
- count = class_interface_decl->ivar_size();
- }
- }
- break;
-
- default:
- break;
- }
- return count;
-}
-
-static lldb::opaque_compiler_type_t
-GetObjCFieldAtIndex(clang::ASTContext *ast,
- clang::ObjCInterfaceDecl *class_interface_decl, size_t idx,
- std::string &name, uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) {
- if (class_interface_decl) {
- if (idx < (class_interface_decl->ivar_size())) {
- clang::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 clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
-
- clang::QualType ivar_qual_type(ivar_decl->getType());
-
- name.assign(ivar_decl->getNameAsString());
-
- if (bit_offset_ptr) {
- const clang::ASTRecordLayout &interface_layout =
- ast->getASTObjCInterfaceLayout(class_interface_decl);
- *bit_offset_ptr = interface_layout.getFieldOffset(ivar_idx);
- }
-
- const bool is_bitfield = ivar_pos->isBitField();
-
- if (bitfield_bit_size_ptr) {
- *bitfield_bit_size_ptr = 0;
-
- if (is_bitfield && ast) {
- clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
- clang::Expr::EvalResult result;
- if (bitfield_bit_size_expr &&
- bitfield_bit_size_expr->EvaluateAsInt(result, *ast)) {
- llvm::APSInt bitfield_apsint = result.Val.getInt();
- *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
- }
- }
- }
- if (is_bitfield_ptr)
- *is_bitfield_ptr = is_bitfield;
-
- return ivar_qual_type.getAsOpaquePtr();
- }
- }
- }
- }
- return nullptr;
-}
-
-CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx, std::string &name,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) {
- if (!type)
- return CompilerType();
-
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- uint32_t field_idx = 0;
- clang::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 clang::ASTRecordLayout &record_layout =
- getASTContext().getASTRecordLayout(record_decl);
- *bit_offset_ptr = record_layout.getFieldOffset(field_idx);
- }
-
- const bool is_bitfield = field->isBitField();
-
- if (bitfield_bit_size_ptr) {
- *bitfield_bit_size_ptr = 0;
-
- if (is_bitfield) {
- clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
- clang::Expr::EvalResult result;
- if (bitfield_bit_size_expr &&
- bitfield_bit_size_expr->EvaluateAsInt(result,
- getASTContext())) {
- llvm::APSInt bitfield_apsint = result.Val.getInt();
- *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
- }
- }
- }
- if (is_bitfield_ptr)
- *is_bitfield_ptr = is_bitfield;
-
- return GetType(field->getType());
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer: {
- const clang::ObjCObjectPointerType *objc_class_type =
- qual_type->getAs<clang::ObjCObjectPointerType>();
- const clang::ObjCInterfaceType *objc_interface_type =
- objc_class_type->getInterfaceType();
- if (objc_interface_type &&
- GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
- const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_interface_type->getDecl();
- if (class_interface_decl) {
- return CompilerType(
- this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
- idx, name, bit_offset_ptr,
- bitfield_bit_size_ptr, is_bitfield_ptr));
- }
- }
- break;
- }
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
- return CompilerType(
- this, GetObjCFieldAtIndex(&getASTContext(), class_interface_decl,
- idx, name, bit_offset_ptr,
- bitfield_bit_size_ptr, is_bitfield_ptr));
- }
- }
- break;
-
- default:
- break;
- }
- return CompilerType();
-}
-
-uint32_t
-ClangASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
- uint32_t count = 0;
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- count = cxx_record_decl->getNumBases();
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- count = GetPointeeType(type).GetNumDirectBaseClasses();
- break;
-
- case clang::Type::ObjCObject:
- if (GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- qual_type->getAsObjCQualifiedInterfaceType();
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl && class_interface_decl->getSuperClass())
- count = 1;
- }
- }
- break;
- case clang::Type::ObjCInterface:
- if (GetCompleteType(type)) {
- const clang::ObjCInterfaceType *objc_interface_type =
- qual_type->getAs<clang::ObjCInterfaceType>();
- if (objc_interface_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_interface_type->getInterface();
-
- if (class_interface_decl && class_interface_decl->getSuperClass())
- count = 1;
- }
- }
- break;
-
- default:
- break;
- }
- return count;
-}
-
-uint32_t
-ClangASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
- uint32_t count = 0;
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- count = cxx_record_decl->getNumVBases();
- }
- break;
-
- default:
- break;
- }
- return count;
-}
-
-CompilerType ClangASTContext::GetDirectBaseClassAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- uint32_t curr_idx = 0;
- clang::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 clang::ASTRecordLayout &record_layout =
- getASTContext().getASTRecordLayout(cxx_record_decl);
- const clang::CXXRecordDecl *base_class_decl =
- llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()
- ->getAs<clang::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 GetType(base_class->getType());
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr);
-
- case clang::Type::ObjCObject:
- if (idx == 0 && GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- qual_type->getAsObjCQualifiedInterfaceType();
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl) {
- clang::ObjCInterfaceDecl *superclass_interface_decl =
- class_interface_decl->getSuperClass();
- if (superclass_interface_decl) {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- return GetType(getASTContext().getObjCInterfaceType(
- superclass_interface_decl));
- }
- }
- }
- }
- break;
- case clang::Type::ObjCInterface:
- if (idx == 0 && GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_interface_type =
- qual_type->getAs<clang::ObjCInterfaceType>();
- if (objc_interface_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_interface_type->getInterface();
-
- if (class_interface_decl) {
- clang::ObjCInterfaceDecl *superclass_interface_decl =
- class_interface_decl->getSuperClass();
- if (superclass_interface_decl) {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- return GetType(getASTContext().getObjCInterfaceType(
- superclass_interface_decl));
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- return CompilerType();
-}
-
-CompilerType ClangASTContext::GetVirtualBaseClassAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- uint32_t curr_idx = 0;
- clang::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 clang::ASTRecordLayout &record_layout =
- getASTContext().getASTRecordLayout(cxx_record_decl);
- const clang::CXXRecordDecl *base_class_decl =
- llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()
- ->getAs<clang::RecordType>()
- ->getDecl());
- *bit_offset_ptr =
- record_layout.getVBaseClassOffset(base_class_decl)
- .getQuantity() *
- 8;
- }
- return GetType(base_class->getType());
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- return CompilerType();
-}
-
-// 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::QualType type) {
- if (type.isNull())
- return 0;
-
- clang::QualType qual_type = RemoveWrappingTypes(type.getCanonicalType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::Void:
- case clang::BuiltinType::NullPtr:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLImage1dRO:
- case clang::BuiltinType::OCLImage1dWO:
- case clang::BuiltinType::OCLImage1dRW:
- case clang::BuiltinType::OCLImage1dArrayRO:
- case clang::BuiltinType::OCLImage1dArrayWO:
- case clang::BuiltinType::OCLImage1dArrayRW:
- case clang::BuiltinType::OCLImage1dBufferRO:
- case clang::BuiltinType::OCLImage1dBufferWO:
- case clang::BuiltinType::OCLImage1dBufferRW:
- case clang::BuiltinType::OCLImage2dRO:
- case clang::BuiltinType::OCLImage2dWO:
- case clang::BuiltinType::OCLImage2dRW:
- case clang::BuiltinType::OCLImage2dArrayRO:
- case clang::BuiltinType::OCLImage2dArrayWO:
- case clang::BuiltinType::OCLImage2dArrayRW:
- case clang::BuiltinType::OCLImage3dRO:
- case clang::BuiltinType::OCLImage3dWO:
- case clang::BuiltinType::OCLImage3dRW:
- case clang::BuiltinType::OCLSampler:
- 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:
- case clang::BuiltinType::BuiltinFn:
- case clang::BuiltinType::OMPArraySection:
- return 1;
- default:
- return 0;
- }
- 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::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;
-}
-
-CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_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,
- ValueObject *valobj, uint64_t &language_flags) {
- if (!type)
- return CompilerType();
-
- auto get_exe_scope = [&exe_ctx]() {
- return exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
- };
-
- clang::QualType parent_qual_type(
- RemoveWrappingTypes(GetCanonicalQualType(type)));
- const clang::Type::TypeClass parent_type_class =
- parent_qual_type->getTypeClass();
- child_bitfield_bit_size = 0;
- child_bitfield_bit_offset = 0;
- child_is_base_class = false;
- language_flags = 0;
-
- const bool idx_is_valid =
- idx < GetNumChildren(type, omit_empty_base_classes, exe_ctx);
- int32_t bit_offset;
- switch (parent_type_class) {
- case clang::Type::Builtin:
- if (idx_is_valid) {
- switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind()) {
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- child_name = "isa";
- child_byte_size =
- getASTContext().getTypeSize(getASTContext().ObjCBuiltinClassTy) /
- CHAR_BIT;
- return GetType(getASTContext().ObjCBuiltinClassTy);
-
- default:
- break;
- }
- }
- break;
-
- case clang::Type::Record:
- if (idx_is_valid && GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::ASTRecordLayout &record_layout =
- getASTContext().getASTRecordLayout(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl) {
- // We might have base classes to print out first
- clang::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 clang::CXXRecordDecl *base_class_decl = nullptr;
-
- // Skip empty base classes
- if (omit_empty_base_classes) {
- base_class_decl = llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()->getAs<clang::RecordType>()->getDecl());
- if (!ClangASTContext::RecordHasFields(base_class_decl))
- continue;
- }
-
- if (idx == child_idx) {
- if (base_class_decl == nullptr)
- base_class_decl = llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
- if (base_class->isVirtual()) {
- bool handled = false;
- if (valobj) {
- clang::VTableContextBase *vtable_ctx =
- getASTContext().getVTableContext();
- if (vtable_ctx)
- handled = GetVBaseBitOffset(*vtable_ctx, *valobj,
- record_layout, cxx_record_decl,
- base_class_decl, bit_offset);
- }
- if (!handled)
- 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;
- CompilerType base_class_clang_type = GetType(base_class->getType());
- child_name = base_class_clang_type.GetTypeName().AsCString("");
- Optional<uint64_t> size =
- base_class_clang_type.GetBitSize(get_exe_scope());
- if (!size)
- return {};
- uint64_t base_class_clang_type_bit_size = *size;
-
- // Base classes bit sizes should be a multiple of 8 bits in size
- assert(base_class_clang_type_bit_size % 8 == 0);
- child_byte_size = base_class_clang_type_bit_size / 8;
- child_is_base_class = true;
- return base_class_clang_type;
- }
- // 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;
- clang::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());
-
- // Figure out the type byte size (field_type_info.first) and
- // alignment (field_type_info.second) from the AST context.
- CompilerType field_clang_type = GetType(field->getType());
- assert(field_idx < record_layout.getFieldCount());
- Optional<uint64_t> size =
- field_clang_type.GetByteSize(get_exe_scope());
- if (!size)
- return {};
- child_byte_size = *size;
- const uint32_t child_bit_size = child_byte_size * 8;
-
- // Figure out the field offset within the current struct/union/class
- // type
- bit_offset = record_layout.getFieldOffset(field_idx);
- if (FieldIsBitfield(*field, child_bitfield_bit_size)) {
- child_bitfield_bit_offset = bit_offset % child_bit_size;
- const uint32_t child_bit_offset =
- bit_offset - child_bitfield_bit_offset;
- child_byte_offset = child_bit_offset / 8;
- } else {
- child_byte_offset = bit_offset / 8;
- }
-
- return field_clang_type;
- }
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (idx_is_valid && GetCompleteType(type)) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- uint32_t child_idx = 0;
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl) {
-
- const clang::ASTRecordLayout &interface_layout =
- getASTContext().getASTObjCInterfaceLayout(class_interface_decl);
- clang::ObjCInterfaceDecl *superclass_interface_decl =
- class_interface_decl->getSuperClass();
- if (superclass_interface_decl) {
- if (omit_empty_base_classes) {
- CompilerType base_class_clang_type =
- GetType(getASTContext().getObjCInterfaceType(
- superclass_interface_decl));
- if (base_class_clang_type.GetNumChildren(omit_empty_base_classes,
- exe_ctx) > 0) {
- if (idx == 0) {
- clang::QualType ivar_qual_type(
- getASTContext().getObjCInterfaceType(
- superclass_interface_decl));
-
- child_name.assign(
- superclass_interface_decl->getNameAsString());
-
- clang::TypeInfo ivar_type_info =
- getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
-
- child_byte_size = ivar_type_info.Width / 8;
- child_byte_offset = 0;
- child_is_base_class = true;
-
- return GetType(ivar_qual_type);
- }
-
- ++child_idx;
- }
- } else
- ++child_idx;
- }
-
- const uint32_t superclass_idx = child_idx;
-
- if (idx < (child_idx + class_interface_decl->ivar_size())) {
- clang::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) {
- clang::ObjCIvarDecl *ivar_decl = *ivar_pos;
-
- clang::QualType ivar_qual_type(ivar_decl->getType());
-
- child_name.assign(ivar_decl->getNameAsString());
-
- clang::TypeInfo ivar_type_info =
- getASTContext().getTypeInfo(ivar_qual_type.getTypePtr());
-
- child_byte_size = ivar_type_info.Width / 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 = nullptr;
- if (exe_ctx)
- process = exe_ctx->GetProcessPtr();
- if (process) {
- ObjCLanguageRuntime *objc_runtime =
- ObjCLanguageRuntime::Get(*process);
- if (objc_runtime != nullptr) {
- CompilerType parent_ast_type = GetType(parent_qual_type);
- child_byte_offset = objc_runtime->GetByteOffsetForIvar(
- parent_ast_type, ivar_decl->getNameAsString().c_str());
- }
- }
-
- // Setting this to INT32_MAX to make sure we don't compute it
- // twice...
- bit_offset = INT32_MAX;
-
- if (child_byte_offset ==
- static_cast<int32_t>(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 (FieldIsBitfield(ivar_decl, child_bitfield_bit_size)) {
- if (bit_offset == INT32_MAX)
- bit_offset = interface_layout.getFieldOffset(
- child_idx - superclass_idx);
-
- child_bitfield_bit_offset = bit_offset % 8;
- }
- return GetType(ivar_qual_type);
- }
- ++child_idx;
- }
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (idx_is_valid) {
- CompilerType pointee_clang_type(GetPointeeType(type));
-
- if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
- child_is_deref_of_parent = false;
- bool tmp_child_is_deref_of_parent = false;
- return pointee_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, 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, valobj,
- language_flags);
- } else {
- child_is_deref_of_parent = true;
- const char *parent_name =
- valobj ? valobj->GetName().GetCString() : nullptr;
- if (parent_name) {
- child_name.assign(1, '*');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0 && pointee_clang_type.GetCompleteType()) {
- if (Optional<uint64_t> size =
- pointee_clang_type.GetByteSize(get_exe_scope())) {
- child_byte_size = *size;
- child_byte_offset = 0;
- return pointee_clang_type;
- }
- }
- }
- }
- break;
-
- case clang::Type::Vector:
- case clang::Type::ExtVector:
- if (idx_is_valid) {
- const clang::VectorType *array =
- llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
- if (array) {
- CompilerType element_type = GetType(array->getElementType());
- if (element_type.GetCompleteType()) {
- char element_name[64];
- ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]",
- static_cast<uint64_t>(idx));
- child_name.assign(element_name);
- if (Optional<uint64_t> size =
- element_type.GetByteSize(get_exe_scope())) {
- child_byte_size = *size;
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
- }
- }
- }
- }
- break;
-
- case clang::Type::ConstantArray:
- case clang::Type::IncompleteArray:
- if (ignore_array_bounds || idx_is_valid) {
- const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe();
- if (array) {
- CompilerType element_type = GetType(array->getElementType());
- if (element_type.GetCompleteType()) {
- child_name = llvm::formatv("[{0}]", idx);
- if (Optional<uint64_t> size =
- element_type.GetByteSize(get_exe_scope())) {
- child_byte_size = *size;
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
- }
- }
- }
- }
- break;
-
- case clang::Type::Pointer: {
- CompilerType pointee_clang_type(GetPointeeType(type));
-
- // Don't dereference "void *" pointers
- if (pointee_clang_type.IsVoidType())
- return CompilerType();
-
- if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
- child_is_deref_of_parent = false;
- bool tmp_child_is_deref_of_parent = false;
- return pointee_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, 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, valobj,
- language_flags);
- } else {
- child_is_deref_of_parent = true;
-
- const char *parent_name =
- valobj ? valobj->GetName().GetCString() : nullptr;
- if (parent_name) {
- child_name.assign(1, '*');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0) {
- if (Optional<uint64_t> size =
- pointee_clang_type.GetByteSize(get_exe_scope())) {
- child_byte_size = *size;
- child_byte_offset = 0;
- return pointee_clang_type;
- }
- }
- }
- break;
- }
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- if (idx_is_valid) {
- const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
- CompilerType pointee_clang_type =
- GetType(reference_type->getPointeeType());
- if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
- child_is_deref_of_parent = false;
- bool tmp_child_is_deref_of_parent = false;
- return pointee_clang_type.GetChildCompilerTypeAtIndex(
- exe_ctx, 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, valobj,
- language_flags);
- } else {
- const char *parent_name =
- valobj ? valobj->GetName().GetCString() : nullptr;
- if (parent_name) {
- child_name.assign(1, '&');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0) {
- if (Optional<uint64_t> size =
- pointee_clang_type.GetByteSize(get_exe_scope())) {
- child_byte_size = *size;
- child_byte_offset = 0;
- return pointee_clang_type;
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- return CompilerType();
-}
-
-static uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl,
- const clang::CXXBaseSpecifier *base_spec,
- bool omit_empty_base_classes) {
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- // const char *super_name = record_decl->getNameAsCString();
- // const char *base_name =
- // base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString();
- // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
- //
- if (cxx_record_decl) {
- clang::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<clang::RecordType>()->getDecl()->getNameAsCString());
- //
- //
- if (base_class == base_spec)
- return child_idx;
- ++child_idx;
- }
- }
-
- return UINT32_MAX;
-}
-
-static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl,
- clang::NamedDecl *canonical_decl,
- bool omit_empty_base_classes) {
- uint32_t child_idx = ClangASTContext::GetNumBaseClasses(
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
- omit_empty_base_classes);
-
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end();
- field != field_end; ++field, ++child_idx) {
- 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(
- lldb::opaque_compiler_type_t type, const char *name,
- bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
- if (type && name && name[0]) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
-
- assert(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- // Try and find a field that matches NAME
- clang::RecordDecl::field_iterator field, field_end;
- llvm::StringRef name_sref(name);
- for (field = record_decl->field_begin(),
- field_end = record_decl->field_end();
- field != field_end; ++field, ++child_idx) {
- llvm::StringRef field_name = field->getName();
- if (field_name.empty()) {
- CompilerType field_type = GetType(field->getType());
- child_indexes.push_back(child_idx);
- if (field_type.GetIndexOfChildMemberWithName(
- name, omit_empty_base_classes, child_indexes))
- return child_indexes.size();
- child_indexes.pop_back();
-
- } else if (field_name.equals(name_sref)) {
- // We have to add on the number of base classes to this index!
- child_indexes.push_back(
- child_idx + ClangASTContext::GetNumBaseClasses(
- cxx_record_decl, omit_empty_base_classes));
- return child_indexes.size();
- }
- }
-
- if (cxx_record_decl) {
- const clang::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...
- clang::IdentifierInfo &ident_ref =
- getASTContext().Idents.get(name_sref);
- clang::DeclarationName decl_name(&ident_ref);
-
- clang::CXXBasePaths paths;
- if (cxx_record_decl->lookupInBases(
- [decl_name](const clang::CXXBaseSpecifier *specifier,
- clang::CXXBasePath &path) {
- return clang::CXXRecordDecl::FindOrdinaryMember(
- specifier, path, decl_name);
- },
- paths)) {
- clang::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) {
- clang::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 = llvm::cast<clang::RecordDecl>(
- elem.Base->getType()
- ->getAs<clang::RecordType>()
- ->getDecl());
- }
- }
- for (clang::NamedDecl *path_decl : path->Decls) {
- child_idx = GetIndexForRecordChild(
- parent_record_decl, path_decl, 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 (GetCompleteType(type)) {
- llvm::StringRef name_sref(name);
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- uint32_t child_idx = 0;
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl) {
- clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
- ivar_end = class_interface_decl->ivar_end();
- clang::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 clang::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);
-
- CompilerType superclass_clang_type =
- GetType(getASTContext().getObjCInterfaceType(
- superclass_interface_decl));
- if (superclass_clang_type.GetIndexOfChildMemberWithName(
- 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: {
- CompilerType objc_object_clang_type = GetType(
- llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
- ->getPointeeType());
- return objc_object_clang_type.GetIndexOfChildMemberWithName(
- name, omit_empty_base_classes, child_indexes);
- } break;
-
- case clang::Type::ConstantArray: {
- // const clang::ConstantArrayType *array =
- // llvm::cast<clang::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 =
- // llvm::cast<MemberPointerType>(qual_type.getTypePtr());
- // clang::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 clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- clang::QualType pointee_type(reference_type->getPointeeType());
- CompilerType pointee_clang_type = GetType(pointee_type);
-
- if (pointee_clang_type.IsAggregateType()) {
- return pointee_clang_type.GetIndexOfChildMemberWithName(
- name, omit_empty_base_classes, child_indexes);
- }
- } break;
-
- case clang::Type::Pointer: {
- CompilerType pointee_clang_type(GetPointeeType(type));
-
- if (pointee_clang_type.IsAggregateType()) {
- return pointee_clang_type.GetIndexOfChildMemberWithName(
- name, omit_empty_base_classes, child_indexes);
- }
- } break;
-
- 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(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) {
- if (type && name && name[0]) {
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
-
- assert(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- if (cxx_record_decl) {
- clang::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
- clang::CXXRecordDecl *base_class_decl =
- llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()
- ->getAs<clang::RecordType>()
- ->getDecl());
- if (omit_empty_base_classes &&
- !ClangASTContext::RecordHasFields(base_class_decl))
- continue;
-
- CompilerType base_class_clang_type = GetType(base_class->getType());
- std::string base_class_type_name(
- base_class_clang_type.GetTypeName().AsCString(""));
- if (base_class_type_name == name)
- return child_idx;
- ++child_idx;
- }
- }
-
- // Try and find a field that matches NAME
- clang::RecordDecl::field_iterator field, field_end;
- llvm::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 (GetCompleteType(type)) {
- llvm::StringRef name_sref(name);
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- uint32_t child_idx = 0;
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
-
- if (class_interface_decl) {
- clang::ObjCInterfaceDecl::ivar_iterator ivar_pos,
- ivar_end = class_interface_decl->ivar_end();
- clang::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 clang::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: {
- CompilerType pointee_clang_type = GetType(
- llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())
- ->getPointeeType());
- return pointee_clang_type.GetIndexOfChildWithName(
- name, omit_empty_base_classes);
- } break;
-
- case clang::Type::ConstantArray: {
- // const clang::ConstantArrayType *array =
- // llvm::cast<clang::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 =
- // llvm::cast<MemberPointerType>(qual_type.getTypePtr());
- // clang::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 clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- CompilerType pointee_type = GetType(reference_type->getPointeeType());
-
- if (pointee_type.IsAggregateType()) {
- return pointee_type.GetIndexOfChildWithName(name,
- omit_empty_base_classes);
- }
- } break;
-
- case clang::Type::Pointer: {
- const clang::PointerType *pointer_type =
- llvm::cast<clang::PointerType>(qual_type.getTypePtr());
- CompilerType pointee_type = GetType(pointer_type->getPointeeType());
-
- if (pointee_type.IsAggregateType()) {
- return pointee_type.GetIndexOfChildWithName(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;
-
- default:
- break;
- }
- }
- return UINT32_MAX;
-}
-
-size_t
-ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
- if (!type)
- return 0;
-
- clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- const clang::ClassTemplateSpecializationDecl *template_decl =
- llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
- cxx_record_decl);
- if (template_decl)
- return template_decl->getTemplateArgs().size();
- }
- }
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-const clang::ClassTemplateSpecializationDecl *
-ClangASTContext::GetAsTemplateSpecialization(
- lldb::opaque_compiler_type_t type) {
- if (!type)
- return nullptr;
-
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record: {
- if (! GetCompleteType(type))
- return nullptr;
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (!cxx_record_decl)
- return nullptr;
- return llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
- cxx_record_decl);
- }
-
- default:
- return nullptr;
- }
-}
-
-lldb::TemplateArgumentKind
-ClangASTContext::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
- size_t arg_idx) {
- const clang::ClassTemplateSpecializationDecl *template_decl =
- GetAsTemplateSpecialization(type);
- if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size())
- return eTemplateArgumentKindNull;
-
- switch (template_decl->getTemplateArgs()[arg_idx].getKind()) {
- case clang::TemplateArgument::Null:
- return eTemplateArgumentKindNull;
-
- case clang::TemplateArgument::NullPtr:
- return eTemplateArgumentKindNullPtr;
-
- case clang::TemplateArgument::Type:
- return eTemplateArgumentKindType;
-
- case clang::TemplateArgument::Declaration:
- return eTemplateArgumentKindDeclaration;
-
- case clang::TemplateArgument::Integral:
- return eTemplateArgumentKindIntegral;
-
- case clang::TemplateArgument::Template:
- return eTemplateArgumentKindTemplate;
-
- case clang::TemplateArgument::TemplateExpansion:
- return eTemplateArgumentKindTemplateExpansion;
-
- case clang::TemplateArgument::Expression:
- return eTemplateArgumentKindExpression;
-
- case clang::TemplateArgument::Pack:
- return eTemplateArgumentKindPack;
- }
- llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind");
-}
-
-CompilerType
-ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx) {
- const clang::ClassTemplateSpecializationDecl *template_decl =
- GetAsTemplateSpecialization(type);
- if (!template_decl || idx >= template_decl->getTemplateArgs().size())
- return CompilerType();
-
- const clang::TemplateArgument &template_arg =
- template_decl->getTemplateArgs()[idx];
- if (template_arg.getKind() != clang::TemplateArgument::Type)
- return CompilerType();
-
- return GetType(template_arg.getAsType());
-}
-
-Optional<CompilerType::IntegralTemplateArgument>
-ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
- size_t idx) {
- const clang::ClassTemplateSpecializationDecl *template_decl =
- GetAsTemplateSpecialization(type);
- if (! template_decl || idx >= template_decl->getTemplateArgs().size())
- return llvm::None;
-
- const clang::TemplateArgument &template_arg =
- template_decl->getTemplateArgs()[idx];
- if (template_arg.getKind() != clang::TemplateArgument::Integral)
- return llvm::None;
-
- return {
- {template_arg.getAsIntegral(), GetType(template_arg.getIntegralType())}};
-}
-
-CompilerType ClangASTContext::GetTypeForFormatters(void *type) {
- if (type)
- return ClangUtil::RemoveFastQualifiers(CompilerType(this, type));
- return CompilerType();
-}
-
-clang::EnumDecl *ClangASTContext::GetAsEnumDecl(const CompilerType &type) {
- const clang::EnumType *enutype =
- llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type));
- if (enutype)
- return enutype->getDecl();
- return nullptr;
-}
-
-clang::RecordDecl *ClangASTContext::GetAsRecordDecl(const CompilerType &type) {
- const clang::RecordType *record_type =
- llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type));
- if (record_type)
- return record_type->getDecl();
- return nullptr;
-}
-
-clang::TagDecl *ClangASTContext::GetAsTagDecl(const CompilerType &type) {
- return ClangUtil::GetAsTagDecl(type);
-}
-
-clang::TypedefNameDecl *
-ClangASTContext::GetAsTypedefDecl(const CompilerType &type) {
- const clang::TypedefType *typedef_type =
- llvm::dyn_cast<clang::TypedefType>(ClangUtil::GetQualType(type));
- if (typedef_type)
- return typedef_type->getDecl();
- return nullptr;
-}
-
-clang::CXXRecordDecl *
-ClangASTContext::GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type) {
- return GetCanonicalQualType(type)->getAsCXXRecordDecl();
-}
-
-clang::ObjCInterfaceDecl *
-ClangASTContext::GetAsObjCInterfaceDecl(const CompilerType &type) {
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(
- ClangUtil::GetCanonicalQualType(type));
- if (objc_class_type)
- return objc_class_type->getInterface();
- return nullptr;
-}
-
-clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
- const CompilerType &type, llvm::StringRef name,
- const CompilerType &field_clang_type, AccessType access,
- uint32_t bitfield_bit_size) {
- if (!type.IsValid() || !field_clang_type.IsValid())
- return nullptr;
- ClangASTContext *ast =
- llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return nullptr;
- clang::ASTContext &clang_ast = ast->getASTContext();
- clang::IdentifierInfo *ident = nullptr;
- if (!name.empty())
- ident = &clang_ast.Idents.get(name);
-
- clang::FieldDecl *field = nullptr;
-
- clang::Expr *bit_width = nullptr;
- if (bitfield_bit_size != 0) {
- llvm::APInt bitfield_bit_size_apint(clang_ast.getTypeSize(clang_ast.IntTy),
- bitfield_bit_size);
- bit_width = new (clang_ast)
- clang::IntegerLiteral(clang_ast, bitfield_bit_size_apint,
- clang_ast.IntTy, clang::SourceLocation());
- }
-
- clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
- if (record_decl) {
- field = clang::FieldDecl::Create(
- clang_ast, record_decl, clang::SourceLocation(),
- clang::SourceLocation(),
- ident, // Identifier
- ClangUtil::GetQualType(field_clang_type), // Field type
- nullptr, // TInfo *
- bit_width, // BitWidth
- false, // Mutable
- clang::ICIS_NoInit); // HasInit
-
- if (name.empty()) {
- // Determine whether this field corresponds to an anonymous struct or
- // union.
- if (const clang::TagType *TagT =
- field->getType()->getAs<clang::TagType>()) {
- if (clang::RecordDecl *Rec =
- llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl()))
- if (!Rec->getDeclName()) {
- Rec->setAnonymousStructOrUnion(true);
- field->setImplicit();
- }
- }
- }
-
- if (field) {
- field->setAccess(
- ClangASTContext::ConvertAccessTypeToAccessSpecifier(access));
-
- record_decl->addDecl(field);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(field);
-#endif
- }
- } else {
- clang::ObjCInterfaceDecl *class_interface_decl =
- ast->GetAsObjCInterfaceDecl(type);
-
- if (class_interface_decl) {
- const bool is_synthesized = false;
-
- field_clang_type.GetCompleteType();
-
- field = clang::ObjCIvarDecl::Create(
- clang_ast, class_interface_decl, clang::SourceLocation(),
- clang::SourceLocation(),
- ident, // Identifier
- ClangUtil::GetQualType(field_clang_type), // Field type
- nullptr, // TypeSourceInfo *
- ConvertAccessTypeToObjCIvarAccessControl(access), bit_width,
- is_synthesized);
-
- if (field) {
- class_interface_decl->addDecl(field);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(field);
-#endif
- }
- }
- }
- return field;
-}
-
-void ClangASTContext::BuildIndirectFields(const CompilerType &type) {
- if (!type)
- return;
-
- ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return;
-
- clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
-
- if (!record_decl)
- return;
-
- typedef llvm::SmallVector<clang::IndirectFieldDecl *, 1> IndirectFieldVector;
-
- IndirectFieldVector indirect_fields;
- clang::RecordDecl::field_iterator field_pos;
- clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end();
- clang::RecordDecl::field_iterator last_field_pos = field_end_pos;
- for (field_pos = record_decl->field_begin(); field_pos != field_end_pos;
- last_field_pos = field_pos++) {
- if (field_pos->isAnonymousStructOrUnion()) {
- clang::QualType field_qual_type = field_pos->getType();
-
- const clang::RecordType *field_record_type =
- field_qual_type->getAs<clang::RecordType>();
-
- if (!field_record_type)
- continue;
-
- clang::RecordDecl *field_record_decl = field_record_type->getDecl();
-
- if (!field_record_decl)
- continue;
-
- for (clang::RecordDecl::decl_iterator
- di = field_record_decl->decls_begin(),
- de = field_record_decl->decls_end();
- di != de; ++di) {
- if (clang::FieldDecl *nested_field_decl =
- llvm::dyn_cast<clang::FieldDecl>(*di)) {
- clang::NamedDecl **chain =
- new (ast->getASTContext()) clang::NamedDecl *[2];
- chain[0] = *field_pos;
- chain[1] = nested_field_decl;
- clang::IndirectFieldDecl *indirect_field =
- clang::IndirectFieldDecl::Create(
- ast->getASTContext(), record_decl, clang::SourceLocation(),
- nested_field_decl->getIdentifier(),
- nested_field_decl->getType(), {chain, 2});
-
- indirect_field->setImplicit();
-
- indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(
- field_pos->getAccess(), nested_field_decl->getAccess()));
-
- indirect_fields.push_back(indirect_field);
- } else if (clang::IndirectFieldDecl *nested_indirect_field_decl =
- llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) {
- size_t nested_chain_size =
- nested_indirect_field_decl->getChainingSize();
- clang::NamedDecl **chain = new (ast->getASTContext())
- clang::NamedDecl *[nested_chain_size + 1];
- chain[0] = *field_pos;
-
- int chain_index = 1;
- for (clang::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++;
- }
-
- clang::IndirectFieldDecl *indirect_field =
- clang::IndirectFieldDecl::Create(
- ast->getASTContext(), record_decl, clang::SourceLocation(),
- nested_indirect_field_decl->getIdentifier(),
- nested_indirect_field_decl->getType(),
- {chain, nested_chain_size + 1});
-
- indirect_field->setImplicit();
-
- indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(
- field_pos->getAccess(), nested_indirect_field_decl->getAccess()));
-
- indirect_fields.push_back(indirect_field);
- }
- }
- }
- }
-
- // Check the last field to see if it has an incomplete array type as its last
- // member and if it does, the tell the record decl about it
- if (last_field_pos != field_end_pos) {
- if (last_field_pos->getType()->isIncompleteArrayType())
- record_decl->hasFlexibleArrayMember();
- }
-
- for (IndirectFieldVector::iterator ifi = indirect_fields.begin(),
- ife = indirect_fields.end();
- ifi < ife; ++ifi) {
- record_decl->addDecl(*ifi);
- }
-}
-
-void ClangASTContext::SetIsPacked(const CompilerType &type) {
- if (type) {
- ClangASTContext *ast =
- llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (ast) {
- clang::RecordDecl *record_decl = GetAsRecordDecl(type);
-
- if (!record_decl)
- return;
-
- record_decl->addAttr(
- clang::PackedAttr::CreateImplicit(ast->getASTContext()));
- }
- }
-}
-
-clang::VarDecl *ClangASTContext::AddVariableToRecordType(
- const CompilerType &type, llvm::StringRef name,
- const CompilerType &var_type, AccessType access) {
- if (!type.IsValid() || !var_type.IsValid())
- return nullptr;
-
- ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return nullptr;
-
- clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
- if (!record_decl)
- return nullptr;
-
- clang::VarDecl *var_decl = nullptr;
- clang::IdentifierInfo *ident = nullptr;
- if (!name.empty())
- ident = &ast->getASTContext().Idents.get(name);
-
- var_decl = clang::VarDecl::Create(
- ast->getASTContext(), // ASTContext &
- record_decl, // DeclContext *
- clang::SourceLocation(), // clang::SourceLocation StartLoc
- clang::SourceLocation(), // clang::SourceLocation IdLoc
- ident, // clang::IdentifierInfo *
- ClangUtil::GetQualType(var_type), // Variable clang::QualType
- nullptr, // TypeSourceInfo *
- clang::SC_Static); // StorageClass
- if (!var_decl)
- return nullptr;
-
- var_decl->setAccess(
- ClangASTContext::ConvertAccessTypeToAccessSpecifier(access));
- record_decl->addDecl(var_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(var_decl);
-#endif
-
- return var_decl;
-}
-
-clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
- lldb::opaque_compiler_type_t type, llvm::StringRef name,
- const char *mangled_name, const CompilerType &method_clang_type,
- lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline,
- bool is_explicit, bool is_attr_used, bool is_artificial) {
- if (!type || !method_clang_type.IsValid() || name.empty())
- return nullptr;
-
- clang::QualType record_qual_type(GetCanonicalQualType(type));
-
- clang::CXXRecordDecl *cxx_record_decl =
- record_qual_type->getAsCXXRecordDecl();
-
- if (cxx_record_decl == nullptr)
- return nullptr;
-
- clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type));
-
- clang::CXXMethodDecl *cxx_method_decl = nullptr;
-
- clang::DeclarationName decl_name(&getASTContext().Idents.get(name));
-
- const clang::FunctionType *function_type =
- llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
-
- if (function_type == nullptr)
- return nullptr;
-
- const clang::FunctionProtoType *method_function_prototype(
- llvm::dyn_cast<clang::FunctionProtoType>(function_type));
-
- if (!method_function_prototype)
- return nullptr;
-
- unsigned int num_params = method_function_prototype->getNumParams();
-
- clang::CXXDestructorDecl *cxx_dtor_decl(nullptr);
- clang::CXXConstructorDecl *cxx_ctor_decl(nullptr);
-
- if (is_artificial)
- return nullptr; // skip everything artificial
-
- const clang::ExplicitSpecifier explicit_spec(
- nullptr /*expr*/, is_explicit
- ? clang::ExplicitSpecKind::ResolvedTrue
- : clang::ExplicitSpecKind::ResolvedFalse);
- if (name.startswith("~")) {
- cxx_dtor_decl = clang::CXXDestructorDecl::Create(
- getASTContext(), cxx_record_decl, clang::SourceLocation(),
- clang::DeclarationNameInfo(
- getASTContext().DeclarationNames.getCXXDestructorName(
- getASTContext().getCanonicalType(record_qual_type)),
- clang::SourceLocation()),
- method_qual_type, nullptr, is_inline, is_artificial,
- ConstexprSpecKind::CSK_unspecified);
- cxx_method_decl = cxx_dtor_decl;
- } else if (decl_name == cxx_record_decl->getDeclName()) {
- cxx_ctor_decl = clang::CXXConstructorDecl::Create(
- getASTContext(), cxx_record_decl, clang::SourceLocation(),
- clang::DeclarationNameInfo(
- getASTContext().DeclarationNames.getCXXConstructorName(
- getASTContext().getCanonicalType(record_qual_type)),
- clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- explicit_spec, is_inline, is_artificial, CSK_unspecified);
- cxx_method_decl = cxx_ctor_decl;
- } else {
- clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
- clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
-
- if (IsOperator(name, op_kind)) {
- if (op_kind != clang::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 method and add it to the class, clang will assert and
- // crash, so we need to make sure things are acceptable.
- const bool is_method = true;
- if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(
- is_method, op_kind, num_params))
- return nullptr;
- cxx_method_decl = clang::CXXMethodDecl::Create(
- getASTContext(), cxx_record_decl, clang::SourceLocation(),
- clang::DeclarationNameInfo(
- getASTContext().DeclarationNames.getCXXOperatorName(op_kind),
- clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- SC, is_inline, CSK_unspecified, clang::SourceLocation());
- } else if (num_params == 0) {
- // Conversion operators don't take params...
- cxx_method_decl = clang::CXXConversionDecl::Create(
- getASTContext(), cxx_record_decl, clang::SourceLocation(),
- clang::DeclarationNameInfo(
- getASTContext().DeclarationNames.getCXXConversionFunctionName(
- getASTContext().getCanonicalType(
- function_type->getReturnType())),
- clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- is_inline, explicit_spec, CSK_unspecified, clang::SourceLocation());
- }
- }
-
- if (cxx_method_decl == nullptr) {
- cxx_method_decl = clang::CXXMethodDecl::Create(
- getASTContext(), cxx_record_decl, clang::SourceLocation(),
- clang::DeclarationNameInfo(decl_name, clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- SC, is_inline, CSK_unspecified, clang::SourceLocation());
- }
- }
-
- clang::AccessSpecifier access_specifier =
- ClangASTContext::ConvertAccessTypeToAccessSpecifier(access);
-
- cxx_method_decl->setAccess(access_specifier);
- cxx_method_decl->setVirtualAsWritten(is_virtual);
-
- if (is_attr_used)
- cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext()));
-
- if (mangled_name != nullptr) {
- cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
- getASTContext(), mangled_name, /*literal=*/false));
- }
-
- // Populate the method decl with parameter decls
-
- llvm::SmallVector<clang::ParmVarDecl *, 12> params;
-
- for (unsigned param_index = 0; param_index < num_params; ++param_index) {
- params.push_back(clang::ParmVarDecl::Create(
- getASTContext(), cxx_method_decl, clang::SourceLocation(),
- clang::SourceLocation(),
- nullptr, // anonymous
- method_function_prototype->getParamType(param_index), nullptr,
- clang::SC_None, nullptr));
- }
-
- cxx_method_decl->setParams(llvm::ArrayRef<clang::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
-
- return cxx_method_decl;
-}
-
-void ClangASTContext::AddMethodOverridesForCXXRecordType(
- lldb::opaque_compiler_type_t type) {
- if (auto *record = GetAsCXXRecordDecl(type))
- for (auto *method : record->methods())
- addOverridesForMethod(method);
-}
-
-#pragma mark C++ Base Classes
-
-std::unique_ptr<clang::CXXBaseSpecifier>
-ClangASTContext::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
- AccessType access, bool is_virtual,
- bool base_of_class) {
- if (!type)
- return nullptr;
-
- return std::make_unique<clang::CXXBaseSpecifier>(
- clang::SourceRange(), is_virtual, base_of_class,
- ClangASTContext::ConvertAccessTypeToAccessSpecifier(access),
- getASTContext().getTrivialTypeSourceInfo(GetQualType(type)),
- clang::SourceLocation());
-}
-
-bool ClangASTContext::TransferBaseClasses(
- lldb::opaque_compiler_type_t type,
- std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases) {
- if (!type)
- return false;
- clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type);
- if (!cxx_record_decl)
- return false;
- std::vector<clang::CXXBaseSpecifier *> raw_bases;
- raw_bases.reserve(bases.size());
-
- // Clang will make a copy of them, so it's ok that we pass pointers that we're
- // about to destroy.
- for (auto &b : bases)
- raw_bases.push_back(b.get());
- cxx_record_decl->setBases(raw_bases.data(), raw_bases.size());
- return true;
-}
-
-bool ClangASTContext::SetObjCSuperClass(
- const CompilerType &type, const CompilerType &superclass_clang_type) {
- ClangASTContext *ast =
- llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return false;
- clang::ASTContext &clang_ast = ast->getASTContext();
-
- if (type && superclass_clang_type.IsValid() &&
- superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- GetAsObjCInterfaceDecl(type);
- clang::ObjCInterfaceDecl *super_interface_decl =
- GetAsObjCInterfaceDecl(superclass_clang_type);
- if (class_interface_decl && super_interface_decl) {
- class_interface_decl->setSuperClass(clang_ast.getTrivialTypeSourceInfo(
- clang_ast.getObjCInterfaceType(super_interface_decl)));
- return true;
- }
- }
- return false;
-}
-
-bool ClangASTContext::AddObjCClassProperty(
- const CompilerType &type, const char *property_name,
- const CompilerType &property_clang_type, clang::ObjCIvarDecl *ivar_decl,
- const char *property_setter_name, const char *property_getter_name,
- uint32_t property_attributes, ClangASTMetadata *metadata) {
- if (!type || !property_clang_type.IsValid() || property_name == nullptr ||
- property_name[0] == '\0')
- return false;
- ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return false;
- clang::ASTContext &clang_ast = ast->getASTContext();
-
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
- if (!class_interface_decl)
- return false;
-
- CompilerType property_clang_type_to_access;
-
- if (property_clang_type.IsValid())
- property_clang_type_to_access = property_clang_type;
- else if (ivar_decl)
- property_clang_type_to_access = ast->GetType(ivar_decl->getType());
-
- if (!class_interface_decl || !property_clang_type_to_access.IsValid())
- return false;
-
- clang::TypeSourceInfo *prop_type_source;
- if (ivar_decl)
- prop_type_source = clang_ast.getTrivialTypeSourceInfo(ivar_decl->getType());
- else
- prop_type_source = clang_ast.getTrivialTypeSourceInfo(
- ClangUtil::GetQualType(property_clang_type));
-
- clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create(
- clang_ast, class_interface_decl,
- clang::SourceLocation(), // Source Location
- &clang_ast.Idents.get(property_name),
- clang::SourceLocation(), // Source Location for AT
- clang::SourceLocation(), // Source location for (
- ivar_decl ? ivar_decl->getType()
- : ClangUtil::GetQualType(property_clang_type),
- prop_type_source);
-
- if (!property_decl)
- return false;
-
- if (metadata)
- ast->SetMetadata(property_decl, *metadata);
-
- class_interface_decl->addDecl(property_decl);
-
- clang::Selector setter_sel, getter_sel;
-
- if (property_setter_name) {
- std::string property_setter_no_colon(property_setter_name,
- strlen(property_setter_name) - 1);
- clang::IdentifierInfo *setter_ident =
- &clang_ast.Idents.get(property_setter_no_colon);
- setter_sel = clang_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 =
- &clang_ast.Idents.get(setter_sel_string);
- setter_sel = clang_ast.Selectors.getSelector(1, &setter_ident);
- }
- property_decl->setSetterName(setter_sel);
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
-
- if (property_getter_name != nullptr) {
- clang::IdentifierInfo *getter_ident =
- &clang_ast.Idents.get(property_getter_name);
- getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
- } else {
- clang::IdentifierInfo *getter_ident = &clang_ast.Idents.get(property_name);
- getter_sel = clang_ast.Selectors.getSelector(0, &getter_ident);
- }
- property_decl->setGetterName(getter_sel);
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
-
- if (ivar_decl)
- property_decl->setPropertyIvarDecl(ivar_decl);
-
- if (property_attributes & DW_APPLE_PROPERTY_readonly)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
- if (property_attributes & DW_APPLE_PROPERTY_readwrite)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
- if (property_attributes & DW_APPLE_PROPERTY_assign)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
- if (property_attributes & DW_APPLE_PROPERTY_retain)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
- if (property_attributes & DW_APPLE_PROPERTY_copy)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
- if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
- if (property_attributes & ObjCPropertyDecl::OBJC_PR_nullability)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
- if (property_attributes & ObjCPropertyDecl::OBJC_PR_null_resettable)
- property_decl->setPropertyAttributes(
- ObjCPropertyDecl::OBJC_PR_null_resettable);
- if (property_attributes & ObjCPropertyDecl::OBJC_PR_class)
- property_decl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_class);
-
- const bool isInstance =
- (property_attributes & ObjCPropertyDecl::OBJC_PR_class) == 0;
-
- clang::ObjCMethodDecl *getter = nullptr;
- if (!getter_sel.isNull())
- getter = isInstance ? class_interface_decl->lookupInstanceMethod(getter_sel)
- : class_interface_decl->lookupClassMethod(getter_sel);
- if (!getter_sel.isNull() && !getter) {
- const bool isVariadic = false;
- const bool isPropertyAccessor = false;
- const bool isSynthesizedAccessorStub = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl =
- clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- getter = clang::ObjCMethodDecl::Create(
- clang_ast, clang::SourceLocation(), clang::SourceLocation(), getter_sel,
- ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
- class_interface_decl, isInstance, isVariadic, isPropertyAccessor,
- isSynthesizedAccessorStub, isImplicitlyDeclared, isDefined, impControl,
- HasRelatedResultType);
-
- if (getter) {
- if (metadata)
- ast->SetMetadata(getter, *metadata);
-
- getter->setMethodParams(clang_ast, llvm::ArrayRef<clang::ParmVarDecl *>(),
- llvm::ArrayRef<clang::SourceLocation>());
- class_interface_decl->addDecl(getter);
- }
- }
- if (getter) {
- getter->setPropertyAccessor(true);
- property_decl->setGetterMethodDecl(getter);
- }
-
- clang::ObjCMethodDecl *setter = nullptr;
- setter = isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel)
- : class_interface_decl->lookupClassMethod(setter_sel);
- if (!setter_sel.isNull() && !setter) {
- clang::QualType result_type = clang_ast.VoidTy;
- const bool isVariadic = false;
- const bool isPropertyAccessor = true;
- const bool isSynthesizedAccessorStub = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl =
- clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- setter = clang::ObjCMethodDecl::Create(
- clang_ast, clang::SourceLocation(), clang::SourceLocation(), setter_sel,
- result_type, nullptr, class_interface_decl, isInstance, isVariadic,
- isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
- isDefined, impControl, HasRelatedResultType);
-
- if (setter) {
- if (metadata)
- ast->SetMetadata(setter, *metadata);
-
- llvm::SmallVector<clang::ParmVarDecl *, 1> params;
- params.push_back(clang::ParmVarDecl::Create(
- clang_ast, setter, clang::SourceLocation(), clang::SourceLocation(),
- nullptr, // anonymous
- ClangUtil::GetQualType(property_clang_type_to_access), nullptr,
- clang::SC_Auto, nullptr));
-
- setter->setMethodParams(clang_ast,
- llvm::ArrayRef<clang::ParmVarDecl *>(params),
- llvm::ArrayRef<clang::SourceLocation>());
-
- class_interface_decl->addDecl(setter);
- }
- }
- if (setter) {
- setter->setPropertyAccessor(true);
- property_decl->setSetterMethodDecl(setter);
- }
-
- return true;
-}
-
-bool ClangASTContext::IsObjCClassTypeAndHasIVars(const CompilerType &type,
- bool check_superclass) {
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
- if (class_interface_decl)
- return ObjCDeclHasIVars(class_interface_decl, check_superclass);
- return false;
-}
-
-clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType(
- const CompilerType &type,
- const char *name, // the full symbol name as seen in the symbol table
- // (lldb::opaque_compiler_type_t type, "-[NString
- // stringWithCString:]")
- const CompilerType &method_clang_type, lldb::AccessType access,
- bool is_artificial, bool is_variadic, bool is_objc_direct_call) {
- if (!type || !method_clang_type.IsValid())
- return nullptr;
-
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
-
- if (class_interface_decl == nullptr)
- return nullptr;
- ClangASTContext *lldb_ast =
- llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (lldb_ast == nullptr)
- return nullptr;
- clang::ASTContext &ast = lldb_ast->getASTContext();
-
- const char *selector_start = ::strchr(name, ' ');
- if (selector_start == nullptr)
- return nullptr;
-
- selector_start++;
- llvm::SmallVector<clang::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(&ast.Idents.get(llvm::StringRef(start, len)));
- if (has_arg)
- len += 1;
- }
-
- if (selector_idents.size() == 0)
- return nullptr;
-
- clang::Selector method_selector = ast.Selectors.getSelector(
- num_selectors_with_args ? selector_idents.size() : 0,
- selector_idents.data());
-
- clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type));
-
- // Populate the method decl with parameter decls
- const clang::Type *method_type(method_qual_type.getTypePtr());
-
- if (method_type == nullptr)
- return nullptr;
-
- const clang::FunctionProtoType *method_function_prototype(
- llvm::dyn_cast<clang::FunctionProtoType>(method_type));
-
- if (!method_function_prototype)
- return nullptr;
-
- const bool isInstance = (name[0] == '-');
- const bool isVariadic = is_variadic;
- const bool isPropertyAccessor = false;
- const bool isSynthesizedAccessorStub = false;
- /// Force this to true because we don't have source locations.
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl =
- clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- const unsigned num_args = method_function_prototype->getNumParams();
-
- if (num_args != num_selectors_with_args)
- return nullptr; // some debug information is corrupt. We are not going to
- // deal with it.
-
- clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create(
- ast,
- clang::SourceLocation(), // beginLoc,
- clang::SourceLocation(), // endLoc,
- method_selector, method_function_prototype->getReturnType(),
- nullptr, // TypeSourceInfo *ResultTInfo,
- lldb_ast->GetDeclContextForType(ClangUtil::GetQualType(type)), isInstance,
- isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
- isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
-
- if (objc_method_decl == nullptr)
- return nullptr;
-
- if (num_args > 0) {
- llvm::SmallVector<clang::ParmVarDecl *, 12> params;
-
- for (unsigned param_index = 0; param_index < num_args; ++param_index) {
- params.push_back(clang::ParmVarDecl::Create(
- ast, objc_method_decl, clang::SourceLocation(),
- clang::SourceLocation(),
- nullptr, // anonymous
- method_function_prototype->getParamType(param_index), nullptr,
- clang::SC_Auto, nullptr));
- }
-
- objc_method_decl->setMethodParams(
- ast, llvm::ArrayRef<clang::ParmVarDecl *>(params),
- llvm::ArrayRef<clang::SourceLocation>());
- }
-
- if (is_objc_direct_call) {
- // Add a the objc_direct attribute to the declaration we generate that
- // we generate a direct method call for this ObjCMethodDecl.
- objc_method_decl->addAttr(
- clang::ObjCDirectAttr::CreateImplicit(ast, SourceLocation()));
- // Usually Sema is creating implicit parameters (e.g., self) when it
- // parses the method. We don't have a parsing Sema when we build our own
- // AST here so we manually need to create these implicit parameters to
- // make the direct call code generation happy.
- objc_method_decl->createImplicitParams(ast, class_interface_decl);
- }
-
- class_interface_decl->addDecl(objc_method_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(objc_method_decl);
-#endif
-
- return objc_method_decl;
-}
-
-bool ClangASTContext::SetHasExternalStorage(lldb::opaque_compiler_type_t type,
- bool has_extern) {
- if (!type)
- return false;
-
- clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record: {
- clang::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: {
- clang::EnumDecl *enum_decl =
- llvm::cast<clang::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 clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- clang::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;
-
- default:
- break;
- }
- return false;
-}
-
-#pragma mark TagDecl
-
-bool ClangASTContext::StartTagDeclarationDefinition(const CompilerType &type) {
- clang::QualType qual_type(ClangUtil::GetQualType(type));
- if (!qual_type.isNull()) {
- const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl) {
- tag_decl->startDefinition();
- return true;
- }
- }
-
- const clang::ObjCObjectType *object_type =
- qual_type->getAs<clang::ObjCObjectType>();
- if (object_type) {
- clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
- if (interface_decl) {
- interface_decl->startDefinition();
- return true;
- }
- }
- }
- return false;
-}
-
-bool ClangASTContext::CompleteTagDeclarationDefinition(
- const CompilerType &type) {
- clang::QualType qual_type(ClangUtil::GetQualType(type));
- if (qual_type.isNull())
- return false;
-
- // Make sure we use the same methodology as
- // ClangASTContext::StartTagDeclarationDefinition() as to how we start/end
- // the definition.
- const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
-
- if (auto *cxx_record_decl = llvm::dyn_cast<CXXRecordDecl>(tag_decl)) {
- if (!cxx_record_decl->isCompleteDefinition())
- cxx_record_decl->completeDefinition();
- cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
- cxx_record_decl->setHasExternalLexicalStorage(false);
- cxx_record_decl->setHasExternalVisibleStorage(false);
- return true;
- }
- }
-
- const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
-
- if (!enutype)
- return false;
- clang::EnumDecl *enum_decl = enutype->getDecl();
-
- if (enum_decl->isCompleteDefinition())
- return true;
-
- ClangASTContext *lldb_ast =
- llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (lldb_ast == nullptr)
- return false;
- clang::ASTContext &ast = lldb_ast->getASTContext();
-
- /// TODO This really needs to be fixed.
-
- QualType integer_type(enum_decl->getIntegerType());
- if (!integer_type.isNull()) {
- unsigned NumPositiveBits = 1;
- unsigned NumNegativeBits = 0;
-
- clang::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;
-}
-
-clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
- const CompilerType &enum_type, const Declaration &decl, const char *name,
- const llvm::APSInt &value) {
-
- if (!enum_type || ConstString(name).IsEmpty())
- return nullptr;
-
- lldbassert(enum_type.GetTypeSystem() == static_cast<TypeSystem *>(this));
-
- lldb::opaque_compiler_type_t enum_opaque_compiler_type =
- enum_type.GetOpaqueQualType();
-
- if (!enum_opaque_compiler_type)
- return nullptr;
-
- clang::QualType enum_qual_type(
- GetCanonicalQualType(enum_opaque_compiler_type));
-
- const clang::Type *clang_type = enum_qual_type.getTypePtr();
-
- if (!clang_type)
- return nullptr;
-
- const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type);
-
- if (!enutype)
- return nullptr;
-
- clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create(
- getASTContext(), enutype->getDecl(), clang::SourceLocation(),
- name ? &getASTContext().Idents.get(name) : nullptr, // Identifier
- clang::QualType(enutype, 0), nullptr, value);
-
- if (!enumerator_decl)
- return nullptr;
-
- enutype->getDecl()->addDecl(enumerator_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(enumerator_decl);
-#endif
-
- return enumerator_decl;
-}
-
-clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
- const CompilerType &enum_type, const Declaration &decl, const char *name,
- int64_t enum_value, uint32_t enum_value_bit_size) {
- CompilerType underlying_type =
- GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
- bool is_signed = false;
- underlying_type.IsIntegerType(is_signed);
-
- llvm::APSInt value(enum_value_bit_size, is_signed);
- value = enum_value;
-
- return AddEnumerationValueToEnumerationType(enum_type, decl, name, value);
-}
-
-CompilerType
-ClangASTContext::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) {
- clang::QualType enum_qual_type(GetCanonicalQualType(type));
- const clang::Type *clang_type = enum_qual_type.getTypePtr();
- if (clang_type) {
- const clang::EnumType *enutype =
- llvm::dyn_cast<clang::EnumType>(clang_type);
- if (enutype) {
- clang::EnumDecl *enum_decl = enutype->getDecl();
- if (enum_decl)
- return GetType(enum_decl->getIntegerType());
- }
- }
- return CompilerType();
-}
-
-CompilerType
-ClangASTContext::CreateMemberPointerType(const CompilerType &type,
- const CompilerType &pointee_type) {
- if (type && pointee_type.IsValid() &&
- type.GetTypeSystem() == pointee_type.GetTypeSystem()) {
- ClangASTContext *ast =
- llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
- if (!ast)
- return CompilerType();
- return ast->GetType(ast->getASTContext().getMemberPointerType(
- ClangUtil::GetQualType(pointee_type),
- ClangUtil::GetQualType(type).getTypePtr()));
- }
- return CompilerType();
-}
-
-// Dumping types
-#define DEPTH_INCREMENT 2
-
-#ifndef NDEBUG
-LLVM_DUMP_METHOD void
-ClangASTContext::dump(lldb::opaque_compiler_type_t type) const {
- if (!type)
- return;
- clang::QualType qual_type(GetQualType(type));
- qual_type.dump();
-}
-#endif
-
-void ClangASTContext::Dump(Stream &s) {
- Decl *tu = Decl::castFromDeclContext(GetTranslationUnitDecl());
- tu->dump(s.AsRawOstream());
-}
-
-void ClangASTContext::DumpFromSymbolFile(Stream &s,
- llvm::StringRef symbol_name) {
- SymbolFile *symfile = GetSymbolFile();
-
- if (!symfile)
- return;
-
- lldb_private::TypeList type_list;
- symfile->GetTypes(nullptr, eTypeClassAny, type_list);
- size_t ntypes = type_list.GetSize();
-
- for (size_t i = 0; i < ntypes; ++i) {
- TypeSP type = type_list.GetTypeAtIndex(i);
-
- if (!symbol_name.empty())
- if (symbol_name != type->GetName().GetStringRef())
- continue;
-
- s << type->GetName().AsCString() << "\n";
-
- CompilerType full_type = type->GetFullCompilerType();
- if (clang::TagDecl *tag_decl = GetAsTagDecl(full_type)) {
- tag_decl->dump(s.AsRawOstream());
- continue;
- }
- if (clang::TypedefNameDecl *typedef_decl = GetAsTypedefDecl(full_type)) {
- typedef_decl->dump(s.AsRawOstream());
- continue;
- }
- if (auto *objc_obj = llvm::dyn_cast<clang::ObjCObjectType>(
- ClangUtil::GetQualType(full_type).getTypePtr())) {
- if (clang::ObjCInterfaceDecl *interface_decl = objc_obj->getInterface()) {
- interface_decl->dump(s.AsRawOstream());
- continue;
- }
- }
- GetCanonicalQualType(full_type.GetOpaqueQualType()).dump(s.AsRawOstream());
- }
-}
-
-void ClangASTContext::DumpValue(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
- lldb::Format format, const lldb_private::DataExtractor &data,
- lldb::offset_t data_byte_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
- bool show_summary, bool verbose, uint32_t depth) {
- if (!type)
- return;
-
- clang::QualType qual_type(GetQualType(type));
- switch (qual_type->getTypeClass()) {
- case clang::Type::Record:
- if (GetCompleteType(type)) {
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- uint32_t field_bit_offset = 0;
- uint32_t field_byte_offset = 0;
- const clang::ASTRecordLayout &record_layout =
- getASTContext().getASTRecordLayout(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl) {
- // We might have base classes to print out first
- clang::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 clang::CXXRecordDecl *base_class_decl =
- llvm::cast<clang::CXXRecordDecl>(
- base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
- // Skip empty base classes
- if (!verbose && !ClangASTContext::RecordHasFields(base_class_decl))
- continue;
-
- if (base_class->isVirtual())
- field_bit_offset =
- record_layout.getVBaseClassOffset(base_class_decl)
- .getQuantity() *
- 8;
- else
- field_bit_offset = record_layout.getBaseClassOffset(base_class_decl)
- .getQuantity() *
- 8;
- field_byte_offset = field_bit_offset / 8;
- assert(field_bit_offset % 8 == 0);
- if (child_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- clang::QualType base_class_qual_type = base_class->getType();
- std::string base_class_type_name(base_class_qual_type.getAsString());
-
- // Indent and print the base class type name
- s->Format("\n{0}{1}", llvm::fmt_repeat(" ", depth + DEPTH_INCREMENT),
- base_class_type_name);
-
- clang::TypeInfo base_class_type_info =
- getASTContext().getTypeInfo(base_class_qual_type);
-
- // Dump the value of the member
- CompilerType base_clang_type = GetType(base_class_qual_type);
- base_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- base_clang_type
- .GetFormat(), // The format with which to display the member
- data, // Data buffer containing all bytes for this type
- data_byte_offset + field_byte_offset, // Offset into "data" where
- // to grab value from
- base_class_type_info.Width / 8, // Size of this type in bytes
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable
- // types
- show_summary, // Boolean indicating if we should show a summary
- // for the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have
- // children
-
- ++child_idx;
- }
- }
- uint32_t field_idx = 0;
- clang::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) {
- // Print the starting squiggly bracket (if this is the first member) or
- // comma (for member 2 and beyond) for the struct/union/class member.
- if (child_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- // Indent
- s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
-
- clang::QualType field_type = field->getType();
- // Print the member type if requested
- // Figure out the type byte size (field_type_info.first) and alignment
- // (field_type_info.second) from the AST context.
- clang::TypeInfo field_type_info =
- getASTContext().getTypeInfo(field_type);
- assert(field_idx < record_layout.getFieldCount());
- // Figure out the field offset within the current struct/union/class
- // type
- field_bit_offset = record_layout.getFieldOffset(field_idx);
- field_byte_offset = field_bit_offset / 8;
- uint32_t field_bitfield_bit_size = 0;
- uint32_t field_bitfield_bit_offset = 0;
- if (FieldIsBitfield(*field, field_bitfield_bit_size))
- field_bitfield_bit_offset = field_bit_offset % 8;
-
- if (show_types) {
- std::string field_type_name(field_type.getAsString());
- if (field_bitfield_bit_size > 0)
- s->Printf("(%s:%u) ", field_type_name.c_str(),
- field_bitfield_bit_size);
- else
- s->Printf("(%s) ", field_type_name.c_str());
- }
- // Print the member name and equal sign
- s->Printf("%s = ", field->getNameAsString().c_str());
-
- // Dump the value of the member
- CompilerType field_clang_type = GetType(field_type);
- field_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- field_clang_type
- .GetFormat(), // The format with which to display the member
- data, // Data buffer containing all bytes for this type
- data_byte_offset + field_byte_offset, // Offset into "data" where to
- // grab value from
- field_type_info.Width / 8, // Size of this type in bytes
- field_bitfield_bit_size, // Bitfield bit size
- field_bitfield_bit_offset, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable
- // types
- show_summary, // Boolean indicating if we should show a summary for
- // the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have
- // children
- }
-
- // Indent the trailing squiggly bracket
- if (child_idx > 0)
- s->Printf("\n%*s}", depth, "");
- }
- return;
-
- case clang::Type::Enum:
- if (GetCompleteType(type)) {
- const clang::EnumType *enutype =
- llvm::cast<clang::EnumType>(qual_type.getTypePtr());
- const clang::EnumDecl *enum_decl = enutype->getDecl();
- assert(enum_decl);
- clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
- lldb::offset_t offset = data_byte_offset;
- const int64_t enum_value = data.GetMaxU64Bitfield(
- &offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
- for (enum_pos = enum_decl->enumerator_begin(),
- enum_end_pos = enum_decl->enumerator_end();
- enum_pos != enum_end_pos; ++enum_pos) {
- if (enum_pos->getInitVal() == enum_value) {
- s->Printf("%s", enum_pos->getNameAsString().c_str());
- return;
- }
- }
- // If we have gotten here we didn't get find the enumerator in the enum
- // decl, so just print the integer.
- s->Printf("%" PRIi64, enum_value);
- }
- return;
-
- case clang::Type::ConstantArray: {
- const clang::ConstantArrayType *array =
- llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr());
- bool is_array_of_characters = false;
- clang::QualType element_qual_type = array->getElementType();
-
- const clang::Type *canonical_type =
- element_qual_type->getCanonicalTypeInternal().getTypePtr();
- if (canonical_type)
- is_array_of_characters = canonical_type->isCharType();
-
- const uint64_t element_count = array->getSize().getLimitedValue();
-
- clang::TypeInfo field_type_info =
- getASTContext().getTypeInfo(element_qual_type);
-
- uint32_t element_idx = 0;
- uint32_t element_offset = 0;
- uint64_t element_byte_size = field_type_info.Width / 8;
- uint32_t element_stride = element_byte_size;
-
- if (is_array_of_characters) {
- s->PutChar('"');
- DumpDataExtractor(data, s, data_byte_offset, lldb::eFormatChar,
- element_byte_size, element_count, UINT32_MAX,
- LLDB_INVALID_ADDRESS, 0, 0);
- s->PutChar('"');
- return;
- } else {
- CompilerType element_clang_type = GetType(element_qual_type);
- lldb::Format element_format = element_clang_type.GetFormat();
-
- for (element_idx = 0; element_idx < element_count; ++element_idx) {
- // Print the starting squiggly bracket (if this is the first member) or
- // comman (for member 2 and beyong) for the struct/union/class member.
- if (element_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- // Indent and print the index
- s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx);
-
- // Figure out the field offset within the current struct/union/class
- // type
- element_offset = element_idx * element_stride;
-
- // Dump the value of the member
- element_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- element_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset +
- element_offset, // Offset into "data" where to grab value from
- element_byte_size, // Size of this type in bytes
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable
- // types
- show_summary, // Boolean indicating if we should show a summary for
- // the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have
- // children
- }
-
- // Indent the trailing squiggly bracket
- if (element_idx > 0)
- s->Printf("\n%*s}", depth, "");
- }
- }
- return;
-
- case clang::Type::Typedef: {
- clang::QualType typedef_qual_type =
- llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType();
-
- CompilerType typedef_clang_type = GetType(typedef_qual_type);
- lldb::Format typedef_format = typedef_clang_type.GetFormat();
- clang::TypeInfo typedef_type_info =
- getASTContext().getTypeInfo(typedef_qual_type);
- uint64_t typedef_byte_size = typedef_type_info.Width / 8;
-
- return typedef_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- typedef_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- typedef_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the
- // current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- } break;
-
- case clang::Type::Auto: {
- clang::QualType elaborated_qual_type =
- llvm::cast<clang::AutoType>(qual_type)->getDeducedType();
- CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
- lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
- clang::TypeInfo elaborated_type_info =
- getASTContext().getTypeInfo(elaborated_qual_type);
- uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
-
- return elaborated_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- elaborated_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- elaborated_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the
- // current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- } break;
-
- case clang::Type::Elaborated: {
- clang::QualType elaborated_qual_type =
- llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
- CompilerType elaborated_clang_type = GetType(elaborated_qual_type);
- lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
- clang::TypeInfo elaborated_type_info =
- getASTContext().getTypeInfo(elaborated_qual_type);
- uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
-
- return elaborated_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- elaborated_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- elaborated_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the
- // current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- } break;
-
- case clang::Type::Paren: {
- clang::QualType desugar_qual_type =
- llvm::cast<clang::ParenType>(qual_type)->desugar();
- CompilerType desugar_clang_type = GetType(desugar_qual_type);
-
- lldb::Format desugar_format = desugar_clang_type.GetFormat();
- clang::TypeInfo desugar_type_info =
- getASTContext().getTypeInfo(desugar_qual_type);
- uint64_t desugar_byte_size = desugar_type_info.Width / 8;
-
- return desugar_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- desugar_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- desugar_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the
- // current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- } break;
-
- default:
- // We are down to a scalar type that we just need to display.
- DumpDataExtractor(data, s, data_byte_offset, format, data_byte_size, 1,
- UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
- bitfield_bit_offset);
-
- if (show_summary)
- DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
- break;
- }
-}
-
-static bool DumpEnumValue(const clang::QualType &qual_type, Stream *s,
- const DataExtractor &data, lldb::offset_t byte_offset,
- size_t byte_size, uint32_t bitfield_bit_offset,
- uint32_t bitfield_bit_size) {
- const clang::EnumType *enutype =
- llvm::cast<clang::EnumType>(qual_type.getTypePtr());
- const clang::EnumDecl *enum_decl = enutype->getDecl();
- assert(enum_decl);
- lldb::offset_t offset = byte_offset;
- const uint64_t enum_svalue = data.GetMaxS64Bitfield(
- &offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
- bool can_be_bitfield = true;
- uint64_t covered_bits = 0;
- int num_enumerators = 0;
-
- // Try to find an exact match for the value.
- // At the same time, we're applying a heuristic to determine whether we want
- // to print this enum as a bitfield. We're likely dealing with a bitfield if
- // every enumrator is either a one bit value or a superset of the previous
- // enumerators. Also 0 doesn't make sense when the enumerators are used as
- // flags.
- for (auto enumerator : enum_decl->enumerators()) {
- uint64_t val = enumerator->getInitVal().getSExtValue();
- val = llvm::SignExtend64(val, 8*byte_size);
- if (llvm::countPopulation(val) != 1 && (val & ~covered_bits) != 0)
- can_be_bitfield = false;
- covered_bits |= val;
- ++num_enumerators;
- if (val == enum_svalue) {
- // Found an exact match, that's all we need to do.
- s->PutCString(enumerator->getNameAsString());
- return true;
- }
- }
-
- // Unsigned values make more sense for flags.
- offset = byte_offset;
- const uint64_t enum_uvalue = data.GetMaxU64Bitfield(
- &offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
-
- // No exact match, but we don't think this is a bitfield. Print the value as
- // decimal.
- if (!can_be_bitfield) {
- if (qual_type->isSignedIntegerOrEnumerationType())
- s->Printf("%" PRIi64, enum_svalue);
- else
- s->Printf("%" PRIu64, enum_uvalue);
- return true;
- }
-
- uint64_t remaining_value = enum_uvalue;
- std::vector<std::pair<uint64_t, llvm::StringRef>> values;
- values.reserve(num_enumerators);
- for (auto enumerator : enum_decl->enumerators())
- if (auto val = enumerator->getInitVal().getZExtValue())
- values.emplace_back(val, enumerator->getName());
-
- // Sort in reverse order of the number of the population count, so that in
- // `enum {A, B, ALL = A|B }` we visit ALL first. Use a stable sort so that
- // A | C where A is declared before C is displayed in this order.
- std::stable_sort(values.begin(), values.end(), [](const auto &a, const auto &b) {
- return llvm::countPopulation(a.first) > llvm::countPopulation(b.first);
- });
-
- for (const auto &val : values) {
- if ((remaining_value & val.first) != val.first)
- continue;
- remaining_value &= ~val.first;
- s->PutCString(val.second);
- if (remaining_value)
- s->PutCString(" | ");
- }
-
- // If there is a remainder that is not covered by the value, print it as hex.
- if (remaining_value)
- s->Printf("0x%" PRIx64, remaining_value);
-
- return true;
-}
-
-bool ClangASTContext::DumpTypeValue(
- lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
- const lldb_private::DataExtractor &data, lldb::offset_t byte_offset,
- size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope) {
- if (!type)
- return false;
- if (IsAggregateType(type)) {
- return false;
- } else {
- clang::QualType qual_type(GetQualType(type));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
- if (type_class == clang::Type::Elaborated) {
- qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
- return DumpTypeValue(qual_type.getAsOpaquePtr(), s, format, data, byte_offset, byte_size,
- bitfield_bit_size, bitfield_bit_offset, exe_scope);
- }
-
- switch (type_class) {
- case clang::Type::Typedef: {
- clang::QualType typedef_qual_type =
- llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType();
- CompilerType typedef_clang_type = GetType(typedef_qual_type);
- if (format == eFormatDefault)
- format = typedef_clang_type.GetFormat();
- clang::TypeInfo typedef_type_info =
- getASTContext().getTypeInfo(typedef_qual_type);
- uint64_t typedef_byte_size = typedef_type_info.Width / 8;
-
- return typedef_clang_type.DumpTypeValue(
- s,
- format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- byte_offset, // Offset into "data" where to grab value from
- typedef_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Size in bits of a bitfield value, if zero don't
- // treat as a bitfield
- bitfield_bit_offset, // Offset in bits of a bitfield value if
- // bitfield_bit_size != 0
- exe_scope);
- } break;
-
- case clang::Type::Enum:
- // If our format is enum or default, show the enumeration value as its
- // enumeration string value, else just display it as requested.
- if ((format == eFormatEnum || format == eFormatDefault) &&
- GetCompleteType(type))
- return DumpEnumValue(qual_type, s, data, byte_offset, byte_size,
- bitfield_bit_offset, bitfield_bit_size);
- // format was not enum, just fall through and dump the value as
- // requested....
- LLVM_FALLTHROUGH;
-
- default:
- // We are down to a scalar type that we just need to display.
- {
- uint32_t item_count = 1;
- // A few formats, we might need to modify our size and count for
- // depending
- // on how we are trying to display the value...
- switch (format) {
- default:
- case eFormatBoolean:
- case eFormatBinary:
- case eFormatComplex:
- case eFormatCString: // NULL terminated C strings
- case eFormatDecimal:
- case eFormatEnum:
- case eFormatHex:
- case eFormatHexUppercase:
- case eFormatFloat:
- case eFormatOctal:
- case eFormatOSType:
- case eFormatUnsigned:
- case eFormatPointer:
- case eFormatVectorOfChar:
- case eFormatVectorOfSInt8:
- case eFormatVectorOfUInt8:
- case eFormatVectorOfSInt16:
- case eFormatVectorOfUInt16:
- case eFormatVectorOfSInt32:
- case eFormatVectorOfUInt32:
- case eFormatVectorOfSInt64:
- case eFormatVectorOfUInt64:
- case eFormatVectorOfFloat32:
- case eFormatVectorOfFloat64:
- case eFormatVectorOfUInt128:
- break;
-
- case eFormatChar:
- case eFormatCharPrintable:
- case eFormatCharArray:
- case eFormatBytes:
- case eFormatBytesWithASCII:
- item_count = byte_size;
- byte_size = 1;
- break;
-
- case eFormatUnicode16:
- item_count = byte_size / 2;
- byte_size = 2;
- break;
-
- case eFormatUnicode32:
- item_count = byte_size / 4;
- byte_size = 4;
- break;
- }
- return DumpDataExtractor(data, s, byte_offset, format, byte_size,
- item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
- bitfield_bit_size, bitfield_bit_offset,
- exe_scope);
- }
- break;
- }
- }
- return false;
-}
-
-void ClangASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
- ExecutionContext *exe_ctx, Stream *s,
- const lldb_private::DataExtractor &data,
- lldb::offset_t data_byte_offset,
- size_t data_byte_size) {
- uint32_t length = 0;
- if (IsCStringType(type, length)) {
- if (exe_ctx) {
- Process *process = exe_ctx->GetProcessPtr();
- if (process) {
- lldb::offset_t offset = data_byte_offset;
- lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size);
- std::vector<uint8_t> buf;
- if (length > 0)
- buf.resize(length);
- else
- buf.resize(256);
-
- DataExtractor cstr_data(&buf.front(), buf.size(),
- process->GetByteOrder(), 4);
- buf.back() = '\0';
- size_t bytes_read;
- size_t total_cstr_len = 0;
- Status error;
- while ((bytes_read = process->ReadMemory(pointer_address, &buf.front(),
- buf.size(), error)) > 0) {
- const size_t len = strlen((const char *)&buf.front());
- if (len == 0)
- break;
- if (total_cstr_len == 0)
- s->PutCString(" \"");
- DumpDataExtractor(cstr_data, s, 0, lldb::eFormatChar, 1, len,
- UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
- total_cstr_len += len;
- if (len < buf.size())
- break;
- pointer_address += total_cstr_len;
- }
- if (total_cstr_len > 0)
- s->PutChar('"');
- }
- }
- }
-}
-
-void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
- StreamFile s(stdout, false);
- DumpTypeDescription(type, &s);
-
- CompilerType ct(this, type);
- const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr();
- ClangASTMetadata *metadata = GetMetadata(clang_type);
- if (metadata) {
- metadata->Dump(&s);
- }
-}
-
-void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) {
- if (type) {
- clang::QualType qual_type =
- RemoveWrappingTypes(GetQualType(type), {clang::Type::Typedef});
-
- llvm::SmallVector<char, 1024> buf;
- llvm::raw_svector_ostream llvm_ostrm(buf);
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface: {
- GetCompleteType(type);
-
- const clang::ObjCObjectType *objc_class_type =
- llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert(objc_class_type);
- if (objc_class_type) {
- clang::ObjCInterfaceDecl *class_interface_decl =
- objc_class_type->getInterface();
- if (class_interface_decl) {
- clang::PrintingPolicy policy = getASTContext().getPrintingPolicy();
- class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
- }
- }
- } break;
-
- case clang::Type::Typedef: {
- const clang::TypedefType *typedef_type =
- qual_type->getAs<clang::TypedefType>();
- if (typedef_type) {
- const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
- std::string clang_typedef_name(
- typedef_decl->getQualifiedNameAsString());
- if (!clang_typedef_name.empty()) {
- s->PutCString("typedef ");
- s->PutCString(clang_typedef_name);
- }
- }
- } break;
-
- case clang::Type::Record: {
- GetCompleteType(type);
-
- const clang::RecordType *record_type =
- llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- const clang::CXXRecordDecl *cxx_record_decl =
- llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- if (cxx_record_decl)
- cxx_record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
- s->GetIndentLevel());
- else
- record_decl->print(llvm_ostrm, getASTContext().getPrintingPolicy(),
- s->GetIndentLevel());
- } break;
-
- default: {
- const clang::TagType *tag_type =
- llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type) {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- tag_decl->print(llvm_ostrm, 0);
- } else {
- std::string clang_type_name(qual_type.getAsString());
- if (!clang_type_name.empty())
- s->PutCString(clang_type_name);
- }
- }
- }
-
- if (buf.size() > 0) {
- s->Write(buf.data(), buf.size());
- }
- }
-}
-
-void ClangASTContext::DumpTypeName(const CompilerType &type) {
- if (ClangUtil::IsClangType(type)) {
- clang::QualType qual_type(
- ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record: {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- printf("class %s", cxx_record_decl->getName().str().c_str());
- } break;
-
- case clang::Type::Enum: {
- clang::EnumDecl *enum_decl =
- llvm::cast<clang::EnumType>(qual_type)->getDecl();
- if (enum_decl) {
- printf("enum %s", enum_decl->getName().str().c_str());
- }
- } break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface: {
- const clang::ObjCObjectType *objc_class_type =
- llvm::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)
- printf("@class %s", class_interface_decl->getName().str().c_str());
- }
- } break;
-
- case clang::Type::Typedef:
- printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getName()
- .str()
- .c_str());
- break;
-
- case clang::Type::Auto:
- printf("auto ");
- return DumpTypeName(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr()));
-
- case clang::Type::Elaborated:
- printf("elaborated ");
- return DumpTypeName(CompilerType(
- type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr()));
-
- case clang::Type::Paren:
- printf("paren ");
- return DumpTypeName(CompilerType(
- type.GetTypeSystem(),
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
-
- default:
- printf("ClangASTContext::DumpTypeName() type_class = %u", type_class);
- break;
- }
- }
-}
-
-clang::ClassTemplateDecl *ClangASTContext::ParseClassTemplateDecl(
- clang::DeclContext *decl_ctx, lldb::AccessType access_type,
- const char *parent_name, int tag_decl_kind,
- const ClangASTContext::TemplateParameterInfos &template_param_infos) {
- if (template_param_infos.IsValid()) {
- std::string template_basename(parent_name);
- template_basename.erase(template_basename.find('<'));
-
- return CreateClassTemplateDecl(decl_ctx, access_type,
- template_basename.c_str(), tag_decl_kind,
- template_param_infos);
- }
- return nullptr;
-}
-
-void ClangASTContext::CompleteTagDecl(clang::TagDecl *decl) {
- SymbolFile *sym_file = GetSymbolFile();
- if (sym_file) {
- CompilerType clang_type = GetTypeForDecl(decl);
- if (clang_type)
- sym_file->CompleteType(clang_type);
- }
-}
-
-void ClangASTContext::CompleteObjCInterfaceDecl(
- clang::ObjCInterfaceDecl *decl) {
- SymbolFile *sym_file = GetSymbolFile();
- if (sym_file) {
- CompilerType clang_type = GetTypeForDecl(decl);
- if (clang_type)
- sym_file->CompleteType(clang_type);
- }
-}
-
-DWARFASTParser *ClangASTContext::GetDWARFParser() {
- if (!m_dwarf_ast_parser_up)
- m_dwarf_ast_parser_up.reset(new DWARFASTParserClang(*this));
- return m_dwarf_ast_parser_up.get();
-}
-
-PDBASTParser *ClangASTContext::GetPDBParser() {
- if (!m_pdb_ast_parser_up)
- m_pdb_ast_parser_up.reset(new PDBASTParser(*this));
- return m_pdb_ast_parser_up.get();
-}
-
-bool ClangASTContext::LayoutRecordType(
- const clang::RecordDecl *record_decl, uint64_t &bit_size,
- uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &vbase_offsets) {
- lldb_private::ClangASTImporter *importer = nullptr;
- if (m_dwarf_ast_parser_up)
- importer = &m_dwarf_ast_parser_up->GetClangASTImporter();
- if (!importer && m_pdb_ast_parser_up)
- importer = &m_pdb_ast_parser_up->GetClangASTImporter();
- if (!importer)
- return false;
-
- return importer->LayoutRecordType(record_decl, bit_size, alignment,
- field_offsets, base_offsets, vbase_offsets);
-}
-
-// CompilerDecl override functions
-
-ConstString ClangASTContext::DeclGetName(void *opaque_decl) {
- if (opaque_decl) {
- clang::NamedDecl *nd =
- llvm::dyn_cast<NamedDecl>((clang::Decl *)opaque_decl);
- if (nd != nullptr)
- return ConstString(nd->getDeclName().getAsString());
- }
- return ConstString();
-}
-
-ConstString ClangASTContext::DeclGetMangledName(void *opaque_decl) {
- if (opaque_decl) {
- clang::NamedDecl *nd =
- llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)opaque_decl);
- if (nd != nullptr && !llvm::isa<clang::ObjCMethodDecl>(nd)) {
- clang::MangleContext *mc = getMangleContext();
- if (mc && mc->shouldMangleCXXName(nd)) {
- llvm::SmallVector<char, 1024> buf;
- llvm::raw_svector_ostream llvm_ostrm(buf);
- if (llvm::isa<clang::CXXConstructorDecl>(nd)) {
- mc->mangleCXXCtor(llvm::dyn_cast<clang::CXXConstructorDecl>(nd),
- Ctor_Complete, llvm_ostrm);
- } else if (llvm::isa<clang::CXXDestructorDecl>(nd)) {
- mc->mangleCXXDtor(llvm::dyn_cast<clang::CXXDestructorDecl>(nd),
- Dtor_Complete, llvm_ostrm);
- } else {
- mc->mangleName(nd, llvm_ostrm);
- }
- if (buf.size() > 0)
- return ConstString(buf.data(), buf.size());
- }
- }
- }
- return ConstString();
-}
-
-CompilerDeclContext ClangASTContext::DeclGetDeclContext(void *opaque_decl) {
- if (opaque_decl)
- return CreateDeclContext(((clang::Decl *)opaque_decl)->getDeclContext());
- return CompilerDeclContext();
-}
-
-CompilerType ClangASTContext::DeclGetFunctionReturnType(void *opaque_decl) {
- if (clang::FunctionDecl *func_decl =
- llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
- return GetType(func_decl->getReturnType());
- if (clang::ObjCMethodDecl *objc_method =
- llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
- return GetType(objc_method->getReturnType());
- else
- return CompilerType();
-}
-
-size_t ClangASTContext::DeclGetFunctionNumArguments(void *opaque_decl) {
- if (clang::FunctionDecl *func_decl =
- llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl))
- return func_decl->param_size();
- if (clang::ObjCMethodDecl *objc_method =
- llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl))
- return objc_method->param_size();
- else
- return 0;
-}
-
-CompilerType ClangASTContext::DeclGetFunctionArgumentType(void *opaque_decl,
- size_t idx) {
- if (clang::FunctionDecl *func_decl =
- llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl)) {
- if (idx < func_decl->param_size()) {
- ParmVarDecl *var_decl = func_decl->getParamDecl(idx);
- if (var_decl)
- return GetType(var_decl->getOriginalType());
- }
- } else if (clang::ObjCMethodDecl *objc_method =
- llvm::dyn_cast<clang::ObjCMethodDecl>(
- (clang::Decl *)opaque_decl)) {
- if (idx < objc_method->param_size())
- return GetType(objc_method->parameters()[idx]->getOriginalType());
- }
- return CompilerType();
-}
-
-// CompilerDeclContext functions
-
-std::vector<CompilerDecl> ClangASTContext::DeclContextFindDeclByName(
- void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) {
- std::vector<CompilerDecl> found_decls;
- if (opaque_decl_ctx) {
- DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
- std::set<DeclContext *> searched;
- std::multimap<DeclContext *, DeclContext *> search_queue;
- SymbolFile *symbol_file = GetSymbolFile();
-
- for (clang::DeclContext *decl_context = root_decl_ctx;
- decl_context != nullptr && found_decls.empty();
- decl_context = decl_context->getParent()) {
- search_queue.insert(std::make_pair(decl_context, decl_context));
-
- for (auto it = search_queue.find(decl_context); it != search_queue.end();
- it++) {
- if (!searched.insert(it->second).second)
- continue;
- symbol_file->ParseDeclsForContext(
- CreateDeclContext(it->second));
-
- for (clang::Decl *child : it->second->decls()) {
- if (clang::UsingDirectiveDecl *ud =
- llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) {
- if (ignore_using_decls)
- continue;
- clang::DeclContext *from = ud->getCommonAncestor();
- if (searched.find(ud->getNominatedNamespace()) == searched.end())
- search_queue.insert(
- std::make_pair(from, ud->getNominatedNamespace()));
- } else if (clang::UsingDecl *ud =
- llvm::dyn_cast<clang::UsingDecl>(child)) {
- if (ignore_using_decls)
- continue;
- for (clang::UsingShadowDecl *usd : ud->shadows()) {
- clang::Decl *target = usd->getTargetDecl();
- if (clang::NamedDecl *nd =
- llvm::dyn_cast<clang::NamedDecl>(target)) {
- IdentifierInfo *ii = nd->getIdentifier();
- if (ii != nullptr &&
- ii->getName().equals(name.AsCString(nullptr)))
- found_decls.push_back(CompilerDecl(this, nd));
- }
- }
- } else if (clang::NamedDecl *nd =
- llvm::dyn_cast<clang::NamedDecl>(child)) {
- IdentifierInfo *ii = nd->getIdentifier();
- if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
- found_decls.push_back(CompilerDecl(this, nd));
- }
- }
- }
- }
- }
- return found_decls;
-}
-
-// Look for child_decl_ctx's lookup scope in frame_decl_ctx and its parents,
-// and return the number of levels it took to find it, or
-// LLDB_INVALID_DECL_LEVEL if not found. If the decl was imported via a using
-// declaration, its name and/or type, if set, will be used to check that the
-// decl found in the scope is a match.
-//
-// The optional name is required by languages (like C++) to handle using
-// declarations like:
-//
-// void poo();
-// namespace ns {
-// void foo();
-// void goo();
-// }
-// void bar() {
-// using ns::foo;
-// // CountDeclLevels returns 0 for 'foo', 1 for 'poo', and
-// // LLDB_INVALID_DECL_LEVEL for 'goo'.
-// }
-//
-// The optional type is useful in the case that there's a specific overload
-// that we're looking for that might otherwise be shadowed, like:
-//
-// void foo(int);
-// namespace ns {
-// void foo();
-// }
-// void bar() {
-// using ns::foo;
-// // CountDeclLevels returns 0 for { 'foo', void() },
-// // 1 for { 'foo', void(int) }, and
-// // LLDB_INVALID_DECL_LEVEL for { 'foo', void(int, int) }.
-// }
-//
-// NOTE: Because file statics are at the TranslationUnit along with globals, a
-// function at file scope will return the same level as a function at global
-// scope. Ideally we'd like to treat the file scope as an additional scope just
-// below the global scope. More work needs to be done to recognise that, if
-// the decl we're trying to look up is static, we should compare its source
-// file with that of the current scope and return a lower number for it.
-uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
- clang::DeclContext *child_decl_ctx,
- ConstString *child_name,
- CompilerType *child_type) {
- if (frame_decl_ctx) {
- std::set<DeclContext *> searched;
- std::multimap<DeclContext *, DeclContext *> search_queue;
- SymbolFile *symbol_file = GetSymbolFile();
-
- // Get the lookup scope for the decl we're trying to find.
- clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent();
-
- // Look for it in our scope's decl context and its parents.
- uint32_t level = 0;
- for (clang::DeclContext *decl_ctx = frame_decl_ctx; decl_ctx != nullptr;
- decl_ctx = decl_ctx->getParent()) {
- if (!decl_ctx->isLookupContext())
- continue;
- if (decl_ctx == parent_decl_ctx)
- // Found it!
- return level;
- search_queue.insert(std::make_pair(decl_ctx, decl_ctx));
- for (auto it = search_queue.find(decl_ctx); it != search_queue.end();
- it++) {
- if (searched.find(it->second) != searched.end())
- continue;
-
- // Currently DWARF has one shared translation unit for all Decls at top
- // level, so this would erroneously find using statements anywhere. So
- // don't look at the top-level translation unit.
- // TODO fix this and add a testcase that depends on it.
-
- if (llvm::isa<clang::TranslationUnitDecl>(it->second))
- continue;
-
- searched.insert(it->second);
- symbol_file->ParseDeclsForContext(
- CreateDeclContext(it->second));
-
- for (clang::Decl *child : it->second->decls()) {
- if (clang::UsingDirectiveDecl *ud =
- llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) {
- clang::DeclContext *ns = ud->getNominatedNamespace();
- if (ns == parent_decl_ctx)
- // Found it!
- return level;
- clang::DeclContext *from = ud->getCommonAncestor();
- if (searched.find(ns) == searched.end())
- search_queue.insert(std::make_pair(from, ns));
- } else if (child_name) {
- if (clang::UsingDecl *ud =
- llvm::dyn_cast<clang::UsingDecl>(child)) {
- for (clang::UsingShadowDecl *usd : ud->shadows()) {
- clang::Decl *target = usd->getTargetDecl();
- clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target);
- if (!nd)
- continue;
- // Check names.
- IdentifierInfo *ii = nd->getIdentifier();
- if (ii == nullptr ||
- !ii->getName().equals(child_name->AsCString(nullptr)))
- continue;
- // Check types, if one was provided.
- if (child_type) {
- CompilerType clang_type = GetTypeForDecl(nd);
- if (!AreTypesSame(clang_type, *child_type,
- /*ignore_qualifiers=*/true))
- continue;
- }
- // Found it!
- return level;
- }
- }
- }
- }
- }
- ++level;
- }
- }
- return LLDB_INVALID_DECL_LEVEL;
-}
-
-ConstString ClangASTContext::DeclContextGetName(void *opaque_decl_ctx) {
- if (opaque_decl_ctx) {
- clang::NamedDecl *named_decl =
- llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
- if (named_decl)
- return ConstString(named_decl->getName());
- }
- return ConstString();
-}
-
-ConstString
-ClangASTContext::DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) {
- if (opaque_decl_ctx) {
- clang::NamedDecl *named_decl =
- llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
- if (named_decl)
- return ConstString(
- llvm::StringRef(named_decl->getQualifiedNameAsString()));
- }
- return ConstString();
-}
-
-bool ClangASTContext::DeclContextIsClassMethod(
- void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
- bool *is_instance_method_ptr, ConstString *language_object_name_ptr) {
- if (opaque_decl_ctx) {
- clang::DeclContext *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
- if (ObjCMethodDecl *objc_method =
- llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx)) {
- if (is_instance_method_ptr)
- *is_instance_method_ptr = objc_method->isInstanceMethod();
- if (language_ptr)
- *language_ptr = eLanguageTypeObjC;
- if (language_object_name_ptr)
- language_object_name_ptr->SetCString("self");
- return true;
- } else if (CXXMethodDecl *cxx_method =
- llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx)) {
- if (is_instance_method_ptr)
- *is_instance_method_ptr = cxx_method->isInstance();
- if (language_ptr)
- *language_ptr = eLanguageTypeC_plus_plus;
- if (language_object_name_ptr)
- language_object_name_ptr->SetCString("this");
- return true;
- } else if (clang::FunctionDecl *function_decl =
- llvm::dyn_cast<clang::FunctionDecl>(decl_ctx)) {
- ClangASTMetadata *metadata = GetMetadata(function_decl);
- if (metadata && metadata->HasObjectPtr()) {
- if (is_instance_method_ptr)
- *is_instance_method_ptr = true;
- if (language_ptr)
- *language_ptr = eLanguageTypeObjC;
- if (language_object_name_ptr)
- language_object_name_ptr->SetCString(metadata->GetObjectPtrName());
- return true;
- }
- }
- }
- return false;
-}
-
-bool ClangASTContext::DeclContextIsContainedInLookup(
- void *opaque_decl_ctx, void *other_opaque_decl_ctx) {
- auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
- auto *other = (clang::DeclContext *)other_opaque_decl_ctx;
-
- do {
- // A decl context always includes its own contents in its lookup.
- if (decl_ctx == other)
- return true;
-
- // If we have an inline namespace, then the lookup of the parent context
- // also includes the inline namespace contents.
- } while (other->isInlineNamespace() && (other = other->getParent()));
-
- return false;
-}
-
-static bool IsClangDeclContext(const CompilerDeclContext &dc) {
- return dc.IsValid() && isa<ClangASTContext>(dc.GetTypeSystem());
-}
-
-clang::DeclContext *
-ClangASTContext::DeclContextGetAsDeclContext(const CompilerDeclContext &dc) {
- if (IsClangDeclContext(dc))
- return (clang::DeclContext *)dc.GetOpaqueDeclContext();
- return nullptr;
-}
-
-ObjCMethodDecl *
-ClangASTContext::DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc) {
- if (IsClangDeclContext(dc))
- return llvm::dyn_cast<clang::ObjCMethodDecl>(
- (clang::DeclContext *)dc.GetOpaqueDeclContext());
- return nullptr;
-}
-
-CXXMethodDecl *
-ClangASTContext::DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc) {
- if (IsClangDeclContext(dc))
- return llvm::dyn_cast<clang::CXXMethodDecl>(
- (clang::DeclContext *)dc.GetOpaqueDeclContext());
- return nullptr;
-}
-
-clang::FunctionDecl *
-ClangASTContext::DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc) {
- if (IsClangDeclContext(dc))
- return llvm::dyn_cast<clang::FunctionDecl>(
- (clang::DeclContext *)dc.GetOpaqueDeclContext());
- return nullptr;
-}
-
-clang::NamespaceDecl *
-ClangASTContext::DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc) {
- if (IsClangDeclContext(dc))
- return llvm::dyn_cast<clang::NamespaceDecl>(
- (clang::DeclContext *)dc.GetOpaqueDeclContext());
- return nullptr;
-}
-
-ClangASTMetadata *
-ClangASTContext::DeclContextGetMetaData(const CompilerDeclContext &dc,
- const Decl *object) {
- ClangASTContext *ast = llvm::cast<ClangASTContext>(dc.GetTypeSystem());
- return ast->GetMetadata(object);
-}
-
-clang::ASTContext *
-ClangASTContext::DeclContextGetClangASTContext(const CompilerDeclContext &dc) {
- ClangASTContext *ast =
- llvm::dyn_cast_or_null<ClangASTContext>(dc.GetTypeSystem());
- if (ast)
- return &ast->getASTContext();
- return nullptr;
-}
-
-ClangASTContextForExpressions::ClangASTContextForExpressions(
- Target &target, llvm::Triple triple)
- : ClangASTContext(triple), m_target_wp(target.shared_from_this()),
- m_persistent_variables(new ClangPersistentVariables) {
- m_scratch_ast_source_up.reset(new ClangASTSource(
- target.shared_from_this(), target.GetClangASTImporter()));
- m_scratch_ast_source_up->InstallASTContext(*this);
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
- m_scratch_ast_source_up->CreateProxy());
- SetExternalSource(proxy_ast_source);
-}
-
-void ClangASTContextForExpressions::Finalize() {
- ClangASTContext::Finalize();
- m_scratch_ast_source_up.reset();
-}
-
-UserExpression *ClangASTContextForExpressions::GetUserExpression(
- llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language,
- Expression::ResultType desired_type,
- const EvaluateExpressionOptions &options,
- ValueObject *ctx_obj) {
- TargetSP target_sp = m_target_wp.lock();
- if (!target_sp)
- return nullptr;
-
- return new ClangUserExpression(*target_sp.get(), expr, prefix, language,
- desired_type, options, ctx_obj);
-}
-
-FunctionCaller *ClangASTContextForExpressions::GetFunctionCaller(
- const CompilerType &return_type, const Address &function_address,
- const ValueList &arg_value_list, const char *name) {
- TargetSP target_sp = m_target_wp.lock();
- if (!target_sp)
- return nullptr;
-
- Process *process = target_sp->GetProcessSP().get();
- if (!process)
- return nullptr;
-
- return new ClangFunctionCaller(*process, return_type, function_address,
- arg_value_list, name);
-}
-
-UtilityFunction *
-ClangASTContextForExpressions::GetUtilityFunction(const char *text,
- const char *name) {
- TargetSP target_sp = m_target_wp.lock();
- if (!target_sp)
- return nullptr;
-
- return new ClangUtilityFunction(*target_sp.get(), text, name);
-}
-
-PersistentExpressionState *
-ClangASTContextForExpressions::GetPersistentExpressionState() {
- return m_persistent_variables.get();
-}
diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp
deleted file mode 100644
index 8cb404231a8d..000000000000
--- a/lldb/source/Symbol/ClangASTImporter.cpp
+++ /dev/null
@@ -1,1165 +0,0 @@
-//===-- ClangASTImporter.cpp ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/Log.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Sema.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <memory>
-
-using namespace lldb_private;
-using namespace clang;
-
-CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast,
- const CompilerType &src_type) {
- clang::ASTContext &dst_clang_ast = dst_ast.getASTContext();
-
- ClangASTContext *src_ast =
- llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
- if (!src_ast)
- return CompilerType();
-
- clang::ASTContext &src_clang_ast = src_ast->getASTContext();
-
- clang::QualType src_qual_type = ClangUtil::GetQualType(src_type);
-
- ImporterDelegateSP delegate_sp(GetDelegate(&dst_clang_ast, &src_clang_ast));
- if (!delegate_sp)
- return CompilerType();
-
- ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast);
-
- llvm::Expected<QualType> ret_or_error = delegate_sp->Import(src_qual_type);
- if (!ret_or_error) {
- Log *log =
- lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, ret_or_error.takeError(),
- "Couldn't import type: {0}");
- return CompilerType();
- }
-
- lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr();
-
- if (dst_clang_type)
- return CompilerType(&dst_ast, dst_clang_type);
- return CompilerType();
-}
-
-clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast,
- clang::Decl *decl) {
- ImporterDelegateSP delegate_sp;
-
- clang::ASTContext *src_ast = &decl->getASTContext();
- delegate_sp = GetDelegate(dst_ast, src_ast);
-
- ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
-
- if (!delegate_sp)
- return nullptr;
-
- llvm::Expected<clang::Decl *> result = delegate_sp->Import(decl);
- if (!result) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- LLDB_LOG_ERROR(log, result.takeError(), "Couldn't import decl: {0}");
- if (log) {
- lldb::user_id_t user_id = LLDB_INVALID_UID;
- ClangASTMetadata *metadata = GetDeclMetadata(decl);
- if (metadata)
- user_id = metadata->GetUserID();
-
- if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl))
- LLDB_LOGF(log,
- " [ClangASTImporter] WARNING: Failed to import a %s "
- "'%s', metadata 0x%" PRIx64,
- decl->getDeclKindName(),
- named_decl->getNameAsString().c_str(), user_id);
- else
- LLDB_LOGF(log,
- " [ClangASTImporter] WARNING: Failed to import a %s, "
- "metadata 0x%" PRIx64,
- decl->getDeclKindName(), user_id);
- }
- return nullptr;
- }
-
- return *result;
-}
-
-class DeclContextOverride {
-private:
- struct Backup {
- clang::DeclContext *decl_context;
- clang::DeclContext *lexical_decl_context;
- };
-
- llvm::DenseMap<clang::Decl *, Backup> m_backups;
-
- void OverrideOne(clang::Decl *decl) {
- if (m_backups.find(decl) != m_backups.end()) {
- return;
- }
-
- m_backups[decl] = {decl->getDeclContext(), decl->getLexicalDeclContext()};
-
- decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl());
- decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl());
- }
-
- bool ChainPassesThrough(
- clang::Decl *decl, clang::DeclContext *base,
- clang::DeclContext *(clang::Decl::*contextFromDecl)(),
- clang::DeclContext *(clang::DeclContext::*contextFromContext)()) {
- for (DeclContext *decl_ctx = (decl->*contextFromDecl)(); decl_ctx;
- decl_ctx = (decl_ctx->*contextFromContext)()) {
- if (decl_ctx == base) {
- return true;
- }
- }
-
- return false;
- }
-
- clang::Decl *GetEscapedChild(clang::Decl *decl,
- clang::DeclContext *base = nullptr) {
- if (base) {
- // decl's DeclContext chains must pass through base.
-
- if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext,
- &clang::DeclContext::getParent) ||
- !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext,
- &clang::DeclContext::getLexicalParent)) {
- return decl;
- }
- } else {
- base = clang::dyn_cast<clang::DeclContext>(decl);
-
- if (!base) {
- return nullptr;
- }
- }
-
- if (clang::DeclContext *context =
- clang::dyn_cast<clang::DeclContext>(decl)) {
- for (clang::Decl *decl : context->decls()) {
- if (clang::Decl *escaped_child = GetEscapedChild(decl)) {
- return escaped_child;
- }
- }
- }
-
- return nullptr;
- }
-
- void Override(clang::Decl *decl) {
- if (clang::Decl *escaped_child = GetEscapedChild(decl)) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- LLDB_LOGF(log,
- " [ClangASTImporter] DeclContextOverride couldn't "
- "override (%sDecl*)%p - its child (%sDecl*)%p escapes",
- decl->getDeclKindName(), static_cast<void *>(decl),
- escaped_child->getDeclKindName(),
- static_cast<void *>(escaped_child));
- lldbassert(0 && "Couldn't override!");
- }
-
- OverrideOne(decl);
- }
-
-public:
- DeclContextOverride() {}
-
- void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) {
- for (DeclContext *decl_context = decl->getLexicalDeclContext();
- decl_context; decl_context = decl_context->getLexicalParent()) {
- DeclContext *redecl_context = decl_context->getRedeclContext();
-
- if (llvm::isa<FunctionDecl>(redecl_context) &&
- llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent())) {
- for (clang::Decl *child_decl : decl_context->decls()) {
- Override(child_decl);
- }
- }
- }
- }
-
- ~DeclContextOverride() {
- for (const std::pair<clang::Decl *, Backup> &backup : m_backups) {
- backup.first->setDeclContext(backup.second.decl_context);
- backup.first->setLexicalDeclContext(backup.second.lexical_decl_context);
- }
- }
-};
-
-namespace {
-/// Completes all imported TagDecls at the end of the scope.
-///
-/// While in a CompleteTagDeclsScope, every decl that could be completed will
-/// be completed at the end of the scope (including all Decls that are
-/// imported while completing the original Decls).
-class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener {
- ClangASTImporter::ImporterDelegateSP m_delegate;
- llvm::SmallVector<NamedDecl *, 32> m_decls_to_complete;
- llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed;
- clang::ASTContext *m_dst_ctx;
- clang::ASTContext *m_src_ctx;
- ClangASTImporter &importer;
-
-public:
- /// Constructs a CompleteTagDeclsScope.
- /// \param importer The ClangASTImporter that we should observe.
- /// \param dst_ctx The ASTContext to which Decls are imported.
- /// \param src_ctx The ASTContext from which Decls are imported.
- explicit CompleteTagDeclsScope(ClangASTImporter &importer,
- clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx)
- : m_delegate(importer.GetDelegate(dst_ctx, src_ctx)), m_dst_ctx(dst_ctx),
- m_src_ctx(src_ctx), importer(importer) {
- m_delegate->SetImportListener(this);
- }
-
- virtual ~CompleteTagDeclsScope() {
- ClangASTImporter::ASTContextMetadataSP to_context_md =
- importer.GetContextMetadata(m_dst_ctx);
-
- // Complete all decls we collected until now.
- while (!m_decls_to_complete.empty()) {
- NamedDecl *decl = m_decls_to_complete.pop_back_val();
- m_decls_already_completed.insert(decl);
-
- // We should only complete decls coming from the source context.
- assert(to_context_md->m_origins[decl].ctx == m_src_ctx);
-
- Decl *original_decl = to_context_md->m_origins[decl].decl;
-
- // Complete the decl now.
- ClangASTContext::GetCompleteDecl(m_src_ctx, original_decl);
- if (auto *tag_decl = dyn_cast<TagDecl>(decl)) {
- if (auto *original_tag_decl = dyn_cast<TagDecl>(original_decl)) {
- if (original_tag_decl->isCompleteDefinition()) {
- m_delegate->ImportDefinitionTo(tag_decl, original_tag_decl);
- tag_decl->setCompleteDefinition(true);
- }
- }
-
- tag_decl->setHasExternalLexicalStorage(false);
- tag_decl->setHasExternalVisibleStorage(false);
- } else if (auto *container_decl = dyn_cast<ObjCContainerDecl>(decl)) {
- container_decl->setHasExternalLexicalStorage(false);
- container_decl->setHasExternalVisibleStorage(false);
- }
-
- to_context_md->m_origins.erase(decl);
- }
-
- // Stop listening to imported decls. We do this after clearing the
- // Decls we needed to import to catch all Decls they might have pulled in.
- m_delegate->RemoveImportListener();
- }
-
- void NewDeclImported(clang::Decl *from, clang::Decl *to) override {
- // Filter out decls that we can't complete later.
- if (!isa<TagDecl>(to) && !isa<ObjCInterfaceDecl>(to))
- return;
- RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
- // We don't need to complete injected class name decls.
- if (from_record_decl && from_record_decl->isInjectedClassName())
- return;
-
- NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
- // Check if we already completed this type.
- if (m_decls_already_completed.count(to_named_decl) != 0)
- return;
- m_decls_to_complete.push_back(to_named_decl);
- }
-};
-} // namespace
-
-CompilerType ClangASTImporter::DeportType(ClangASTContext &dst,
- const CompilerType &src_type) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- ClangASTContext *src_ctxt =
- llvm::cast<ClangASTContext>(src_type.GetTypeSystem());
-
- LLDB_LOG(log,
- " [ClangASTImporter] DeportType called on ({0}Type*){1:x} "
- "from (ASTContext*){2:x} to (ASTContext*){3:x}",
- src_type.GetTypeName(), src_type.GetOpaqueQualType(),
- &src_ctxt->getASTContext(), &dst.getASTContext());
-
- DeclContextOverride decl_context_override;
-
- if (auto *t = ClangUtil::GetQualType(src_type)->getAs<TagType>())
- decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl());
-
- CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(),
- &src_ctxt->getASTContext());
- return CopyType(dst, src_type);
-}
-
-clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
- clang::Decl *decl) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- clang::ASTContext *src_ctx = &decl->getASTContext();
- LLDB_LOGF(log,
- " [ClangASTImporter] DeportDecl called on (%sDecl*)%p from "
- "(ASTContext*)%p to (ASTContext*)%p",
- decl->getDeclKindName(), static_cast<void *>(decl),
- static_cast<void *>(src_ctx), static_cast<void *>(dst_ctx));
-
- DeclContextOverride decl_context_override;
-
- decl_context_override.OverrideAllDeclsFromContainingFunction(decl);
-
- clang::Decl *result;
- {
- CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
- result = CopyDecl(dst_ctx, decl);
- }
-
- if (!result)
- return nullptr;
-
- LLDB_LOGF(
- log,
- " [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p",
- decl->getDeclKindName(), static_cast<void *>(decl),
- result->getDeclKindName(), static_cast<void *>(result));
-
- return result;
-}
-
-bool ClangASTImporter::CanImport(const CompilerType &type) {
- if (!ClangUtil::IsClangType(type))
- return false;
-
- // TODO: remove external completion BOOL
- // CompleteAndFetchChildren should get the Decl out and check for the
-
- clang::QualType qual_type(
- ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record: {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- if (GetDeclOrigin(cxx_record_decl).Valid())
- return true;
- }
- } break;
-
- case clang::Type::Enum: {
- clang::EnumDecl *enum_decl =
- llvm::cast<clang::EnumType>(qual_type)->getDecl();
- if (enum_decl) {
- if (GetDeclOrigin(enum_decl).Valid())
- return true;
- }
- } break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface: {
- const clang::ObjCObjectType *objc_class_type =
- llvm::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 (GetDeclOrigin(class_interface_decl).Valid())
- return true;
- }
- }
- } break;
-
- case clang::Type::Typedef:
- return CanImport(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr()));
-
- case clang::Type::Auto:
- return CanImport(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr()));
-
- case clang::Type::Elaborated:
- return CanImport(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr()));
-
- case clang::Type::Paren:
- return CanImport(CompilerType(
- type.GetTypeSystem(),
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
-
- default:
- break;
- }
-
- return false;
-}
-
-bool ClangASTImporter::Import(const CompilerType &type) {
- if (!ClangUtil::IsClangType(type))
- return false;
- // TODO: remove external completion BOOL
- // CompleteAndFetchChildren should get the Decl out and check for the
-
- clang::QualType qual_type(
- ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class) {
- case clang::Type::Record: {
- const clang::CXXRecordDecl *cxx_record_decl =
- qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl) {
- if (GetDeclOrigin(cxx_record_decl).Valid())
- return CompleteAndFetchChildren(qual_type);
- }
- } break;
-
- case clang::Type::Enum: {
- clang::EnumDecl *enum_decl =
- llvm::cast<clang::EnumType>(qual_type)->getDecl();
- if (enum_decl) {
- if (GetDeclOrigin(enum_decl).Valid())
- return CompleteAndFetchChildren(qual_type);
- }
- } break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface: {
- const clang::ObjCObjectType *objc_class_type =
- llvm::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 (GetDeclOrigin(class_interface_decl).Valid())
- return CompleteAndFetchChildren(qual_type);
- }
- }
- } break;
-
- case clang::Type::Typedef:
- return Import(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::TypedefType>(qual_type)
- ->getDecl()
- ->getUnderlyingType()
- .getAsOpaquePtr()));
-
- case clang::Type::Auto:
- return Import(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::AutoType>(qual_type)
- ->getDeducedType()
- .getAsOpaquePtr()));
-
- case clang::Type::Elaborated:
- return Import(CompilerType(type.GetTypeSystem(),
- llvm::cast<clang::ElaboratedType>(qual_type)
- ->getNamedType()
- .getAsOpaquePtr()));
-
- case clang::Type::Paren:
- return Import(CompilerType(
- type.GetTypeSystem(),
- llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
-
- default:
- break;
- }
- return false;
-}
-
-bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) {
- if (!CanImport(compiler_type))
- return false;
-
- if (Import(compiler_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
- return true;
- }
-
- ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
- false);
- return false;
-}
-
-bool ClangASTImporter::LayoutRecordType(
- const clang::RecordDecl *record_decl, uint64_t &bit_size,
- uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &vbase_offsets) {
- RecordDeclToLayoutMap::iterator pos =
- m_record_decl_to_layout_map.find(record_decl);
- bool success = false;
- base_offsets.clear();
- vbase_offsets.clear();
- if (pos != m_record_decl_to_layout_map.end()) {
- bit_size = pos->second.bit_size;
- alignment = pos->second.alignment;
- field_offsets.swap(pos->second.field_offsets);
- base_offsets.swap(pos->second.base_offsets);
- vbase_offsets.swap(pos->second.vbase_offsets);
- m_record_decl_to_layout_map.erase(pos);
- success = true;
- } else {
- bit_size = 0;
- alignment = 0;
- field_offsets.clear();
- }
- return success;
-}
-
-void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl,
- const LayoutInfo &layout) {
- m_record_decl_to_layout_map.insert(std::make_pair(decl, layout));
-}
-
-void ClangASTImporter::CompleteDecl(clang::Decl *decl) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- LLDB_LOGF(log, " [ClangASTImporter] CompleteDecl called on (%sDecl*)%p",
- decl->getDeclKindName(), static_cast<void *>(decl));
-
- if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) {
- if (!interface_decl->getDefinition()) {
- interface_decl->startDefinition();
- CompleteObjCInterfaceDecl(interface_decl);
- }
- } else if (ObjCProtocolDecl *protocol_decl =
- dyn_cast<ObjCProtocolDecl>(decl)) {
- if (!protocol_decl->getDefinition())
- protocol_decl->startDefinition();
- } else if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) {
- if (!tag_decl->getDefinition() && !tag_decl->isBeingDefined()) {
- tag_decl->startDefinition();
- CompleteTagDecl(tag_decl);
- tag_decl->setCompleteDefinition(true);
- }
- } else {
- assert(0 && "CompleteDecl called on a Decl that can't be completed");
- }
-}
-
-bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
- DeclOrigin decl_origin = GetDeclOrigin(decl);
-
- if (!decl_origin.Valid())
- return false;
-
- if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
- return false;
-
- ImporterDelegateSP delegate_sp(
- GetDelegate(&decl->getASTContext(), decl_origin.ctx));
-
- ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
- &decl->getASTContext());
- if (delegate_sp)
- delegate_sp->ImportDefinitionTo(decl, decl_origin.decl);
-
- return true;
-}
-
-bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
- clang::TagDecl *origin_decl) {
- clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
-
- if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl))
- return false;
-
- ImporterDelegateSP delegate_sp(
- GetDelegate(&decl->getASTContext(), origin_ast_ctx));
-
- if (delegate_sp)
- delegate_sp->ImportDefinitionTo(decl, origin_decl);
-
- ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
- OriginMap &origins = context_md->m_origins;
-
- origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl);
-
- return true;
-}
-
-bool ClangASTImporter::CompleteObjCInterfaceDecl(
- clang::ObjCInterfaceDecl *interface_decl) {
- DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
-
- if (!decl_origin.Valid())
- return false;
-
- if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
- return false;
-
- ImporterDelegateSP delegate_sp(
- GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx));
-
- if (delegate_sp)
- delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
-
- if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
- RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
-
- return true;
-}
-
-bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
- if (!RequireCompleteType(type))
- return false;
-
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-
- if (const TagType *tag_type = type->getAs<TagType>()) {
- TagDecl *tag_decl = tag_type->getDecl();
-
- DeclOrigin decl_origin = GetDeclOrigin(tag_decl);
-
- if (!decl_origin.Valid())
- return false;
-
- ImporterDelegateSP delegate_sp(
- GetDelegate(&tag_decl->getASTContext(), decl_origin.ctx));
-
- ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
- &tag_decl->getASTContext());
-
- TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
-
- for (Decl *origin_child_decl : origin_tag_decl->decls()) {
- llvm::Expected<Decl *> imported_or_err =
- delegate_sp->Import(origin_child_decl);
- if (!imported_or_err) {
- LLDB_LOG_ERROR(log, imported_or_err.takeError(),
- "Couldn't import decl: {0}");
- return false;
- }
- }
-
- if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
- record_decl->setHasLoadedFieldsFromExternalStorage(true);
-
- return true;
- }
-
- if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) {
- if (ObjCInterfaceDecl *objc_interface_decl =
- objc_object_type->getInterface()) {
- DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl);
-
- if (!decl_origin.Valid())
- return false;
-
- ImporterDelegateSP delegate_sp(
- GetDelegate(&objc_interface_decl->getASTContext(), decl_origin.ctx));
-
- ObjCInterfaceDecl *origin_interface_decl =
- llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl);
-
- for (Decl *origin_child_decl : origin_interface_decl->decls()) {
- llvm::Expected<Decl *> imported_or_err =
- delegate_sp->Import(origin_child_decl);
- if (!imported_or_err) {
- LLDB_LOG_ERROR(log, imported_or_err.takeError(),
- "Couldn't import decl: {0}");
- return false;
- }
- }
-
- return true;
- }
- return false;
- }
-
- return true;
-}
-
-bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
- if (type.isNull())
- return false;
-
- if (const TagType *tag_type = type->getAs<TagType>()) {
- TagDecl *tag_decl = tag_type->getDecl();
-
- if (tag_decl->getDefinition() || tag_decl->isBeingDefined())
- return true;
-
- return CompleteTagDecl(tag_decl);
- }
- if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) {
- if (ObjCInterfaceDecl *objc_interface_decl =
- objc_object_type->getInterface())
- return CompleteObjCInterfaceDecl(objc_interface_decl);
- return false;
- }
- if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
- return RequireCompleteType(array_type->getElementType());
- if (const AtomicType *atomic_type = type->getAs<AtomicType>())
- return RequireCompleteType(atomic_type->getPointeeType());
-
- return true;
-}
-
-ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) {
- DeclOrigin decl_origin = GetDeclOrigin(decl);
-
- if (decl_origin.Valid()) {
- ClangASTContext *ast = ClangASTContext::GetASTContext(decl_origin.ctx);
- return ast->GetMetadata(decl_origin.decl);
- }
- ClangASTContext *ast = ClangASTContext::GetASTContext(&decl->getASTContext());
- return ast->GetMetadata(decl);
-}
-
-ClangASTImporter::DeclOrigin
-ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) {
- ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
- OriginMap &origins = context_md->m_origins;
-
- OriginMap::iterator iter = origins.find(decl);
-
- if (iter != origins.end())
- return iter->second;
- return DeclOrigin();
-}
-
-void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl,
- clang::Decl *original_decl) {
- ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
- OriginMap &origins = context_md->m_origins;
-
- OriginMap::iterator iter = origins.find(decl);
-
- if (iter != origins.end()) {
- iter->second.decl = original_decl;
- iter->second.ctx = &original_decl->getASTContext();
- return;
- }
- origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
-}
-
-void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl,
- NamespaceMapSP &namespace_map) {
- ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
- context_md->m_namespace_maps[decl] = namespace_map;
-}
-
-ClangASTImporter::NamespaceMapSP
-ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) {
- ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
- NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps;
-
- NamespaceMetaMap::iterator iter = namespace_maps.find(decl);
-
- if (iter != namespace_maps.end())
- return iter->second;
- return NamespaceMapSP();
-}
-
-void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) {
- assert(decl);
- ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
-
- const DeclContext *parent_context = decl->getDeclContext();
- const NamespaceDecl *parent_namespace =
- dyn_cast<NamespaceDecl>(parent_context);
- NamespaceMapSP parent_map;
-
- if (parent_namespace)
- parent_map = GetNamespaceMap(parent_namespace);
-
- NamespaceMapSP new_map;
-
- new_map = std::make_shared<NamespaceMap>();
-
- if (context_md->m_map_completer) {
- std::string namespace_string = decl->getDeclName().getAsString();
-
- context_md->m_map_completer->CompleteNamespaceMap(
- new_map, ConstString(namespace_string.c_str()), parent_map);
- }
-
- context_md->m_namespace_maps[decl] = new_map;
-}
-
-void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- LLDB_LOGF(log,
- " [ClangASTImporter] Forgetting destination (ASTContext*)%p",
- static_cast<void *>(dst_ast));
-
- m_metadata_map.erase(dst_ast);
-}
-
-void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast) {
- ASTContextMetadataSP md = MaybeGetContextMetadata(dst_ast);
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- LLDB_LOGF(log,
- " [ClangASTImporter] Forgetting source->dest "
- "(ASTContext*)%p->(ASTContext*)%p",
- static_cast<void *>(src_ast), static_cast<void *>(dst_ast));
-
- if (!md)
- return;
-
- md->m_delegates.erase(src_ast);
-
- for (OriginMap::iterator iter = md->m_origins.begin();
- iter != md->m_origins.end();) {
- if (iter->second.ctx == src_ast)
- md->m_origins.erase(iter++);
- else
- ++iter;
- }
-}
-
-ClangASTImporter::MapCompleter::~MapCompleter() { return; }
-
-llvm::Expected<Decl *>
-ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
- if (m_std_handler) {
- llvm::Optional<Decl *> D = m_std_handler->Import(From);
- if (D) {
- // Make sure we don't use this decl later to map it back to it's original
- // decl. The decl the CxxModuleHandler created has nothing to do with
- // the one from debug info, and linking those two would just cause the
- // ASTImporter to try 'updating' the module decl with the minimal one from
- // the debug info.
- m_decls_to_ignore.insert(*D);
- return *D;
- }
- }
-
- // Check which ASTContext this declaration originally came from.
- DeclOrigin origin = m_master.GetDeclOrigin(From);
- // If it originally came from the target ASTContext then we can just
- // pretend that the original is the one we imported. This can happen for
- // example when inspecting a persistent declaration from the scratch
- // ASTContext (which will provide the declaration when parsing the
- // expression and then we later try to copy the declaration back to the
- // scratch ASTContext to store the result).
- // Without this check we would ask the ASTImporter to import a declaration
- // into the same ASTContext where it came from (which doesn't make a lot of
- // sense).
- if (origin.Valid() && origin.ctx == &getToContext()) {
- RegisterImportedDecl(From, origin.decl);
- return origin.decl;
- }
-
- // This declaration came originally from another ASTContext. Instead of
- // copying our potentially incomplete 'From' Decl we instead go to the
- // original ASTContext and copy the original to the target. This is not
- // only faster than first completing our current decl and then copying it
- // to the target, but it also prevents that indirectly copying the same
- // declaration to the same target requires the ASTImporter to merge all
- // the different decls that appear to come from different ASTContexts (even
- // though all these different source ASTContexts just got a copy from
- // one source AST).
- if (origin.Valid()) {
- auto R = m_master.CopyDecl(&getToContext(), origin.decl);
- if (R) {
- RegisterImportedDecl(From, R);
- return R;
- }
- }
-
- return ASTImporter::ImportImpl(From);
-}
-
-void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(
- clang::Decl *to, clang::Decl *from) {
- ASTImporter::Imported(from, to);
-
- /*
- if (to_objc_interface)
- to_objc_interface->startDefinition();
-
- CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
-
- if (to_cxx_record)
- to_cxx_record->startDefinition();
- */
-
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-
- if (llvm::Error err = ImportDefinition(from)) {
- LLDB_LOG_ERROR(log, std::move(err),
- "[ClangASTImporter] Error during importing definition: {0}");
- return;
- }
-
- if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) {
- if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) {
- to_tag->setCompleteDefinition(from_tag->isCompleteDefinition());
-
- if (Log *log_ast =
- lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST)) {
- std::string name_string;
- if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) {
- llvm::raw_string_ostream name_stream(name_string);
- from_named_decl->printName(name_stream);
- name_stream.flush();
- }
- LLDB_LOG(log_ast, "==== [ClangASTImporter][TUDecl: {0}] Imported "
- "({1}Decl*){2}, named {3} (from "
- "(Decl*){4})",
- static_cast<void *>(to->getTranslationUnitDecl()),
- from->getDeclKindName(), static_cast<void *>(to), name_string,
- static_cast<void *>(from));
-
- // Log the AST of the TU.
- std::string ast_string;
- llvm::raw_string_ostream ast_stream(ast_string);
- to->getTranslationUnitDecl()->dump(ast_stream);
- LLDB_LOG(log_ast, "{0}", ast_string);
- }
- }
- }
-
- // If we're dealing with an Objective-C class, ensure that the inheritance
- // has been set up correctly. The ASTImporter may not do this correctly if
- // the class was originally sourced from symbols.
-
- if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) {
- do {
- ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass();
-
- if (to_superclass)
- break; // we're not going to override it if it's set
-
- ObjCInterfaceDecl *from_objc_interface =
- dyn_cast<ObjCInterfaceDecl>(from);
-
- if (!from_objc_interface)
- break;
-
- ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass();
-
- if (!from_superclass)
- break;
-
- llvm::Expected<Decl *> imported_from_superclass_decl =
- Import(from_superclass);
-
- if (!imported_from_superclass_decl) {
- LLDB_LOG_ERROR(log, imported_from_superclass_decl.takeError(),
- "Couldn't import decl: {0}");
- break;
- }
-
- ObjCInterfaceDecl *imported_from_superclass =
- dyn_cast<ObjCInterfaceDecl>(*imported_from_superclass_decl);
-
- if (!imported_from_superclass)
- break;
-
- if (!to_objc_interface->hasDefinition())
- to_objc_interface->startDefinition();
-
- to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo(
- m_source_ctx->getObjCInterfaceType(imported_from_superclass)));
- } while (false);
- }
-}
-
-void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
- clang::Decl *to) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- // Some decls shouldn't be tracked here because they were not created by
- // copying 'from' to 'to'. Just exit early for those.
- if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end())
- return clang::ASTImporter::Imported(from, to);
-
- lldb::user_id_t user_id = LLDB_INVALID_UID;
- ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
- if (metadata)
- user_id = metadata->GetUserID();
-
- if (log) {
- if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) {
- std::string name_string;
- llvm::raw_string_ostream name_stream(name_string);
- from_named_decl->printName(name_stream);
- name_stream.flush();
-
- LLDB_LOGF(log,
- " [ClangASTImporter] Imported (%sDecl*)%p, named %s (from "
- "(Decl*)%p), metadata 0x%" PRIx64,
- from->getDeclKindName(), static_cast<void *>(to),
- name_string.c_str(), static_cast<void *>(from), user_id);
- } else {
- LLDB_LOGF(log,
- " [ClangASTImporter] Imported (%sDecl*)%p (from "
- "(Decl*)%p), metadata 0x%" PRIx64,
- from->getDeclKindName(), static_cast<void *>(to),
- static_cast<void *>(from), user_id);
- }
- }
-
- ASTContextMetadataSP to_context_md =
- m_master.GetContextMetadata(&to->getASTContext());
- ASTContextMetadataSP from_context_md =
- m_master.MaybeGetContextMetadata(m_source_ctx);
-
- if (from_context_md) {
- OriginMap &origins = from_context_md->m_origins;
-
- OriginMap::iterator origin_iter = origins.find(from);
-
- if (origin_iter != origins.end()) {
- if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
- user_id != LLDB_INVALID_UID) {
- if (origin_iter->second.ctx != &to->getASTContext())
- to_context_md->m_origins[to] = origin_iter->second;
- }
-
- ImporterDelegateSP direct_completer =
- m_master.GetDelegate(&to->getASTContext(), origin_iter->second.ctx);
-
- if (direct_completer.get() != this)
- direct_completer->ASTImporter::Imported(origin_iter->second.decl, to);
-
- LLDB_LOGF(log,
- " [ClangASTImporter] Propagated origin "
- "(Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to "
- "(ASTContext*)%p",
- static_cast<void *>(origin_iter->second.decl),
- static_cast<void *>(origin_iter->second.ctx),
- static_cast<void *>(&from->getASTContext()),
- static_cast<void *>(&to->getASTContext()));
- } else {
- if (m_new_decl_listener)
- m_new_decl_listener->NewDeclImported(from, to);
-
- if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
- user_id != LLDB_INVALID_UID) {
- to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
- }
-
- LLDB_LOGF(log,
- " [ClangASTImporter] Decl has no origin information in "
- "(ASTContext*)%p",
- static_cast<void *>(&from->getASTContext()));
- }
-
- if (clang::NamespaceDecl *to_namespace =
- dyn_cast<clang::NamespaceDecl>(to)) {
- clang::NamespaceDecl *from_namespace =
- dyn_cast<clang::NamespaceDecl>(from);
-
- NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps;
-
- NamespaceMetaMap::iterator namespace_map_iter =
- namespace_maps.find(from_namespace);
-
- if (namespace_map_iter != namespace_maps.end())
- to_context_md->m_namespace_maps[to_namespace] =
- namespace_map_iter->second;
- }
- } else {
- to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
-
- LLDB_LOGF(log,
- " [ClangASTImporter] Sourced origin "
- "(Decl*)%p/(ASTContext*)%p into (ASTContext*)%p",
- static_cast<void *>(from), static_cast<void *>(m_source_ctx),
- static_cast<void *>(&to->getASTContext()));
- }
-
- if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from)) {
- TagDecl *to_tag_decl = dyn_cast<TagDecl>(to);
-
- to_tag_decl->setHasExternalLexicalStorage();
- to_tag_decl->getPrimaryContext()->setMustBuildLookupTable();
-
- LLDB_LOGF(
- log,
- " [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
- (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
- (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
- (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
- (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
- }
-
- if (isa<NamespaceDecl>(from)) {
- NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to);
-
- m_master.BuildNamespaceMap(to_namespace_decl);
-
- to_namespace_decl->setHasExternalVisibleStorage();
- }
-
- if (isa<ObjCContainerDecl>(from)) {
- ObjCContainerDecl *to_container_decl = dyn_cast<ObjCContainerDecl>(to);
-
- to_container_decl->setHasExternalLexicalStorage();
- to_container_decl->setHasExternalVisibleStorage();
-
- /*to_interface_decl->setExternallyCompleted();*/
-
- if (log) {
- if (ObjCInterfaceDecl *to_interface_decl =
- llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) {
- LLDB_LOGF(
- log,
- " [ClangASTImporter] To is an ObjCInterfaceDecl - attributes "
- "%s%s%s",
- (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
- (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
- (to_interface_decl->hasDefinition() ? " HasDefinition" : ""));
- } else {
- LLDB_LOGF(
- log, " [ClangASTImporter] To is an %sDecl - attributes %s%s",
- ((Decl *)to_container_decl)->getDeclKindName(),
- (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
- (to_container_decl->hasExternalVisibleStorage() ? " Visible" : ""));
- }
- }
- }
-}
-
-clang::Decl *
-ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) {
- return m_master.GetDeclOrigin(To).decl;
-}
diff --git a/lldb/source/Symbol/ClangASTMetadata.cpp b/lldb/source/Symbol/ClangASTMetadata.cpp
deleted file mode 100644
index 31b012f553fa..000000000000
--- a/lldb/source/Symbol/ClangASTMetadata.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- ClangASTMetadata.cpp ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangASTMetadata.h"
-#include "lldb/Utility/Stream.h"
-
-using namespace lldb_private;
-
-void ClangASTMetadata::Dump(Stream *s) {
- lldb::user_id_t uid = GetUserID();
-
- if (uid != LLDB_INVALID_UID) {
- s->Printf("uid=0x%" PRIx64, uid);
- }
-
- uint64_t isa_ptr = GetISAPtr();
- if (isa_ptr != 0) {
- s->Printf("isa_ptr=0x%" PRIx64, isa_ptr);
- }
-
- const char *obj_ptr_name = GetObjectPtrName();
- if (obj_ptr_name) {
- s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name);
- }
-
- if (m_is_dynamic_cxx) {
- s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx);
- }
- s->EOL();
-}
diff --git a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
deleted file mode 100644
index 008c2acd9b48..000000000000
--- a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===-- ClangExternalASTSourceCallbacks.cpp ---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
-#include "lldb/Symbol/ClangASTContext.h"
-
-#include "clang/AST/Decl.h"
-
-using namespace lldb_private;
-
-void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) {
- m_ast.CompleteTagDecl(tag_decl);
-}
-
-void ClangExternalASTSourceCallbacks::CompleteType(
- clang::ObjCInterfaceDecl *objc_decl) {
- m_ast.CompleteObjCInterfaceDecl(objc_decl);
-}
-
-bool ClangExternalASTSourceCallbacks::layoutRecordType(
- const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
- &VirtualBaseOffsets) {
- return m_ast.LayoutRecordType(Record, Size, Alignment, FieldOffsets,
- BaseOffsets, VirtualBaseOffsets);
-}
-
-void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls(
- const clang::DeclContext *decl_ctx,
- llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
- llvm::SmallVectorImpl<clang::Decl *> &decls) {
- if (decl_ctx) {
- clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(
- const_cast<clang::DeclContext *>(decl_ctx));
- if (tag_decl)
- CompleteType(tag_decl);
- }
-}
diff --git a/lldb/source/Symbol/ClangUtil.cpp b/lldb/source/Symbol/ClangUtil.cpp
deleted file mode 100644
index 52ea4f5111d6..000000000000
--- a/lldb/source/Symbol/ClangUtil.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- ClangUtil.cpp -------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// A collection of helper methods and data structures for manipulating clang
-// types and decls.
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/ClangASTContext.h"
-
-using namespace clang;
-using namespace lldb_private;
-
-bool ClangUtil::IsClangType(const CompilerType &ct) {
- // Invalid types are never Clang types.
- if (!ct)
- return false;
-
- if (llvm::dyn_cast_or_null<ClangASTContext>(ct.GetTypeSystem()) == nullptr)
- return false;
-
- if (!ct.GetOpaqueQualType())
- return false;
-
- return true;
-}
-
-QualType ClangUtil::GetQualType(const CompilerType &ct) {
- // Make sure we have a clang type before making a clang::QualType
- if (!IsClangType(ct))
- return QualType();
-
- return QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
-}
-
-QualType ClangUtil::GetCanonicalQualType(const CompilerType &ct) {
- if (!IsClangType(ct))
- return QualType();
-
- return GetQualType(ct).getCanonicalType();
-}
-
-CompilerType ClangUtil::RemoveFastQualifiers(const CompilerType &ct) {
- if (!IsClangType(ct))
- return ct;
-
- QualType qual_type(GetQualType(ct));
- qual_type.removeLocalFastQualifiers();
- return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr());
-}
-
-clang::TagDecl *ClangUtil::GetAsTagDecl(const CompilerType &type) {
- clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type);
- if (qual_type.isNull())
- return nullptr;
-
- return qual_type->getAsTagDecl();
-}
-
-std::string ClangUtil::DumpDecl(const clang::Decl *d) {
- if (!d)
- return "nullptr";
-
- std::string result;
- llvm::raw_string_ostream stream(result);
- bool deserialize = false;
- d->dump(stream, deserialize);
-
- stream.flush();
- return result;
-}
-
-std::string ClangUtil::ToString(const clang::Type *t) {
- return clang::QualType(t, 0).getAsString();
-}
-
-std::string ClangUtil::ToString(const CompilerType &c) {
- return ClangUtil::GetQualType(c).getAsString();
-}
diff --git a/lldb/source/Symbol/CompactUnwindInfo.cpp b/lldb/source/Symbol/CompactUnwindInfo.cpp
index 3eee7f785f36..1bb7cd1fc05b 100644
--- a/lldb/source/Symbol/CompactUnwindInfo.cpp
+++ b/lldb/source/Symbol/CompactUnwindInfo.cpp
@@ -1,4 +1,4 @@
-//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===//
+//===-- CompactUnwindInfo.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index b05036e27fcf..0c67bf5b702a 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -1,4 +1,4 @@
-//===-- CompileUnit.cpp -----------------------------------------*- C++ -*-===//
+//===-- CompileUnit.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/CompilerDecl.cpp b/lldb/source/Symbol/CompilerDecl.cpp
index 48d9169c1a7a..3cafa9535a72 100644
--- a/lldb/source/Symbol/CompilerDecl.cpp
+++ b/lldb/source/Symbol/CompilerDecl.cpp
@@ -1,4 +1,4 @@
-//===-- CompilerDecl.cpp ----------------------------------------*- C++ -*-===//
+//===-- CompilerDecl.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/CompilerDeclContext.cpp b/lldb/source/Symbol/CompilerDeclContext.cpp
index 581e0872a6a7..a3af568e7c99 100644
--- a/lldb/source/Symbol/CompilerDeclContext.cpp
+++ b/lldb/source/Symbol/CompilerDeclContext.cpp
@@ -1,4 +1,4 @@
-//===-- CompilerDeclContext.cpp ---------------------------------*- C++ -*-===//
+//===-- CompilerDeclContext.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 09930f7a800e..f819c9f8ce23 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -1,4 +1,4 @@
-//===-- CompilerType.cpp ----------------------------------------*- C++ -*-===//
+//===-- CompilerType.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -268,19 +268,6 @@ size_t CompilerType::GetPointerByteSize() const {
return 0;
}
-ConstString CompilerType::GetConstQualifiedTypeName() const {
- return GetConstTypeName();
-}
-
-ConstString CompilerType::GetConstTypeName() const {
- if (IsValid()) {
- ConstString type_name(GetTypeName());
- if (type_name)
- return type_name;
- }
- return ConstString("<invalid>");
-}
-
ConstString CompilerType::GetTypeName() const {
if (IsValid()) {
return m_type_system->GetTypeName(m_type);
@@ -288,7 +275,11 @@ ConstString CompilerType::GetTypeName() const {
return ConstString("<invalid>");
}
-ConstString CompilerType::GetDisplayTypeName() const { return GetTypeName(); }
+ConstString CompilerType::GetDisplayTypeName() const {
+ if (IsValid())
+ return m_type_system->GetDisplayTypeName(m_type);
+ return ConstString("<invalid>");
+}
uint32_t CompilerType::GetTypeInfo(
CompilerType *pointee_or_element_compiler_type) const {
@@ -448,11 +439,11 @@ CompilerType CompilerType::AddRestrictModifier() const {
return CompilerType();
}
-CompilerType
-CompilerType::CreateTypedef(const char *name,
- const CompilerDeclContext &decl_ctx) const {
+CompilerType CompilerType::CreateTypedef(const char *name,
+ const CompilerDeclContext &decl_ctx,
+ uint32_t payload) const {
if (IsValid())
- return m_type_system->CreateTypedef(m_type, name, decl_ctx);
+ return m_type_system->CreateTypedef(m_type, name, decl_ctx, payload);
else
return CompilerType();
}
@@ -715,7 +706,6 @@ CompilerType::GetIndexOfChildWithName(const char *name,
}
// Dumping types
-#define DEPTH_INCREMENT 2
void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s,
lldb::Format format, const DataExtractor &data,
@@ -753,14 +743,15 @@ void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s,
data_byte_size);
}
-void CompilerType::DumpTypeDescription() const {
+void CompilerType::DumpTypeDescription(lldb::DescriptionLevel level) const {
if (IsValid())
- m_type_system->DumpTypeDescription(m_type);
+ m_type_system->DumpTypeDescription(m_type, level);
}
-void CompilerType::DumpTypeDescription(Stream *s) const {
+void CompilerType::DumpTypeDescription(Stream *s,
+ lldb::DescriptionLevel level) const {
if (IsValid()) {
- m_type_system->DumpTypeDescription(m_type, s);
+ m_type_system->DumpTypeDescription(m_type, s, level);
}
}
@@ -874,6 +865,12 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
return false;
}
+#ifndef NDEBUG
+bool CompilerType::Verify() const {
+ return !IsValid() || m_type_system->Verify(m_type);
+}
+#endif
+
bool lldb_private::operator==(const lldb_private::CompilerType &lhs,
const lldb_private::CompilerType &rhs) {
return lhs.GetTypeSystem() == rhs.GetTypeSystem() &&
diff --git a/lldb/source/Symbol/CxxModuleHandler.cpp b/lldb/source/Symbol/CxxModuleHandler.cpp
deleted file mode 100644
index 19e80e5036bc..000000000000
--- a/lldb/source/Symbol/CxxModuleHandler.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-//===-- CxxModuleHandler.cpp ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/CxxModuleHandler.h"
-
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Utility/Log.h"
-#include "clang/Sema/Lookup.h"
-#include "llvm/Support/Error.h"
-
-using namespace lldb_private;
-using namespace clang;
-
-CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target)
- : m_importer(&importer),
- m_sema(ClangASTContext::GetASTContext(target)->getSema()) {
-
- std::initializer_list<const char *> supported_names = {
- // containers
- "deque",
- "forward_list",
- "list",
- "queue",
- "stack",
- "vector",
- // pointers
- "shared_ptr",
- "unique_ptr",
- "weak_ptr",
- // utility
- "allocator",
- };
- m_supported_templates.insert(supported_names.begin(), supported_names.end());
-}
-
-/// Builds a list of scopes that point into the given context.
-///
-/// \param sema The sema that will be using the scopes.
-/// \param ctxt The context that the scope should look into.
-/// \param result A list of scopes. The scopes need to be freed by the caller
-/// (except the TUScope which is owned by the sema).
-static void makeScopes(Sema &sema, DeclContext *ctxt,
- std::vector<Scope *> &result) {
- // FIXME: The result should be a list of unique_ptrs, but the TUScope makes
- // this currently impossible as it's owned by the Sema.
-
- if (auto parent = ctxt->getParent()) {
- makeScopes(sema, parent, result);
-
- Scope *scope =
- new Scope(result.back(), Scope::DeclScope, sema.getDiagnostics());
- scope->setEntity(ctxt);
- result.push_back(scope);
- } else
- result.push_back(sema.TUScope);
-}
-
-/// Uses the Sema to look up the given name in the given DeclContext.
-static std::unique_ptr<LookupResult>
-emulateLookupInCtxt(Sema &sema, llvm::StringRef name, DeclContext *ctxt) {
- IdentifierInfo &ident = sema.getASTContext().Idents.get(name);
-
- std::unique_ptr<LookupResult> lookup_result;
- lookup_result.reset(new LookupResult(sema, DeclarationName(&ident),
- SourceLocation(),
- Sema::LookupOrdinaryName));
-
- // Usually during parsing we already encountered the scopes we would use. But
- // here don't have these scopes so we have to emulate the behavior of the
- // Sema during parsing.
- std::vector<Scope *> scopes;
- makeScopes(sema, ctxt, scopes);
-
- // Now actually perform the lookup with the sema.
- sema.LookupName(*lookup_result, scopes.back());
-
- // Delete all the allocated scopes beside the translation unit scope (which
- // has depth 0).
- for (Scope *s : scopes)
- if (s->getDepth() != 0)
- delete s;
-
- return lookup_result;
-}
-
-/// Error class for handling problems when finding a certain DeclContext.
-struct MissingDeclContext : public llvm::ErrorInfo<MissingDeclContext> {
-
- static char ID;
-
- MissingDeclContext(DeclContext *context, std::string error)
- : m_context(context), m_error(error) {}
-
- DeclContext *m_context;
- std::string m_error;
-
- void log(llvm::raw_ostream &OS) const override {
- OS << llvm::formatv("error when reconstructing context of kind {0}:{1}",
- m_context->getDeclKindName(), m_error);
- }
-
- std::error_code convertToErrorCode() const override {
- return llvm::inconvertibleErrorCode();
- }
-};
-
-char MissingDeclContext::ID = 0;
-
-/// Given a foreign decl context, this function finds the equivalent local
-/// decl context in the ASTContext of the given Sema. Potentially deserializes
-/// decls from the 'std' module if necessary.
-static llvm::Expected<DeclContext *>
-getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt) {
-
- // Inline namespaces don't matter for lookups, so let's skip them.
- while (foreign_ctxt && foreign_ctxt->isInlineNamespace())
- foreign_ctxt = foreign_ctxt->getParent();
-
- // If the foreign context is the TU, we just return the local TU.
- if (foreign_ctxt->isTranslationUnit())
- return sema.getASTContext().getTranslationUnitDecl();
-
- // Recursively find/build the parent DeclContext.
- llvm::Expected<DeclContext *> parent =
- getEqualLocalDeclContext(sema, foreign_ctxt->getParent());
- if (!parent)
- return parent;
-
- // We currently only support building namespaces.
- if (foreign_ctxt->isNamespace()) {
- NamedDecl *ns = llvm::dyn_cast<NamedDecl>(foreign_ctxt);
- llvm::StringRef ns_name = ns->getName();
-
- auto lookup_result = emulateLookupInCtxt(sema, ns_name, *parent);
- for (NamedDecl *named_decl : *lookup_result) {
- if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl))
- return DC->getPrimaryContext();
- }
- return llvm::make_error<MissingDeclContext>(
- foreign_ctxt,
- "Couldn't find namespace " + ns->getQualifiedNameAsString());
- }
-
- return llvm::make_error<MissingDeclContext>(foreign_ctxt, "Unknown context ");
-}
-
-/// Returns true iff tryInstantiateStdTemplate supports instantiating a template
-/// with the given template arguments.
-static bool templateArgsAreSupported(ArrayRef<TemplateArgument> a) {
- for (const TemplateArgument &arg : a) {
- switch (arg.getKind()) {
- case TemplateArgument::Type:
- case TemplateArgument::Integral:
- break;
- default:
- // TemplateArgument kind hasn't been handled yet.
- return false;
- }
- }
- return true;
-}
-
-/// Constructor function for Clang declarations. Ensures that the created
-/// declaration is registered with the ASTImporter.
-template <typename T, typename... Args>
-T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) {
- T *to_d = T::Create(std::forward<Args>(args)...);
- importer.RegisterImportedDecl(from_d, to_d);
- return to_d;
-}
-
-llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
-
- // If we don't have a template to instiantiate, then there is nothing to do.
- auto td = dyn_cast<ClassTemplateSpecializationDecl>(d);
- if (!td)
- return {};
-
- // We only care about templates in the std namespace.
- if (!td->getDeclContext()->isStdNamespace())
- return {};
-
- // We have a whitelist of supported template names.
- if (m_supported_templates.find(td->getName()) == m_supported_templates.end())
- return {};
-
- // Early check if we even support instantiating this template. We do this
- // before we import anything into the target AST.
- auto &foreign_args = td->getTemplateInstantiationArgs();
- if (!templateArgsAreSupported(foreign_args.asArray()))
- return {};
-
- // Find the local DeclContext that corresponds to the DeclContext of our
- // decl we want to import.
- llvm::Expected<DeclContext *> to_context =
- getEqualLocalDeclContext(*m_sema, td->getDeclContext());
- if (!to_context) {
- LLDB_LOG_ERROR(log, to_context.takeError(),
- "Got error while searching equal local DeclContext for decl "
- "'{1}':\n{0}",
- td->getName());
- return {};
- }
-
- // Look up the template in our local context.
- std::unique_ptr<LookupResult> lookup =
- emulateLookupInCtxt(*m_sema, td->getName(), *to_context);
-
- ClassTemplateDecl *new_class_template = nullptr;
- for (auto LD : *lookup) {
- if ((new_class_template = dyn_cast<ClassTemplateDecl>(LD)))
- break;
- }
- if (!new_class_template)
- return {};
-
- // Import the foreign template arguments.
- llvm::SmallVector<TemplateArgument, 4> imported_args;
-
- // If this logic is changed, also update templateArgsAreSupported.
- for (const TemplateArgument &arg : foreign_args.asArray()) {
- switch (arg.getKind()) {
- case TemplateArgument::Type: {
- llvm::Expected<QualType> type = m_importer->Import(arg.getAsType());
- if (!type) {
- LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}");
- return {};
- }
- imported_args.push_back(TemplateArgument(*type));
- break;
- }
- case TemplateArgument::Integral: {
- llvm::APSInt integral = arg.getAsIntegral();
- llvm::Expected<QualType> type =
- m_importer->Import(arg.getIntegralType());
- if (!type) {
- LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}");
- return {};
- }
- imported_args.push_back(
- TemplateArgument(d->getASTContext(), integral, *type));
- break;
- }
- default:
- assert(false && "templateArgsAreSupported not updated?");
- }
- }
-
- // Find the class template specialization declaration that
- // corresponds to these arguments.
- void *InsertPos = nullptr;
- ClassTemplateSpecializationDecl *result =
- new_class_template->findSpecialization(imported_args, InsertPos);
-
- if (result) {
- // We found an existing specialization in the module that fits our arguments
- // so we can treat it as the result and register it with the ASTImporter.
- m_importer->RegisterImportedDecl(d, result);
- return result;
- }
-
- // Instantiate the template.
- result = createDecl<ClassTemplateSpecializationDecl>(
- *m_importer, d, m_sema->getASTContext(),
- new_class_template->getTemplatedDecl()->getTagKind(),
- new_class_template->getDeclContext(),
- new_class_template->getTemplatedDecl()->getLocation(),
- new_class_template->getLocation(), new_class_template, imported_args,
- nullptr);
-
- new_class_template->AddSpecialization(result, InsertPos);
- if (new_class_template->isOutOfLine())
- result->setLexicalDeclContext(
- new_class_template->getLexicalDeclContext());
- return result;
-}
-
-llvm::Optional<Decl *> CxxModuleHandler::Import(Decl *d) {
- if (!isValid())
- return {};
-
- return tryInstantiateStdTemplate(d);
-}
diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index b4e74e9a2898..3111c33c7108 100644
--- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -1,4 +1,4 @@
-//===-- DWARFCallFrameInfo.cpp ----------------------------------*- C++ -*-===//
+//===-- DWARFCallFrameInfo.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -690,7 +690,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *row.get();
row.reset(newrow);
- row->SetOffset(m_cfi_data.GetPointer(&offset) -
+ row->SetOffset(m_cfi_data.GetAddress(&offset) -
startaddr.GetFileAddress());
break;
}
diff --git a/lldb/source/Symbol/DebugMacros.cpp b/lldb/source/Symbol/DebugMacros.cpp
index d119a78868a4..d6a4ca96a30a 100644
--- a/lldb/source/Symbol/DebugMacros.cpp
+++ b/lldb/source/Symbol/DebugMacros.cpp
@@ -1,4 +1,4 @@
-//===-- DebugMacros.cpp -----------------------------------------*- C++ -*-===//
+//===-- DebugMacros.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/DeclVendor.cpp b/lldb/source/Symbol/DeclVendor.cpp
index 9ccf422e3bea..cf87f4f879b1 100644
--- a/lldb/source/Symbol/DeclVendor.cpp
+++ b/lldb/source/Symbol/DeclVendor.cpp
@@ -1,4 +1,4 @@
-//===-- DeclVendor.cpp ------------------------------------------*- C++ -*-===//
+//===-- DeclVendor.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/Declaration.cpp b/lldb/source/Symbol/Declaration.cpp
index 4d0975d34256..48d8013811d9 100644
--- a/lldb/source/Symbol/Declaration.cpp
+++ b/lldb/source/Symbol/Declaration.cpp
@@ -1,4 +1,4 @@
-//===-- Declaration.cpp -----------------------------------------*- C++ -*-===//
+//===-- Declaration.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index 7a6f3cefea66..30266120d05e 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -1,4 +1,4 @@
-//===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
+//===-- FuncUnwinders.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index e92585ccfed7..67013f6dd8b1 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -1,4 +1,4 @@
-//===-- Function.cpp --------------------------------------------*- C++ -*-===//
+//===-- Function.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -82,25 +82,24 @@ void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
m_mangled.Dump(s);
}
-void InlineFunctionInfo::DumpStopContext(Stream *s,
- LanguageType language) const {
+void InlineFunctionInfo::DumpStopContext(Stream *s) const {
// s->Indent("[inlined] ");
s->Indent();
if (m_mangled)
- s->PutCString(m_mangled.GetName(language).AsCString());
+ s->PutCString(m_mangled.GetName().AsCString());
else
s->PutCString(m_name.AsCString());
}
-ConstString InlineFunctionInfo::GetName(LanguageType language) const {
+ConstString InlineFunctionInfo::GetName() const {
if (m_mangled)
- return m_mangled.GetName(language);
+ return m_mangled.GetName();
return m_name;
}
-ConstString InlineFunctionInfo::GetDisplayName(LanguageType language) const {
+ConstString InlineFunctionInfo::GetDisplayName() const {
if (m_mangled)
- return m_mangled.GetDisplayDemangledName(language);
+ return m_mangled.GetDisplayDemangledName();
return m_name;
}
@@ -121,10 +120,32 @@ size_t InlineFunctionInfo::MemorySize() const {
/// @name Call site related structures
/// @{
+lldb::addr_t CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc,
+ Function &caller, Target &target) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+
+ const Address &caller_start_addr = caller.GetAddressRange().GetBaseAddress();
+
+ ModuleSP caller_module_sp = caller_start_addr.GetModule();
+ if (!caller_module_sp) {
+ LLDB_LOG(log, "GetLoadAddress: cannot get Module for caller");
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ SectionList *section_list = caller_module_sp->GetSectionList();
+ if (!section_list) {
+ LLDB_LOG(log, "GetLoadAddress: cannot get SectionList for Module");
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ Address the_addr = Address(unresolved_pc, section_list);
+ lldb::addr_t load_addr = the_addr.GetLoadAddress(&target);
+ return load_addr;
+}
+
lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller,
Target &target) const {
- const Address &base = caller.GetAddressRange().GetBaseAddress();
- return base.GetLoadAddress(&target) + return_pc;
+ return GetLoadAddress(GetUnresolvedReturnPCAddress(), caller, target);
}
void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
@@ -269,6 +290,8 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) {
}
llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() {
+ std::lock_guard<std::mutex> guard(m_call_edges_lock);
+
if (m_call_edges_resolved)
return m_call_edges;
@@ -288,36 +311,34 @@ llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() {
m_call_edges = sym_file->ParseCallEdgesInFunction(GetID());
// Sort the call edges to speed up return_pc lookups.
- llvm::sort(m_call_edges.begin(), m_call_edges.end(),
- [](const std::unique_ptr<CallEdge> &LHS,
- const std::unique_ptr<CallEdge> &RHS) {
- return LHS->GetUnresolvedReturnPCAddress() <
- RHS->GetUnresolvedReturnPCAddress();
- });
+ llvm::sort(m_call_edges, [](const std::unique_ptr<CallEdge> &LHS,
+ const std::unique_ptr<CallEdge> &RHS) {
+ return LHS->GetSortKey() < RHS->GetSortKey();
+ });
return m_call_edges;
}
llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetTailCallingEdges() {
- // Call edges are sorted by return PC, and tail calling edges have invalid
- // return PCs. Find them at the end of the list.
- return GetCallEdges().drop_until([](const std::unique_ptr<CallEdge> &edge) {
- return edge->GetUnresolvedReturnPCAddress() == LLDB_INVALID_ADDRESS;
- });
+ // Tail calling edges are sorted at the end of the list. Find them by dropping
+ // all non-tail-calls.
+ return GetCallEdges().drop_until(
+ [](const std::unique_ptr<CallEdge> &edge) { return edge->IsTailCall(); });
}
CallEdge *Function::GetCallEdgeForReturnAddress(addr_t return_pc,
Target &target) {
auto edges = GetCallEdges();
auto edge_it =
- std::lower_bound(edges.begin(), edges.end(), return_pc,
- [&](const std::unique_ptr<CallEdge> &edge, addr_t pc) {
- return edge->GetReturnPCAddress(*this, target) < pc;
- });
+ llvm::partition_point(edges, [&](const std::unique_ptr<CallEdge> &edge) {
+ return std::make_pair(edge->IsTailCall(),
+ edge->GetReturnPCAddress(*this, target)) <
+ std::make_pair(false, return_pc);
+ });
if (edge_it == edges.end() ||
edge_it->get()->GetReturnPCAddress(*this, target) != return_pc)
return nullptr;
- return &const_cast<CallEdge &>(*edge_it->get());
+ return edge_it->get();
}
Block &Function::GetBlock(bool can_create) {
@@ -349,9 +370,9 @@ void Function::GetDescription(Stream *s, lldb::DescriptionLevel level,
*s << "id = " << (const UserID &)*this;
if (name)
- *s << ", name = \"" << name.GetCString() << '"';
+ s->AsRawOstream() << ", name = \"" << name << '"';
if (mangled)
- *s << ", mangled = \"" << mangled.GetCString() << '"';
+ s->AsRawOstream() << ", mangled = \"" << mangled << '"';
*s << ", range = ";
Address::DumpStyle fallback_style;
if (level == eDescriptionLevelVerbose)
@@ -404,11 +425,11 @@ lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx,
const char *flavor,
bool prefer_file_cache) {
ModuleSP module_sp(GetAddressRange().GetBaseAddress().GetModule());
- if (module_sp) {
+ if (module_sp && exe_ctx.HasTargetScope()) {
const bool prefer_file_cache = false;
return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
- flavor, exe_ctx, GetAddressRange(),
- prefer_file_cache);
+ flavor, exe_ctx.GetTargetRef(),
+ GetAddressRange(), prefer_file_cache);
}
return lldb::DisassemblerSP();
}
@@ -465,7 +486,7 @@ bool Function::IsTopLevelFunction() {
}
ConstString Function::GetDisplayName() const {
- return m_mangled.GetDisplayDemangledName(GetLanguage());
+ return m_mangled.GetDisplayDemangledName();
}
CompilerDeclContext Function::GetDeclContext() {
@@ -633,15 +654,9 @@ lldb::LanguageType Function::GetLanguage() const {
}
ConstString Function::GetName() const {
- LanguageType language = lldb::eLanguageTypeUnknown;
- if (m_comp_unit)
- language = m_comp_unit->GetLanguage();
- return m_mangled.GetName(language);
+ return m_mangled.GetName();
}
ConstString Function::GetNameNoArguments() const {
- LanguageType language = lldb::eLanguageTypeUnknown;
- if (m_comp_unit)
- language = m_comp_unit->GetLanguage();
- return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments);
+ return m_mangled.GetName(Mangled::ePreferDemangledWithoutArguments);
}
diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp
index bb3828fef784..a3907f4dd9c0 100644
--- a/lldb/source/Symbol/LineEntry.cpp
+++ b/lldb/source/Symbol/LineEntry.cpp
@@ -1,4 +1,4 @@
-//===-- LineEntry.cpp -------------------------------------------*- C++ -*-===//
+//===-- LineEntry.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp
index fecc90c409f2..19c39bd0aeb5 100644
--- a/lldb/source/Symbol/LineTable.cpp
+++ b/lldb/source/Symbol/LineTable.cpp
@@ -1,4 +1,4 @@
-//===-- LineTable.cpp -------------------------------------------*- C++ -*-===//
+//===-- LineTable.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -21,6 +21,18 @@ using namespace lldb_private;
LineTable::LineTable(CompileUnit *comp_unit)
: m_comp_unit(comp_unit), m_entries() {}
+LineTable::LineTable(CompileUnit *comp_unit,
+ std::vector<std::unique_ptr<LineSequence>> &&sequences)
+ : m_comp_unit(comp_unit), m_entries() {
+ LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
+ llvm::stable_sort(sequences, less_than_bp);
+ for (const auto &sequence : sequences) {
+ LineSequenceImpl *seq = static_cast<LineSequenceImpl *>(sequence.get());
+ m_entries.insert(m_entries.end(), seq->m_entries.begin(),
+ seq->m_entries.end());
+ }
+}
+
// Destructor
LineTable::~LineTable() {}
@@ -50,8 +62,8 @@ LineSequence::LineSequence() {}
void LineTable::LineSequenceImpl::Clear() { m_entries.clear(); }
-LineSequence *LineTable::CreateLineSequenceContainer() {
- return new LineTable::LineSequenceImpl();
+std::unique_ptr<LineSequence> LineTable::CreateLineSequenceContainer() {
+ return std::make_unique<LineTable::LineSequenceImpl>();
}
void LineTable::AppendLineEntryToSequence(
@@ -154,6 +166,14 @@ operator()(const LineTable::Entry &a, const LineTable::Entry &b) const {
#undef LT_COMPARE
}
+bool LineTable::Entry::LessThanBinaryPredicate::
+operator()(const std::unique_ptr<LineSequence> &sequence_a,
+ const std::unique_ptr<LineSequence> &sequence_b) const {
+ auto *seq_a = static_cast<const LineSequenceImpl *>(sequence_a.get());
+ auto *seq_b = static_cast<const LineSequenceImpl *>(sequence_b.get());
+ return (*this)(seq_a->m_entries.front(), seq_b->m_entries.front());
+}
+
uint32_t LineTable::GetSize() const { return m_entries.size(); }
bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) {
diff --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp
index d2b39d6acd70..95ae2ca7917a 100644
--- a/lldb/source/Symbol/LocateSymbolFile.cpp
+++ b/lldb/source/Symbol/LocateSymbolFile.cpp
@@ -1,4 +1,4 @@
-//===-- LocateSymbolFile.cpp ------------------------------------*- C++ -*-===//
+//===-- LocateSymbolFile.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp b/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
index 5ee632ec2077..251605085c58 100644
--- a/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
+++ b/lldb/source/Symbol/LocateSymbolFileMacOSX.cpp
@@ -1,4 +1,4 @@
-//===-- LocateSymbolFileMacOSX.cpp ------------------------------*- C++ -*-===//
+//===-- LocateSymbolFileMacOSX.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -253,48 +253,34 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
FileSpec Symbols::FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,
const lldb_private::UUID *uuid,
const ArchSpec *arch) {
- char path[PATH_MAX];
- if (dsym_bundle_fspec.GetPath(path, sizeof(path)) == 0)
- return {};
-
- ::strncat(path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
-
- DIR *dirp = opendir(path);
- if (!dirp)
- return {};
-
- // Make sure we close the directory before exiting this scope.
- auto cleanup_dir = llvm::make_scope_exit([&]() { closedir(dirp); });
-
- FileSpec dsym_fspec;
- dsym_fspec.GetDirectory().SetCString(path);
- struct dirent *dp;
- while ((dp = readdir(dirp)) != NULL) {
- // Only search directories
- if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) {
- if (dp->d_namlen == 1 && dp->d_name[0] == '.')
- continue;
-
- if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
- continue;
- }
-
- if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN) {
- dsym_fspec.GetFilename().SetCString(dp->d_name);
- ModuleSpecList module_specs;
- if (ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs)) {
- ModuleSpec spec;
- for (size_t i = 0; i < module_specs.GetSize(); ++i) {
- bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec);
- UNUSED_IF_ASSERT_DISABLED(got_spec);
- assert(got_spec);
- if ((uuid == NULL ||
- (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
- (arch == NULL ||
- (spec.GetArchitecturePtr() &&
- spec.GetArchitecture().IsCompatibleMatch(*arch)))) {
- return dsym_fspec;
- }
+ std::string dsym_bundle_path = dsym_bundle_fspec.GetPath();
+ llvm::SmallString<128> buffer(dsym_bundle_path);
+ llvm::sys::path::append(buffer, "Contents", "Resources", "DWARF");
+
+ std::error_code EC;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs =
+ FileSystem::Instance().GetVirtualFileSystem();
+ llvm::vfs::recursive_directory_iterator Iter(*vfs, buffer.str(), EC);
+ llvm::vfs::recursive_directory_iterator End;
+ for (; Iter != End && !EC; Iter.increment(EC)) {
+ llvm::ErrorOr<llvm::vfs::Status> Status = vfs->status(Iter->path());
+ if (Status->isDirectory())
+ continue;
+
+ FileSpec dsym_fspec(Iter->path());
+ ModuleSpecList module_specs;
+ if (ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs)) {
+ ModuleSpec spec;
+ for (size_t i = 0; i < module_specs.GetSize(); ++i) {
+ bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec);
+ assert(got_spec); // The call has side-effects so can't be inlined.
+ UNUSED_IF_ASSERT_DISABLED(got_spec);
+ if ((uuid == nullptr ||
+ (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
+ (arch == nullptr ||
+ (spec.GetArchitecturePtr() &&
+ spec.GetArchitecture().IsCompatibleMatch(*arch)))) {
+ return dsym_fspec;
}
}
}
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index 8a72b5fe6f67..6b552dd0c19e 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -1,4 +1,4 @@
-//===-- ObjectFile.cpp ------------------------------------------*- C++ -*-===//
+//===-- ObjectFile.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -47,8 +47,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
FileSpec archive_file;
ObjectContainerCreateInstance create_object_container_callback;
- const bool file_exists = FileSystem::Instance().Exists(*file);
if (!data_sp) {
+ const bool file_exists = FileSystem::Instance().Exists(*file);
// We have an object name which most likely means we have a .o file in
// a static archive (.a file). Try and see if we have a cached archive
// first without reading any data first
@@ -207,9 +207,11 @@ ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp,
size_t ObjectFile::GetModuleSpecifications(const FileSpec &file,
lldb::offset_t file_offset,
lldb::offset_t file_size,
- ModuleSpecList &specs) {
- DataBufferSP data_sp =
- FileSystem::Instance().CreateDataBuffer(file.GetPath(), 512, file_offset);
+ ModuleSpecList &specs,
+ DataBufferSP data_sp) {
+ if (!data_sp)
+ data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath(), 512,
+ file_offset);
if (data_sp) {
if (file_size == 0) {
const lldb::offset_t actual_file_size =
@@ -367,6 +369,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
case eSectionTypeDWARFDebugStrDwo:
case eSectionTypeDWARFDebugStrOffsets:
case eSectionTypeDWARFDebugStrOffsetsDwo:
+ case eSectionTypeDWARFDebugTuIndex:
case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFDebugTypesDwo:
case eSectionTypeDWARFAppleNames:
diff --git a/lldb/source/Symbol/PostfixExpression.cpp b/lldb/source/Symbol/PostfixExpression.cpp
index 8ecd571ed929..588b3f92c3f4 100644
--- a/lldb/source/Symbol/PostfixExpression.cpp
+++ b/lldb/source/Symbol/PostfixExpression.cpp
@@ -1,4 +1,4 @@
-//===-- PostfixExpression.cpp -----------------------------------*- C++ -*-===//
+//===-- PostfixExpression.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 3ace153d32ab..8d099e0cc7e1 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -1,4 +1,4 @@
-//===-- Symbol.cpp ----------------------------------------------*- C++ -*-===//
+//===-- Symbol.cpp --------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -120,7 +120,7 @@ bool Symbol::ValueIsAddress() const {
}
ConstString Symbol::GetDisplayName() const {
- return m_mangled.GetDisplayDemangledName(GetLanguage());
+ return m_mangled.GetDisplayDemangledName();
}
ConstString Symbol::GetReExportedSymbolName() const {
@@ -203,7 +203,7 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
s->Printf(", value = 0x%16.16" PRIx64,
m_addr_range.GetBaseAddress().GetOffset());
}
- ConstString demangled = m_mangled.GetDemangledName(GetLanguage());
+ ConstString demangled = m_mangled.GetDemangledName();
if (demangled)
s->Printf(", name=\"%s\"", demangled.AsCString());
if (m_mangled.GetMangledName())
@@ -219,7 +219,7 @@ void Symbol::Dump(Stream *s, Target *target, uint32_t index,
// Make sure the size of the symbol is up to date before dumping
GetByteSize();
- ConstString name = m_mangled.GetName(GetLanguage(), name_preference);
+ ConstString name = m_mangled.GetName(name_preference);
if (ValueIsAddress()) {
if (!m_addr_range.GetBaseAddress().Dump(s, nullptr,
Address::DumpStyleFileAddress))
@@ -333,7 +333,7 @@ uint32_t Symbol::GetPrologueByteSize() {
bool Symbol::Compare(ConstString name, SymbolType type) const {
if (type == eSymbolTypeAny || m_type == type)
return m_mangled.GetMangledName() == name ||
- m_mangled.GetDemangledName(GetLanguage()) == name;
+ m_mangled.GetDemangledName() == name;
return false;
}
@@ -496,11 +496,10 @@ lldb::addr_t Symbol::GetLoadAddress(Target *target) const {
return LLDB_INVALID_ADDRESS;
}
-ConstString Symbol::GetName() const { return m_mangled.GetName(GetLanguage()); }
+ConstString Symbol::GetName() const { return m_mangled.GetName(); }
ConstString Symbol::GetNameNoArguments() const {
- return m_mangled.GetName(GetLanguage(),
- Mangled::ePreferDemangledWithoutArguments);
+ return m_mangled.GetName(Mangled::ePreferDemangledWithoutArguments);
}
lldb::addr_t Symbol::ResolveCallableAddress(Target &target) const {
@@ -542,11 +541,11 @@ lldb::DisassemblerSP Symbol::GetInstructions(const ExecutionContext &exe_ctx,
const char *flavor,
bool prefer_file_cache) {
ModuleSP module_sp(m_addr_range.GetBaseAddress().GetModule());
- if (module_sp) {
+ if (module_sp && exe_ctx.HasTargetScope()) {
const bool prefer_file_cache = false;
return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
- flavor, exe_ctx, m_addr_range,
- prefer_file_cache);
+ flavor, exe_ctx.GetTargetRef(),
+ m_addr_range, prefer_file_cache);
}
return lldb::DisassemblerSP();
}
diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index 9eb805976f95..12c2077154b9 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
+//===-- SymbolContext.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -117,9 +117,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
Block *inlined_block = block->GetContainingInlinedBlock();
const InlineFunctionInfo *inlined_block_info =
inlined_block->GetInlinedFunctionInfo();
- s->Printf(
- " [inlined] %s",
- inlined_block_info->GetName(function->GetLanguage()).GetCString());
+ s->Printf(" [inlined] %s", inlined_block_info->GetName().GetCString());
lldb_private::AddressRange block_range;
if (inlined_block->GetRangeContainingAddress(addr, block_range)) {
@@ -657,12 +655,12 @@ SymbolContext::GetFunctionName(Mangled::NamePreference preference) const {
const InlineFunctionInfo *inline_info =
inlined_block->GetInlinedFunctionInfo();
if (inline_info)
- return inline_info->GetName(function->GetLanguage());
+ return inline_info->GetName();
}
}
- return function->GetMangled().GetName(function->GetLanguage(), preference);
+ return function->GetMangled().GetName(preference);
} else if (symbol && symbol->ValueIsAddress()) {
- return symbol->GetMangled().GetName(symbol->GetLanguage(), preference);
+ return symbol->GetMangled().GetName(preference);
} else {
// No function, return an empty string.
return ConstString();
@@ -970,7 +968,7 @@ bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
// CompUnits can't necessarily be resolved here, since an inlined function
// might show up in a number of CompUnits. Instead we just convert to a
// FileSpec and store it away.
- m_file_spec_up.reset(new FileSpec(spec_string));
+ m_file_spec_up = std::make_unique<FileSpec>(spec_string);
m_type |= eFileSpecified;
break;
case eLineStartSpecified:
@@ -1076,19 +1074,17 @@ bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
if (inline_info != nullptr) {
was_inlined = true;
const Mangled &name = inline_info->GetMangled();
- if (!name.NameMatches(func_name, sc.function->GetLanguage()))
+ if (!name.NameMatches(func_name))
return false;
}
}
// If it wasn't inlined, check the name in the function or symbol:
if (!was_inlined) {
if (sc.function != nullptr) {
- if (!sc.function->GetMangled().NameMatches(func_name,
- sc.function->GetLanguage()))
+ if (!sc.function->GetMangled().NameMatches(func_name))
return false;
} else if (sc.symbol != nullptr) {
- if (!sc.symbol->GetMangled().NameMatches(func_name,
- sc.symbol->GetLanguage()))
+ if (!sc.symbol->GetMangled().NameMatches(func_name))
return false;
}
}
diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp
index 90f7d1011716..3f9cdefc8d41 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolFile.cpp ------------------------------------------*- C++ -*-===//
+//===-- SymbolFile.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -105,7 +105,7 @@ uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec,
}
void SymbolFile::FindGlobalVariables(ConstString name,
- const CompilerDeclContext *parent_decl_ctx,
+ const CompilerDeclContext &parent_decl_ctx,
uint32_t max_matches,
VariableList &variables) {}
@@ -114,7 +114,7 @@ void SymbolFile::FindGlobalVariables(const RegularExpression &regex,
VariableList &variables) {}
void SymbolFile::FindFunctions(ConstString name,
- const CompilerDeclContext *parent_decl_ctx,
+ const CompilerDeclContext &parent_decl_ctx,
lldb::FunctionNameType name_type_mask,
bool include_inlines,
SymbolContextList &sc_list) {}
@@ -130,7 +130,7 @@ void SymbolFile::GetMangledNamesForFunction(
}
void SymbolFile::FindTypes(
- ConstString name, const CompilerDeclContext *parent_decl_ctx,
+ ConstString name, const CompilerDeclContext &parent_decl_ctx,
uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {}
diff --git a/lldb/source/Symbol/SymbolVendor.cpp b/lldb/source/Symbol/SymbolVendor.cpp
index 1e1dea71d7f3..0a5acbc48eb4 100644
--- a/lldb/source/Symbol/SymbolVendor.cpp
+++ b/lldb/source/Symbol/SymbolVendor.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolVendor.cpp ----------------------------------------*- C++ -*-===//
+//===-- SymbolVendor.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -51,7 +51,7 @@ SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp,
}
if (!sym_objfile_sp)
sym_objfile_sp = module_sp->GetObjectFile()->shared_from_this();
- instance_up.reset(new SymbolVendor(module_sp));
+ instance_up = std::make_unique<SymbolVendor>(module_sp);
instance_up->AddSymbolFileRepresentation(sym_objfile_sp);
return instance_up.release();
}
diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp
index f5bd22ee5ee2..3f697e6076b3 100644
--- a/lldb/source/Symbol/Symtab.cpp
+++ b/lldb/source/Symbol/Symtab.cpp
@@ -1,4 +1,4 @@
-//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
+//===-- Symtab.cpp --------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -299,7 +299,7 @@ void Symtab::InitNameIndexes() {
// Symbol name strings that didn't match a Mangled::ManglingScheme, are
// stored in the demangled field.
- if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage())) {
+ if (ConstString name = mangled.GetDemangledName()) {
m_name_to_index.Append(name, value);
if (symbol->ContainsLinkerAnnotations()) {
@@ -425,7 +425,7 @@ void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes,
const Mangled &mangled = symbol->GetMangled();
if (add_demangled) {
- if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage()))
+ if (ConstString name = mangled.GetDemangledName())
name_to_index_map.Append(name, value);
}
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index f194356a0a07..307e99ac84b6 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -1,4 +1,4 @@
-//===-- Type.cpp ------------------------------------------------*- C++ -*-===//
+//===-- Type.cpp ----------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -143,15 +143,14 @@ Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name,
llvm::Optional<uint64_t> byte_size, SymbolContextScope *context,
user_id_t encoding_uid, EncodingDataType encoding_uid_type,
const Declaration &decl, const CompilerType &compiler_type,
- ResolveState compiler_type_resolve_state)
+ ResolveState compiler_type_resolve_state, uint32_t opaque_payload)
: std::enable_shared_from_this<Type>(), UserID(uid), m_name(name),
m_symbol_file(symbol_file), m_context(context), m_encoding_type(nullptr),
m_encoding_uid(encoding_uid), m_encoding_uid_type(encoding_uid_type),
m_decl(decl), m_compiler_type(compiler_type),
- m_compiler_type_resolve_state(
- compiler_type ? compiler_type_resolve_state
- : ResolveState::Unresolved),
- m_is_complete_objc_class(false) {
+ m_compiler_type_resolve_state(compiler_type ? compiler_type_resolve_state
+ : ResolveState::Unresolved),
+ m_payload(opaque_payload) {
if (byte_size) {
m_byte_size = *byte_size;
m_byte_size_has_value = true;
@@ -235,7 +234,7 @@ void Type::GetDescription(Stream *s, lldb::DescriptionLevel level,
}
}
-void Type::Dump(Stream *s, bool show_context) {
+void Type::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) {
s->Printf("%p: ", static_cast<void *>(this));
s->Indent();
*s << "Type" << static_cast<const UserID &>(*this) << ' ';
@@ -256,7 +255,7 @@ void Type::Dump(Stream *s, bool show_context) {
if (m_compiler_type.IsValid()) {
*s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' ';
- GetForwardCompilerType().DumpTypeDescription(s);
+ GetForwardCompilerType().DumpTypeDescription(s, level);
} else if (m_encoding_uid != LLDB_INVALID_UID) {
s->Format(", type_data = {0:x-16}", m_encoding_uid);
switch (m_encoding_uid_type) {
@@ -303,7 +302,7 @@ void Type::Dump(Stream *s, bool show_context) {
ConstString Type::GetName() {
if (!m_name)
- m_name = GetForwardCompilerType().GetConstTypeName();
+ m_name = GetForwardCompilerType().GetTypeName();
return m_name;
}
@@ -313,7 +312,7 @@ void Type::DumpValue(ExecutionContext *exe_ctx, Stream *s,
const DataExtractor &data, uint32_t data_byte_offset,
bool show_types, bool show_summary, bool verbose,
lldb::Format format) {
- if (ResolveClangType(ResolveState::Forward)) {
+ if (ResolveCompilerType(ResolveState::Forward)) {
if (show_types) {
s->PutChar('(');
if (verbose)
@@ -466,7 +465,7 @@ bool Type::WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t addr,
const Declaration &Type::GetDeclaration() const { return m_decl; }
-bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
+bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) {
// TODO: This needs to consider the correct type system to use.
Type *encoding_type = nullptr;
if (!m_compiler_type.IsValid()) {
@@ -506,7 +505,7 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
case eEncodingIsTypedefUID:
m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef(
m_name.AsCString("__lldb_invalid_typedef_name"),
- GetSymbolFile()->GetDeclContextContainingUID(GetID()));
+ GetSymbolFile()->GetDeclContextContainingUID(GetID()), m_payload);
m_name.Clear();
break;
@@ -536,7 +535,7 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
LLDB_LOG_ERROR(
lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS),
std::move(err),
- "Unable to construct void type from ClangASTContext");
+ "Unable to construct void type from TypeSystemClang");
} else {
CompilerType void_compiler_type =
type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid);
@@ -564,7 +563,7 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
case eEncodingIsTypedefUID:
m_compiler_type = void_compiler_type.CreateTypedef(
m_name.AsCString("__lldb_invalid_typedef_name"),
- GetSymbolFile()->GetDeclContextContainingUID(GetID()));
+ GetSymbolFile()->GetDeclContextContainingUID(GetID()), m_payload);
break;
case eEncodingIsPointerUID:
@@ -627,7 +626,7 @@ bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
break;
}
}
- encoding_type->ResolveClangType(encoding_compiler_type_resolve_state);
+ encoding_type->ResolveCompilerType(encoding_compiler_type_resolve_state);
}
}
return m_compiler_type.IsValid();
@@ -642,22 +641,22 @@ uint32_t Type::GetEncodingMask() {
}
CompilerType Type::GetFullCompilerType() {
- ResolveClangType(ResolveState::Full);
+ ResolveCompilerType(ResolveState::Full);
return m_compiler_type;
}
CompilerType Type::GetLayoutCompilerType() {
- ResolveClangType(ResolveState::Layout);
+ ResolveCompilerType(ResolveState::Layout);
return m_compiler_type;
}
CompilerType Type::GetForwardCompilerType() {
- ResolveClangType(ResolveState::Forward);
+ ResolveCompilerType(ResolveState::Forward);
return m_compiler_type;
}
ConstString Type::GetQualifiedName() {
- return GetForwardCompilerType().GetConstTypeName();
+ return GetForwardCompilerType().GetTypeName();
}
bool Type::GetTypeScopeAndBasename(const llvm::StringRef& name,
diff --git a/lldb/source/Symbol/TypeList.cpp b/lldb/source/Symbol/TypeList.cpp
index 1813e8ecca9a..f0506c7c5bfc 100644
--- a/lldb/source/Symbol/TypeList.cpp
+++ b/lldb/source/Symbol/TypeList.cpp
@@ -1,4 +1,4 @@
-//===-- TypeList.cpp --------------------------------------------*- C++ -*-===//
+//===-- TypeList.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -107,7 +107,8 @@ void TypeList::RemoveMismatchedTypes(const char *qualified_typename,
type_basename = qualified_typename;
type_scope = "";
}
- return RemoveMismatchedTypes(type_scope, type_basename, type_class,
+ return RemoveMismatchedTypes(std::string(type_scope),
+ std::string(type_basename), type_class,
exact_match);
}
diff --git a/lldb/source/Symbol/TypeMap.cpp b/lldb/source/Symbol/TypeMap.cpp
index 4ee1026bed24..e810d3020073 100644
--- a/lldb/source/Symbol/TypeMap.cpp
+++ b/lldb/source/Symbol/TypeMap.cpp
@@ -1,4 +1,4 @@
-//===-- TypeMap.cpp --------------------------------------------*- C++ -*-===//
+//===-- TypeMap.cpp -------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -121,9 +121,9 @@ bool TypeMap::Remove(const lldb::TypeSP &type_sp) {
return false;
}
-void TypeMap::Dump(Stream *s, bool show_context) {
+void TypeMap::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) {
for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) {
- pos->second->Dump(s, show_context);
+ pos->second->Dump(s, show_context, level);
}
}
@@ -137,7 +137,8 @@ void TypeMap::RemoveMismatchedTypes(const char *qualified_typename,
type_basename = qualified_typename;
type_scope = "";
}
- return RemoveMismatchedTypes(type_scope, type_basename, type_class,
+ return RemoveMismatchedTypes(std::string(type_scope),
+ std::string(type_basename), type_class,
exact_match);
}
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 29a49a6fb1d4..5e57813c28bd 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -1,4 +1,4 @@
-//===-- TypeSystem.cpp ------------------------------------------*- C++ -*-===//
+//===-- TypeSystem.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -70,6 +70,10 @@ lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
return CreateInstanceHelper(language, nullptr, target);
}
+#ifndef NDEBUG
+bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }
+#endif
+
bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
return false;
}
@@ -109,7 +113,8 @@ TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type,
const char *name,
- const CompilerDeclContext &decl_ctx) {
+ const CompilerDeclContext &decl_ctx,
+ uint32_t opaque_payload) {
return CompilerType();
}
@@ -239,7 +244,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
}
error = llvm::make_error<llvm::StringError>(
"TypeSystem for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)) +
+ llvm::StringRef(Language::GetNameForLanguageType(language)) +
" doesn't exist",
llvm::inconvertibleErrorCode());
return std::move(error);
@@ -256,7 +261,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
}
error = llvm::make_error<llvm::StringError>(
"TypeSystem for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)) +
+ llvm::StringRef(Language::GetNameForLanguageType(language)) +
" doesn't exist",
llvm::inconvertibleErrorCode());
return std::move(error);
@@ -266,7 +271,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
if (!can_create) {
error = llvm::make_error<llvm::StringError>(
"Unable to find type system for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)),
+ llvm::StringRef(Language::GetNameForLanguageType(language)),
llvm::inconvertibleErrorCode());
} else {
// Cache even if we get a shared pointer that contains a null type system
@@ -279,7 +284,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
}
error = llvm::make_error<llvm::StringError>(
"TypeSystem for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)) +
+ llvm::StringRef(Language::GetNameForLanguageType(language)) +
" doesn't exist",
llvm::inconvertibleErrorCode());
}
@@ -308,7 +313,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
}
error = llvm::make_error<llvm::StringError>(
"TypeSystem for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)) +
+ llvm::StringRef(Language::GetNameForLanguageType(language)) +
" doesn't exist",
llvm::inconvertibleErrorCode());
return std::move(error);
@@ -325,7 +330,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
}
error = llvm::make_error<llvm::StringError>(
"TypeSystem for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)) +
+ llvm::StringRef(Language::GetNameForLanguageType(language)) +
" doesn't exist",
llvm::inconvertibleErrorCode());
return std::move(error);
@@ -335,7 +340,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
if (!can_create) {
error = llvm::make_error<llvm::StringError>(
"Unable to find type system for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)),
+ llvm::StringRef(Language::GetNameForLanguageType(language)),
llvm::inconvertibleErrorCode());
} else {
// Cache even if we get a shared pointer that contains a null type system
@@ -348,7 +353,7 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
}
error = llvm::make_error<llvm::StringError>(
"TypeSystem for language " +
- llvm::toStringRef(Language::GetNameForLanguageType(language)) +
+ llvm::StringRef(Language::GetNameForLanguageType(language)) +
" doesn't exist",
llvm::inconvertibleErrorCode());
}
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index 15443ce5d8ac..e8906f38e2ff 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -1,4 +1,4 @@
-//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
+//===-- UnwindPlan.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -15,6 +15,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
using namespace lldb;
using namespace lldb_private;
@@ -79,13 +80,10 @@ GetByteOrderAndAddrSize(Thread *thread) {
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
- DataExtractor extractor(expr.data(), expr.size(), order_and_width->first,
- order_and_width->second);
- if (!DWARFExpression::PrintDWARFExpression(s, extractor,
- order_and_width->second,
- /*dwarf_ref_size*/ 4,
- /*location_expression*/ false))
- s.PutCString("invalid-dwarf-expr");
+ llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
+ order_and_width->second);
+ llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
+ .print(s.AsRawOstream(), nullptr, nullptr);
} else
s.PutCString("dwarf-expr");
}
diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp
index 045957a67b3b..3faa528a339f 100644
--- a/lldb/source/Symbol/UnwindTable.cpp
+++ b/lldb/source/Symbol/UnwindTable.cpp
@@ -1,4 +1,4 @@
-//===-- UnwindTable.cpp -----------------------------------------*- C++ -*-===//
+//===-- UnwindTable.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -57,26 +57,28 @@ void UnwindTable::Initialize() {
SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
if (sect.get()) {
- m_eh_frame_up.reset(
- new DWARFCallFrameInfo(*object_file, sect, DWARFCallFrameInfo::EH));
+ m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>(
+ *object_file, sect, DWARFCallFrameInfo::EH);
}
sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
if (sect) {
- m_debug_frame_up.reset(
- new DWARFCallFrameInfo(*object_file, sect, DWARFCallFrameInfo::DWARF));
+ m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>(
+ *object_file, sect, DWARFCallFrameInfo::DWARF);
}
sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
if (sect) {
- m_compact_unwind_up.reset(new CompactUnwindInfo(*object_file, sect));
+ m_compact_unwind_up =
+ std::make_unique<CompactUnwindInfo>(*object_file, sect);
}
sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
if (sect) {
SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
if (sect_extab.get()) {
- m_arm_unwind_up.reset(new ArmUnwindInfo(*object_file, sect, sect_extab));
+ m_arm_unwind_up =
+ std::make_unique<ArmUnwindInfo>(*object_file, sect, sect_extab);
}
}
}
diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp
index a0496824a0a3..6c18ef15e1a2 100644
--- a/lldb/source/Symbol/Variable.cpp
+++ b/lldb/source/Symbol/Variable.cpp
@@ -1,4 +1,4 @@
-//===-- Variable.cpp --------------------------------------------*- C++ -*-===//
+//===-- Variable.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -68,7 +68,7 @@ lldb::LanguageType Variable::GetLanguage() const {
}
ConstString Variable::GetName() const {
- ConstString name = m_mangled.GetName(GetLanguage());
+ ConstString name = m_mangled.GetName();
if (name)
return name;
return m_name;
@@ -82,16 +82,13 @@ bool Variable::NameMatches(ConstString name) const {
SymbolContext variable_sc;
m_owner_scope->CalculateSymbolContext(&variable_sc);
- LanguageType language = eLanguageTypeUnknown;
- if (variable_sc.comp_unit)
- language = variable_sc.comp_unit->GetLanguage();
- return m_mangled.NameMatches(name, language);
+ return m_mangled.NameMatches(name);
}
bool Variable::NameMatches(const RegularExpression &regex) const {
if (regex.Execute(m_name.AsCString()))
return true;
if (m_mangled)
- return m_mangled.NameMatches(regex, GetLanguage());
+ return m_mangled.NameMatches(regex);
return false;
}
@@ -532,7 +529,7 @@ static void PrivateAutoCompleteMembers(
i, member_name, nullptr, nullptr, nullptr);
if (partial_member_name.empty() ||
- member_name.find(partial_member_name) == 0) {
+ llvm::StringRef(member_name).startswith(partial_member_name)) {
if (member_name == partial_member_name) {
PrivateAutoComplete(
frame, partial_path,
@@ -684,8 +681,8 @@ static void PrivateAutoComplete(
break;
}
- std::string token(partial_path, 0, pos);
- remaining_partial_path = partial_path.substr(pos);
+ std::string token(std::string(partial_path), 0, pos);
+ remaining_partial_path = std::string(partial_path.substr(pos));
if (compiler_type.IsValid()) {
PrivateAutoCompleteMembers(frame, token, remaining_partial_path,
diff --git a/lldb/source/Symbol/VariableList.cpp b/lldb/source/Symbol/VariableList.cpp
index 51312472e265..f7a441472bc0 100644
--- a/lldb/source/Symbol/VariableList.cpp
+++ b/lldb/source/Symbol/VariableList.cpp
@@ -1,4 +1,4 @@
-//===-- VariableList.cpp ----------------------------------------*- C++ -*-===//
+//===-- VariableList.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.