summaryrefslogtreecommitdiff
path: root/source/Plugins/Language
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
commit94994d372d014ce4c8758b9605d63fae651bd8aa (patch)
tree51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Plugins/Language
parent39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff)
Notes
Diffstat (limited to 'source/Plugins/Language')
-rw-r--r--source/Plugins/Language/CMakeLists.txt4
-rw-r--r--source/Plugins/Language/CPlusPlus/BlockPointer.cpp6
-rw-r--r--source/Plugins/Language/CPlusPlus/CMakeLists.txt5
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp206
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h11
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h4
-rw-r--r--source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp14
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.cpp186
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.h31
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp19
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp15
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxList.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxMap.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp85
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp256
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVariant.h31
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVector.cpp36
-rw-r--r--source/Plugins/Language/CPlusPlus/LibStdcpp.cpp11
-rw-r--r--source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp99
-rw-r--r--source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h51
-rw-r--r--source/Plugins/Language/ClangCommon/CMakeLists.txt9
-rw-r--r--source/Plugins/Language/ClangCommon/ClangHighlighter.cpp237
-rw-r--r--source/Plugins/Language/ClangCommon/ClangHighlighter.h38
-rw-r--r--source/Plugins/Language/Go/CMakeLists.txt13
-rw-r--r--source/Plugins/Language/Go/GoFormatterFunctions.cpp152
-rw-r--r--source/Plugins/Language/Go/GoFormatterFunctions.h43
-rw-r--r--source/Plugins/Language/Go/GoLanguage.cpp127
-rw-r--r--source/Plugins/Language/Go/GoLanguage.h63
-rw-r--r--source/Plugins/Language/Java/CMakeLists.txt12
-rw-r--r--source/Plugins/Language/Java/JavaFormatterFunctions.cpp167
-rw-r--r--source/Plugins/Language/Java/JavaFormatterFunctions.h35
-rw-r--r--source/Plugins/Language/Java/JavaLanguage.cpp101
-rw-r--r--source/Plugins/Language/Java/JavaLanguage.h52
-rw-r--r--source/Plugins/Language/OCaml/CMakeLists.txt12
-rw-r--r--source/Plugins/Language/OCaml/OCamlLanguage.cpp63
-rw-r--r--source/Plugins/Language/OCaml/OCamlLanguage.h51
-rw-r--r--source/Plugins/Language/ObjC/CF.cpp2
-rw-r--r--source/Plugins/Language/ObjC/CMakeLists.txt1
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.cpp67
-rw-r--r--source/Plugins/Language/ObjC/NSArray.cpp31
-rw-r--r--source/Plugins/Language/ObjC/NSDictionary.cpp4
-rw-r--r--source/Plugins/Language/ObjC/NSError.cpp4
-rw-r--r--source/Plugins/Language/ObjC/NSException.cpp156
-rw-r--r--source/Plugins/Language/ObjC/NSIndexPath.cpp10
-rw-r--r--source/Plugins/Language/ObjC/NSSet.cpp4
-rw-r--r--source/Plugins/Language/ObjC/NSString.cpp13
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.cpp20
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.h11
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt3
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp9
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h11
52 files changed, 1395 insertions, 1208 deletions
diff --git a/source/Plugins/Language/CMakeLists.txt b/source/Plugins/Language/CMakeLists.txt
index 4b92a8ef866b..7869074566d1 100644
--- a/source/Plugins/Language/CMakeLists.txt
+++ b/source/Plugins/Language/CMakeLists.txt
@@ -1,6 +1,4 @@
+add_subdirectory(ClangCommon)
add_subdirectory(CPlusPlus)
-add_subdirectory(Go)
-add_subdirectory(Java)
add_subdirectory(ObjC)
add_subdirectory(ObjCPlusPlus)
-add_subdirectory(OCaml)
diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
index 82b7ac1675fa..40200503a8a7 100644
--- a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
+++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "BlockPointer.h"
#include "lldb/Core/ValueObject.h"
@@ -89,7 +85,7 @@ public:
size_t CalculateNumChildren() override {
const bool omit_empty_base_classes = false;
- return m_block_struct_type.GetNumChildren(omit_empty_base_classes);
+ return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
}
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 180440a244a4..bc357aa52b84 100644
--- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -9,13 +9,16 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxInitializerList.cpp
LibCxxList.cpp
LibCxxMap.cpp
+ LibCxxOptional.cpp
LibCxxQueue.cpp
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
+ LibCxxVariant.cpp
LibCxxVector.cpp
LibStdcpp.cpp
LibStdcppTuple.cpp
LibStdcppUniquePointer.cpp
+ MSVCUndecoratedNameParser.cpp
LINK_LIBS
lldbCore
@@ -24,6 +27,8 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
lldbSymbol
lldbTarget
lldbUtility
+ lldbPluginClangCommon
+
LINK_COMPONENTS
Support
)
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 2c63e6467d4c..982b286d0f05 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -9,20 +9,17 @@
#include "CPlusPlusLanguage.h"
-// C Includes
#include <cctype>
#include <cstring>
-// C++ Includes
#include <functional>
#include <memory>
#include <mutex>
#include <set>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
+#include "llvm/Demangle/ItaniumDemangle.h"
-// Project includes
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/DataFormatters/CXXFunctionPointer.h"
@@ -30,7 +27,6 @@
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/FastDemangle.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
@@ -39,7 +35,9 @@
#include "CxxStringTypes.h"
#include "LibCxx.h"
#include "LibCxxAtomic.h"
+#include "LibCxxVariant.h"
#include "LibStdcpp.h"
+#include "MSVCUndecoratedNameParser.h"
using namespace lldb;
using namespace lldb_private;
@@ -143,10 +141,7 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
}
// We processed all characters. It is a vaild basename.
- if (idx == basename.size())
- return true;
-
- return false;
+ return idx == basename.size();
}
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
@@ -251,19 +246,23 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
// FIXME!! we should really run through all the known C++ Language plugins
// and ask each one if this is a C++ mangled name
-
+
if (name == nullptr)
return false;
-
- // MSVC style mangling
+
+ // MSVC style mangling
if (name[0] == '?')
return true;
-
+
return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
}
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
+ if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))
+ return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,
+ identifier);
+
CPlusPlusNameParser parser(name);
if (auto full_name = parser.ParseAsFullName()) {
identifier = full_name.getValue().basename;
@@ -273,53 +272,89 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
return false;
}
-/// Given a mangled function `mangled`, replace all the primitive function type
-/// arguments of `search` with type `replace`.
-static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
- llvm::StringRef search,
- llvm::StringRef replace) {
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+namespace {
+class NodeAllocator {
+ llvm::BumpPtrAllocator Alloc;
- const size_t max_len =
- mangled.size() + mangled.count(search) * replace.size() + 1;
+public:
+ void reset() { Alloc.Reset(); }
- // Make a temporary buffer to fix up the mangled parameter types and copy the
- // original there
- std::string output_buf;
- output_buf.reserve(max_len);
- output_buf.insert(0, mangled.str());
- ptrdiff_t replaced_offset = 0;
+ template <typename T, typename... Args> T *makeNode(Args &&... args) {
+ return new (Alloc.Allocate(sizeof(T), alignof(T)))
+ T(std::forward<Args>(args)...);
+ }
+
+ void *allocateNodeArray(size_t sz) {
+ return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
+ alignof(llvm::itanium_demangle::Node *));
+ }
+};
- auto swap_parms_hook = [&](const char *parsee) {
- if (!parsee || !*parsee)
- return;
+/// Given a mangled function `Mangled`, replace all the primitive function type
+/// arguments of `Search` with type `Replace`.
+class TypeSubstitutor
+ : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
+ NodeAllocator> {
+ /// Input character until which we have constructed the respective output
+ /// already
+ const char *Written;
- // Check whether we've found a substitutee
- llvm::StringRef s(parsee);
- if (s.startswith(search)) {
- // account for the case where a replacement is of a different length to
- // the original
- replaced_offset += replace.size() - search.size();
+ llvm::StringRef Search;
+ llvm::StringRef Replace;
+ llvm::SmallString<128> Result;
- ptrdiff_t replace_idx = (mangled.size() - s.size()) + replaced_offset;
- output_buf.erase(replace_idx, search.size());
- output_buf.insert(replace_idx, replace.str());
+ /// Whether we have performed any substitutions.
+ bool Substituted;
+
+ void reset(llvm::StringRef Mangled, llvm::StringRef Search,
+ llvm::StringRef Replace) {
+ AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
+ Written = Mangled.begin();
+ this->Search = Search;
+ this->Replace = Replace;
+ Result.clear();
+ Substituted = false;
+ }
+
+ void appendUnchangedInput() {
+ Result += llvm::StringRef(Written, First - Written);
+ Written = First;
+ }
+
+public:
+ TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
+
+ ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
+ llvm::StringRef To) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+ reset(Mangled, From, To);
+ if (parse() == nullptr) {
+ LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
+ return ConstString();
}
- };
+ if (!Substituted)
+ return ConstString();
- // FastDemangle will call our hook for each instance of a primitive type,
- // allowing us to perform substitution
- char *const demangled =
- FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
+ // Append any trailing unmodified input.
+ appendUnchangedInput();
+ LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
+ return ConstString(Result);
+ }
- if (log)
- log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
- mangled.str().c_str(), demangled, output_buf.c_str(),
- FastDemangle(output_buf.c_str()));
- // FastDemangle malloc'd this string.
- free(demangled);
+ llvm::itanium_demangle::Node *parseType() {
+ if (llvm::StringRef(First, numLeft()).startswith(Search)) {
+ // We found a match. Append unmodified input up to this point.
+ appendUnchangedInput();
- return output_buf == mangled ? ConstString() : ConstString(output_buf);
+ // And then perform the replacement.
+ Result += Replace;
+ Written += Search.size();
+ Substituted = true;
+ }
+ return AbstractManglingParser::parseType();
+ }
+};
}
uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
@@ -348,23 +383,24 @@ uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
alternates.insert(ConstString(fixed_scratch));
}
+ TypeSubstitutor TS;
// `char` is implementation defined as either `signed` or `unsigned`. As a
// result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
// char, 'h'-unsigned char. If we're looking for symbols with a signed char
// parameter, try finding matches which have the general case 'c'.
if (ConstString char_fixup =
- SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
+ TS.substitute(mangled_name.GetStringRef(), "a", "c"))
alternates.insert(char_fixup);
// long long parameter mangling 'x', may actually just be a long 'l' argument
if (ConstString long_fixup =
- SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
+ TS.substitute(mangled_name.GetStringRef(), "x", "l"))
alternates.insert(long_fixup);
// unsigned long long parameter mangling 'y', may actually just be unsigned
// long 'm' argument
if (ConstString ulong_fixup =
- SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
+ TS.substitute(mangled_name.GetStringRef(), "y", "m"))
alternates.insert(ulong_fixup);
return alternates.size() - start_size;
@@ -385,8 +421,17 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
#ifndef LLDB_DISABLE_PYTHON
lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
- stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider,
+ stl_summary_flags,
+ lldb_private::formatters::LibcxxStringSummaryProviderASCII,
"std::string summary provider"));
+ lldb::TypeSummaryImplSP std_stringu16_summary_sp(new CXXFunctionSummaryFormat(
+ stl_summary_flags,
+ lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
+ "std::u16string summary provider"));
+ lldb::TypeSummaryImplSP std_stringu32_summary_sp(new CXXFunctionSummaryFormat(
+ stl_summary_flags,
+ lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
+ "std::u32string summary provider"));
lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider,
"std::wstring summary provider"));
@@ -400,6 +445,16 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::__1::allocator<char> >"),
std_string_summary_sp);
cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString(
+ "std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, "
+ "std::__1::allocator<char16_t> >"),
+ std_stringu16_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString(
+ "std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, "
+ "std::__1::allocator<char32_t> >"),
+ std_stringu32_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
ConstString("std::__ndk1::basic_string<char, "
"std::__ndk1::char_traits<char>, "
"std::__ndk1::allocator<char> >"),
@@ -493,6 +548,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::tuple synthetic children",
ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags,
true);
+ AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
+ "libc++ std::optional synthetic children",
+ ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
+ stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
+ "libc++ std::variant synthetic children",
+ ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
+ stl_synth_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
@@ -519,6 +582,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
ConstString("^(std::__(ndk)?1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags,
true);
+ AddCXXSummary(
+ cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider,
+ "libc++ std::function summary provider",
+ ConstString("^std::__(ndk)?1::function<.+>$"), stl_summary_flags, true);
+
stl_summary_flags.SetDontShowChildren(false);
stl_summary_flags.SetSkipPointers(false);
AddCXXSummary(cpp_category_sp,
@@ -584,6 +652,16 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
"libc++ std::atomic summary provider",
ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxOptionalSummaryProvider,
+ "libc++ std::optional summary provider",
+ ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
+ stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxVariantSummaryProvider,
+ "libc++ std::variant summary provider",
+ ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
+ stl_summary_flags, true);
stl_summary_flags.SetSkipPointers(true);
@@ -610,11 +688,6 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::map iterator synthetic children",
ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags,
true);
-
- AddCXXSynthetic(
- cpp_category_sp, lldb_private::formatters::LibcxxFunctionFrontEndCreator,
- "std::function synthetic value provider",
- ConstString("^std::__(ndk)?1::function<.+>$"), stl_synth_flags, true);
#endif
}
@@ -1002,3 +1075,16 @@ CPlusPlusLanguage::GetHardcodedSynthetics() {
return g_formatters;
}
+
+bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
+ const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c",
+ ".h", ".hh", ".hpp", ".hxx", ".h++"};
+ for (auto suffix : suffixes) {
+ if (file_path.endswith_lower(suffix))
+ return true;
+ }
+
+ // Check if we're in a STL path (where the files usually have no extension
+ // that we could check for.
+ return file_path.contains("/usr/include/c++/");
+}
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 7380ef321305..3c8ca96e81f6 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -10,15 +10,12 @@
#ifndef liblldb_CPlusPlusLanguage_h_
#define liblldb_CPlusPlusLanguage_h_
-// C Includes
-// C++ Includes
#include <set>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
+#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
@@ -26,6 +23,8 @@
namespace lldb_private {
class CPlusPlusLanguage : public Language {
+ ClangHighlighter m_highlighter;
+
public:
class MethodName {
public:
@@ -90,6 +89,10 @@ public:
HardcodedFormatters::HardcodedSyntheticFinder
GetHardcodedSynthetics() override;
+ bool IsSourceFile(llvm::StringRef file_path) const override;
+
+ const Highlighter *GetHighlighter() const override { return &m_highlighter; }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
index fe1d46f32c17..d46a53a7a704 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
@@ -10,16 +10,12 @@
#ifndef liblldb_CPlusPlusNameParser_h_
#define liblldb_CPlusPlusNameParser_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
index 0f6fb54e8384..24185b314466 100644
--- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
+++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
@@ -100,8 +100,11 @@ bool lldb_private::formatters::WCharStringSummaryProvider(
if (!wchar_compiler_type)
return false;
- const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
- nullptr); // Safe to pass NULL for exe_scope here
+ // Safe to pass nullptr for exe_scope here.
+ llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ const uint32_t wchar_size = *size;
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(valobj_addr);
@@ -194,8 +197,11 @@ bool lldb_private::formatters::WCharSummaryProvider(
if (!wchar_compiler_type)
return false;
- const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
- nullptr); // Safe to pass NULL for exe_scope here
+ // Safe to pass nullptr for exe_scope here.
+ llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ const uint32_t wchar_size = *size;
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
options.SetData(data);
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 95e02a473cd7..7e8c06bd4c75 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -9,10 +9,7 @@
#include "LibCxx.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "llvm/ADT/ScopeExit.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/ValueObject.h"
@@ -22,7 +19,9 @@
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/VectorIterator.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ProcessStructReader.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
@@ -33,6 +32,76 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+bool lldb_private::formatters::LibcxxOptionalSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+ if (!valobj_sp)
+ return false;
+
+ // An optional either contains a value or not, the member __engaged_ is
+ // a bool flag, it is true if the optional has a value and false otherwise.
+ ValueObjectSP engaged_sp(
+ valobj_sp->GetChildMemberWithName(ConstString("__engaged_"), true));
+
+ if (!engaged_sp)
+ return false;
+
+ llvm::StringRef engaged_as_cstring(
+ engaged_sp->GetValueAsUnsigned(0) == 1 ? "true" : "false");
+
+ stream.Printf(" Has Value=%s ", engaged_as_cstring.data());
+
+ return true;
+}
+
+bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+
+ if (!valobj_sp)
+ return false;
+
+ ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == nullptr)
+ return false;
+
+ CPPLanguageRuntime *cpp_runtime = process->GetCPPLanguageRuntime();
+
+ if (!cpp_runtime)
+ return false;
+
+ CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
+ cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
+
+ switch (callable_info.callable_case) {
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid:
+ stream.Printf(" __f_ = %" PRIu64, callable_info.member__f_pointer_value);
+ return false;
+ break;
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda:
+ stream.Printf(
+ " Lambda in File %s at Line %u",
+ callable_info.callable_line_entry.file.GetFilename().GetCString(),
+ callable_info.callable_line_entry.line);
+ break;
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject:
+ stream.Printf(
+ " Function in File %s at Line %u",
+ callable_info.callable_line_entry.file.GetFilename().GetCString(),
+ callable_info.callable_line_entry.line);
+ break;
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction:
+ stream.Printf(" Function = %s ",
+ callable_info.callable_symbol.GetName().GetCString());
+ break;
+ }
+
+ return true;
+}
+
bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
@@ -120,9 +189,9 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
if (!valobj_sp)
return false;
-
+
static ConstString g___i_("__i_");
-
+
// this must be a ValueObject* because it is a child of the ValueObject we
// are producing children for it if were a ValueObjectSP, we would end up
// with a loop (iterator -> synthetic -> child -> parent == iterator) and
@@ -156,37 +225,53 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
m_pair_ptr = nullptr;
return false;
}
- CompilerType pair_type(__i_->GetCompilerType().GetTypeTemplateArgument(0));
- std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
- pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
+ CompilerType pair_type(
+ __i_->GetCompilerType().GetTypeTemplateArgument(0));
+ std::string name;
+ uint64_t bit_offset_ptr;
+ uint32_t bitfield_bit_size_ptr;
+ bool is_bitfield_ptr;
+ pair_type = pair_type.GetFieldAtIndex(
+ 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
if (!pair_type) {
m_pair_ptr = nullptr;
return false;
}
-
+
auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
m_pair_ptr = nullptr;
- if (addr && addr!=LLDB_INVALID_ADDRESS) {
- ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
+ if (addr && addr != LLDB_INVALID_ADDRESS) {
+ ClangASTContext *ast_ctx =
+ llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
if (!ast_ctx)
return false;
- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
- {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
- {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
- {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
- {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
- {"payload",pair_type}
- });
- DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
+ CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
+ ConstString(),
+ {{"ptr0",
+ ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+ {"ptr1",
+ ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+ {"ptr2",
+ ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+ {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
+ {"payload", pair_type}});
+ llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
+ if (!size)
+ return false;
+ DataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
ProcessSP process_sp(target_sp->GetProcessSP());
Status error;
- process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
+ process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize(), error);
if (error.Fail())
return false;
- DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
- auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
+ DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+ auto pair_sp = CreateValueObjectFromData(
+ "pair", extractor, valobj_sp->GetExecutionContextRef(),
+ tree_node_type);
if (pair_sp)
- m_pair_sp = pair_sp->GetChildAtIndex(4,true);
+ m_pair_sp = pair_sp->GetChildAtIndex(4, true);
}
}
}
@@ -491,6 +576,8 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
->GetScratchClangASTContext()
->GetBasicType(lldb::eBasicTypeWChar)
.GetByteSize(nullptr);
+ if (!wchar_t_size)
+ return false;
options.SetData(extractor);
options.SetStream(&stream);
@@ -499,7 +586,7 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
options.SetSourceSize(size);
options.SetBinaryZeroIsTerminator(false);
- switch (wchar_t_size) {
+ switch (*wchar_t_size) {
case 1:
StringPrinter::ReadBufferAndDumpToStream<
lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
@@ -526,9 +613,10 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
return true;
}
-bool lldb_private::formatters::LibcxxStringSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &summary_options) {
+template <StringPrinter::StringElementType element_type>
+bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options,
+ std::string prefix_token = "") {
uint64_t size = 0;
ValueObjectSP location_sp;
@@ -557,31 +645,37 @@ bool lldb_private::formatters::LibcxxStringSummaryProvider(
options.SetData(extractor);
options.SetStream(&stream);
- options.SetPrefixToken(nullptr);
+
+ if (prefix_token.empty())
+ options.SetPrefixToken(nullptr);
+ else
+ options.SetPrefixToken(prefix_token);
+
options.SetQuote('"');
options.SetSourceSize(size);
options.SetBinaryZeroIsTerminator(false);
- StringPrinter::ReadBufferAndDumpToStream<
- StringPrinter::StringElementType::ASCII>(options);
+ StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
return true;
}
-class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd {
-public:
- LibcxxFunctionFrontEnd(ValueObject &backend)
- : SyntheticValueProviderFrontEnd(backend) {}
+bool lldb_private::formatters::LibcxxStringSummaryProviderASCII(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return LibcxxStringSummaryProvider<StringPrinter::StringElementType::ASCII>(
+ valobj, stream, summary_options);
+}
- lldb::ValueObjectSP GetSyntheticValue() override {
- static ConstString g___f_("__f_");
- return m_backend.GetChildMemberWithName(g___f_, true);
- }
-};
+bool lldb_private::formatters::LibcxxStringSummaryProviderUTF16(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return LibcxxStringSummaryProvider<StringPrinter::StringElementType::UTF16>(
+ valobj, stream, summary_options, "u");
+}
-SyntheticChildrenFrontEnd *
-lldb_private::formatters::LibcxxFunctionFrontEndCreator(
- CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- if (valobj_sp)
- return new LibcxxFunctionFrontEnd(*valobj_sp);
- return nullptr;
+bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return LibcxxStringSummaryProvider<StringPrinter::StringElementType::UTF32>(
+ valobj, stream, summary_options, "U");
}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h
index 3f6e0d6e14d7..224a540eda04 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -19,19 +19,35 @@
namespace lldb_private {
namespace formatters {
-bool LibcxxStringSummaryProvider(
+bool LibcxxStringSummaryProviderASCII(
ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::string
+ const TypeSummaryOptions &summary_options); // libc++ std::string
+
+bool LibcxxStringSummaryProviderUTF16(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options); // libc++ std::u16string
+
+bool LibcxxStringSummaryProviderUTF32(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options); // libc++ std::u32string
bool LibcxxWStringSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libc++ std::wstring
+bool LibcxxOptionalSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::optional<>
+
bool LibcxxSmartPointerSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions
&options); // libc++ std::shared_ptr<> and std::weak_ptr<>
+bool LibcxxFunctionSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::function<>
+
SyntheticChildrenFrontEnd *
LibcxxVectorBoolSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
@@ -124,15 +140,20 @@ SyntheticChildrenFrontEnd *
LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
-SyntheticChildrenFrontEnd *LibcxxFunctionFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP);
-
SyntheticChildrenFrontEnd *LibcxxQueueFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
+SyntheticChildrenFrontEnd *
+LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
+
+SyntheticChildrenFrontEnd *
+LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
+
} // namespace formatters
} // namespace lldb_private
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
index 0cdb0b26cf3b..489ac4d96072 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
@@ -79,17 +79,24 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) {
CompilerType type;
ValueObjectSP chunk;
// For small bitsets __first_ is not an array, but a plain size_t.
- if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr))
- chunk = m_first->GetChildAtIndex(
- idx / type.GetBitSize(ctx.GetBestExecutionContextScope()), true);
- else {
+ if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) {
+ llvm::Optional<uint64_t> bit_size =
+ type.GetBitSize(ctx.GetBestExecutionContextScope());
+ if (!bit_size || *bit_size == 0)
+ return {};
+ chunk = m_first->GetChildAtIndex(idx / *bit_size, true);
+ } else {
type = m_first->GetCompilerType();
chunk = m_first;
}
if (!type || !chunk)
- return ValueObjectSP();
+ return {};
- size_t chunk_idx = idx % type.GetBitSize(ctx.GetBestExecutionContextScope());
+ llvm::Optional<uint64_t> bit_size =
+ type.GetBitSize(ctx.GetBestExecutionContextScope());
+ if (!bit_size || *bit_size == 0)
+ return {};
+ size_t chunk_idx = idx % *bit_size;
uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx));
DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size);
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
index 5823f6f3e038..390483d02668 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
@@ -98,12 +94,11 @@ bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
if (!m_element_type.IsValid())
return false;
- m_element_size = m_element_type.GetByteSize(nullptr);
-
- if (m_element_size > 0)
- m_start =
- m_backend.GetChildMemberWithName(g___begin_, true)
- .get(); // store raw pointers or end up with a circular dependency
+ if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
+ m_element_size = *size;
+ // Store raw pointers or end up with a circular dependency.
+ m_start = m_backend.GetChildMemberWithName(g___begin_, true).get();
+ }
return false;
}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 6066f14b18cc..81606b573cea 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 8f82bdcbfd59..429569d57928 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp
new file mode 100644
index 000000000000..762b824f262a
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp
@@ -0,0 +1,85 @@
+//===-- LibCxxOptional.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+class OptionalFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ OptionalFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
+ Update();
+ }
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override {
+ return formatters::ExtractIndexFromString(name.GetCString());
+ }
+
+ bool MightHaveChildren() override { return true; }
+ bool Update() override;
+ size_t CalculateNumChildren() override { return m_size; }
+ ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+private:
+ size_t m_size = 0;
+ ValueObjectSP m_base_sp;
+};
+} // namespace
+
+bool OptionalFrontEnd::Update() {
+ ValueObjectSP engaged_sp(
+ m_backend.GetChildMemberWithName(ConstString("__engaged_"), true));
+
+ if (!engaged_sp)
+ return false;
+
+ // __engaged_ is a bool flag and is true if the optional contains a value.
+ // Converting it to unsigned gives us a size of 1 if it contains a value
+ // and 0 if not.
+ m_size = engaged_sp->GetValueAsUnsigned(0);
+
+ return false;
+}
+
+ValueObjectSP OptionalFrontEnd::GetChildAtIndex(size_t idx) {
+ if (idx >= m_size)
+ return ValueObjectSP();
+
+ // __val_ contains the underlying value of an optional if it has one.
+ // Currently because it is part of an anonymous union GetChildMemberWithName()
+ // does not peer through and find it unless we are at the parent itself.
+ // We can obtain the parent through __engaged_.
+ ValueObjectSP val_sp(
+ m_backend.GetChildMemberWithName(ConstString("__engaged_"), true)
+ ->GetParent()
+ ->GetChildAtIndex(0, true)
+ ->GetChildMemberWithName(ConstString("__val_"), true));
+
+ if (!val_sp)
+ return ValueObjectSP();
+
+ CompilerType holder_type = val_sp->GetCompilerType();
+
+ if (!holder_type)
+ return ValueObjectSP();
+
+ return val_sp->Clone(ConstString(llvm::formatv("Value").str()));
+}
+
+SyntheticChildrenFrontEnd *
+formatters::LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp) {
+ if (valobj_sp)
+ return new OptionalFrontEnd(*valobj_sp);
+ return nullptr;
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
index 0f1c2537d651..51ae8cb3184c 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
new file mode 100644
index 000000000000..e874616c3251
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
@@ -0,0 +1,256 @@
+//===-- LibCxxVariant.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxxVariant.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/ScopeExit.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// libc++ variant implementation contains two members that we care about both
+// are contained in the __impl member.
+// - __index which tells us which of the variadic template types is the active
+// type for the variant
+// - __data is a variadic union which recursively contains itself as member
+// which refers to the tailing variadic types.
+// - __head which refers to the leading non pack type
+// - __value refers to the actual value contained
+// - __tail which refers to the remaining pack types
+//
+// e.g. given std::variant<int,double,char> v1
+//
+// (lldb) frame var -R v1.__impl.__data
+//(... __union<... 0, int, double, char>) v1.__impl.__data = {
+// ...
+// __head = {
+// __value = ...
+// }
+// __tail = {
+// ...
+// __head = {
+// __value = ...
+// }
+// __tail = {
+// ...
+// __head = {
+// __value = ...
+// ...
+//
+// So given
+// - __index equal to 0 the active value is contained in
+//
+// __data.__head.__value
+//
+// - __index equal to 1 the active value is contained in
+//
+// __data.__tail.__head.__value
+//
+// - __index equal to 2 the active value is contained in
+//
+// __data.__tail.__tail.__head.__value
+//
+
+namespace {
+// libc++ std::variant index could have one of three states
+// 1) VALID, we can obtain it and its not variant_npos
+// 2) INVALID, we can't obtain it or it is not a type we expect
+// 3) NPOS, its value is variant_npos which means the variant has no value
+enum class LibcxxVariantIndexValidity { VALID, INVALID, NPOS };
+
+LibcxxVariantIndexValidity
+LibcxxVariantGetIndexValidity(ValueObjectSP &impl_sp) {
+ ValueObjectSP index_sp(
+ impl_sp->GetChildMemberWithName(ConstString("__index"), true));
+
+ if (!index_sp)
+ return LibcxxVariantIndexValidity::INVALID;
+
+ int64_t index_value = index_sp->GetValueAsSigned(0);
+
+ if (index_value == -1)
+ return LibcxxVariantIndexValidity::NPOS;
+
+ return LibcxxVariantIndexValidity::VALID;
+}
+
+llvm::Optional<uint64_t> LibcxxVariantIndexValue(ValueObjectSP &impl_sp) {
+ ValueObjectSP index_sp(
+ impl_sp->GetChildMemberWithName(ConstString("__index"), true));
+
+ if (!index_sp)
+ return {};
+
+ return {index_sp->GetValueAsUnsigned(0)};
+}
+
+ValueObjectSP LibcxxVariantGetNthHead(ValueObjectSP &impl_sp, uint64_t index) {
+ ValueObjectSP data_sp(
+ impl_sp->GetChildMemberWithName(ConstString("__data"), true));
+
+ if (!data_sp)
+ return ValueObjectSP{};
+
+ ValueObjectSP current_level = data_sp;
+ for (uint64_t n = index; n != 0; --n) {
+ ValueObjectSP tail_sp(
+ current_level->GetChildMemberWithName(ConstString("__tail"), true));
+
+ if (!tail_sp)
+ return ValueObjectSP{};
+
+ current_level = tail_sp;
+ }
+
+ return current_level->GetChildMemberWithName(ConstString("__head"), true);
+}
+} // namespace
+
+namespace lldb_private {
+namespace formatters {
+bool LibcxxVariantSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+ if (!valobj_sp)
+ return false;
+
+ ValueObjectSP impl_sp(
+ valobj_sp->GetChildMemberWithName(ConstString("__impl"), true));
+
+ if (!impl_sp)
+ return false;
+
+ LibcxxVariantIndexValidity validity = LibcxxVariantGetIndexValidity(impl_sp);
+
+ if (validity == LibcxxVariantIndexValidity::INVALID)
+ return false;
+
+ if (validity == LibcxxVariantIndexValidity::NPOS) {
+ stream.Printf(" No Value");
+ return true;
+ }
+
+ auto optional_index_value = LibcxxVariantIndexValue(impl_sp);
+
+ if (!optional_index_value)
+ return false;
+
+ uint64_t index_value = *optional_index_value;
+
+ ValueObjectSP nth_head = LibcxxVariantGetNthHead(impl_sp, index_value);
+
+ if (!nth_head)
+ return false;
+
+ CompilerType head_type = nth_head->GetCompilerType();
+
+ if (!head_type)
+ return false;
+
+ CompilerType template_type = head_type.GetTypeTemplateArgument(1);
+
+ if (!template_type)
+ return false;
+
+ stream.Printf(" Active Type = %s ", template_type.GetTypeName().GetCString());
+
+ return true;
+}
+} // namespace formatters
+} // namespace lldb_private
+
+namespace {
+class VariantFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ VariantFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
+ Update();
+ }
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override {
+ return formatters::ExtractIndexFromString(name.GetCString());
+ }
+
+ bool MightHaveChildren() override { return true; }
+ bool Update() override;
+ size_t CalculateNumChildren() override { return m_size; }
+ ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+private:
+ size_t m_size = 0;
+ ValueObjectSP m_base_sp;
+};
+} // namespace
+
+bool VariantFrontEnd::Update() {
+ m_size = 0;
+ ValueObjectSP impl_sp(
+ m_backend.GetChildMemberWithName(ConstString("__impl"), true));
+ if (!impl_sp)
+ return false;
+
+ LibcxxVariantIndexValidity validity = LibcxxVariantGetIndexValidity(impl_sp);
+
+ if (validity == LibcxxVariantIndexValidity::INVALID)
+ return false;
+
+ if (validity == LibcxxVariantIndexValidity::NPOS)
+ return true;
+
+ m_size = 1;
+
+ return false;
+}
+
+ValueObjectSP VariantFrontEnd::GetChildAtIndex(size_t idx) {
+ if (idx >= m_size)
+ return ValueObjectSP();
+
+ ValueObjectSP impl_sp(
+ m_backend.GetChildMemberWithName(ConstString("__impl"), true));
+
+ auto optional_index_value = LibcxxVariantIndexValue(impl_sp);
+
+ if (!optional_index_value)
+ return ValueObjectSP();
+
+ uint64_t index_value = *optional_index_value;
+
+ ValueObjectSP nth_head = LibcxxVariantGetNthHead(impl_sp, index_value);
+
+ if (!nth_head)
+ return ValueObjectSP();
+
+ CompilerType head_type = nth_head->GetCompilerType();
+
+ if (!head_type)
+ return ValueObjectSP();
+
+ CompilerType template_type = head_type.GetTypeTemplateArgument(1);
+
+ if (!template_type)
+ return ValueObjectSP();
+
+ ValueObjectSP head_value(
+ nth_head->GetChildMemberWithName(ConstString("__value"), true));
+
+ if (!head_value)
+ return ValueObjectSP();
+
+ return head_value->Clone(ConstString(ConstString("Value").AsCString()));
+}
+
+SyntheticChildrenFrontEnd *
+formatters::LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp) {
+ if (valobj_sp)
+ return new VariantFrontEnd(*valobj_sp);
+ return nullptr;
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.h b/source/Plugins/Language/CPlusPlus/LibCxxVariant.h
new file mode 100644
index 000000000000..04834581963f
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.h
@@ -0,0 +1,31 @@
+//===-- LibCxxVariant.h -------------------------------------------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibCxxVariant_h_
+#define liblldb_LibCxxVariant_h_
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Utility/Stream.h"
+
+namespace lldb_private {
+namespace formatters {
+bool LibcxxVariantSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::variant<>
+
+SyntheticChildrenFrontEnd *LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP);
+
+} // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibCxxVariant_h_
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
index 711130639cd2..ed405c875174 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
@@ -149,14 +145,16 @@ bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() {
if (!data_type_finder_sp)
return false;
m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
- m_element_size = m_element_type.GetByteSize(nullptr);
+ if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
+ m_element_size = *size;
- if (m_element_size > 0) {
- // store raw pointers or end up with a circular dependency
- m_start =
- m_backend.GetChildMemberWithName(ConstString("__begin_"), true).get();
- m_finish =
- m_backend.GetChildMemberWithName(ConstString("__end_"), true).get();
+ if (m_element_size > 0) {
+ // store raw pointers or end up with a circular dependency
+ m_start =
+ m_backend.GetChildMemberWithName(ConstString("__begin_"), true).get();
+ m_finish =
+ m_backend.GetChildMemberWithName(ConstString("__end_"), true).get();
+ }
}
return false;
}
@@ -196,27 +194,29 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex(
if (iter != end)
return iter->second;
if (idx >= m_count)
- return ValueObjectSP();
+ return {};
if (m_base_data_address == 0 || m_count == 0)
- return ValueObjectSP();
+ return {};
if (!m_bool_type)
- return ValueObjectSP();
+ return {};
size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
lldb::addr_t byte_location = m_base_data_address + byte_idx;
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
if (!process_sp)
- return ValueObjectSP();
+ return {};
uint8_t byte = 0;
uint8_t mask = 0;
Status err;
size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
if (err.Fail() || bytes_read == 0)
- return ValueObjectSP();
+ return {};
mask = 1 << bit_index;
bool bit_set = ((byte & mask) != 0);
- DataBufferSP buffer_sp(
- new DataBufferHeap(m_bool_type.GetByteSize(nullptr), 0));
+ llvm::Optional<uint64_t> size = m_bool_type.GetByteSize(nullptr);
+ if (!size)
+ return {};
+ DataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
if (bit_set && buffer_sp && buffer_sp->GetBytes()) {
// regardless of endianness, anything non-zero is true
*(buffer_sp->GetBytes()) = 1;
diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 3e2b7159f894..695371fc3992 100644
--- a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -9,10 +9,6 @@
#include "LibStdcpp.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/StringPrinter.h"
@@ -301,8 +297,11 @@ bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
if (!wchar_compiler_type)
return false;
- const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
- nullptr); // Safe to pass NULL for exe_scope here
+ // Safe to pass nullptr for exe_scope here.
+ llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ const uint32_t wchar_size = *size;
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
Status error;
diff --git a/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp
new file mode 100644
index 000000000000..84f03e0e3016
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp
@@ -0,0 +1,99 @@
+//===-- MSVCUndecoratedNameParser.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSVCUndecoratedNameParser.h"
+
+#include <stack>
+
+MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) {
+ std::size_t last_base_start = 0;
+
+ std::stack<std::size_t> stack;
+ unsigned int open_angle_brackets = 0;
+ for (size_t i = 0; i < name.size(); i++) {
+ switch (name[i]) {
+ case '<':
+ // Do not treat `operator<' and `operator<<' as templates
+ // (sometimes they represented as `<' and `<<' in the name).
+ if (i == last_base_start ||
+ (i == last_base_start + 1 && name[last_base_start] == '<'))
+ break;
+
+ stack.push(i);
+ open_angle_brackets++;
+
+ break;
+ case '>':
+ if (!stack.empty() && name[stack.top()] == '<') {
+ open_angle_brackets--;
+ stack.pop();
+ }
+
+ break;
+ case '`':
+ stack.push(i);
+
+ break;
+ case '\'':
+ while (!stack.empty()) {
+ std::size_t top = stack.top();
+ if (name[top] == '<')
+ open_angle_brackets--;
+
+ stack.pop();
+
+ if (name[top] == '`')
+ break;
+ }
+
+ break;
+ case ':':
+ if (open_angle_brackets)
+ break;
+ if (i == 0 || name[i - 1] != ':')
+ break;
+
+ m_specifiers.emplace_back(name.take_front(i - 1),
+ name.slice(last_base_start, i - 1));
+
+ last_base_start = i + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ m_specifiers.emplace_back(name, name.drop_front(last_base_start));
+}
+
+bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) {
+ return name.find('`') != llvm::StringRef::npos;
+}
+
+bool MSVCUndecoratedNameParser::ExtractContextAndIdentifier(
+ llvm::StringRef name, llvm::StringRef &context,
+ llvm::StringRef &identifier) {
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+ std::size_t count = specs.size();
+ identifier = count > 0 ? specs[count - 1].GetBaseName() : "";
+ context = count > 1 ? specs[count - 2].GetFullName() : "";
+
+ return count;
+}
+
+llvm::StringRef MSVCUndecoratedNameParser::DropScope(llvm::StringRef name) {
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+ if (specs.empty())
+ return "";
+
+ return specs[specs.size() - 1].GetBaseName();
+}
diff --git a/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h
new file mode 100644
index 000000000000..0c49100d8d49
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h
@@ -0,0 +1,51 @@
+//===-- MSVCUndecoratedNameParser.h -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_MSVCUndecoratedNameParser_h_
+#define liblldb_MSVCUndecoratedNameParser_h_
+
+#include <vector>
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+class MSVCUndecoratedNameSpecifier {
+public:
+ MSVCUndecoratedNameSpecifier(llvm::StringRef full_name,
+ llvm::StringRef base_name)
+ : m_full_name(full_name), m_base_name(base_name) {}
+
+ llvm::StringRef GetFullName() const { return m_full_name; }
+ llvm::StringRef GetBaseName() const { return m_base_name; }
+
+private:
+ llvm::StringRef m_full_name;
+ llvm::StringRef m_base_name;
+};
+
+class MSVCUndecoratedNameParser {
+public:
+ explicit MSVCUndecoratedNameParser(llvm::StringRef name);
+
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> GetSpecifiers() const {
+ return m_specifiers;
+ }
+
+ static bool IsMSVCUndecoratedName(llvm::StringRef name);
+ static bool ExtractContextAndIdentifier(llvm::StringRef name,
+ llvm::StringRef &context,
+ llvm::StringRef &identifier);
+
+ static llvm::StringRef DropScope(llvm::StringRef name);
+
+private:
+ std::vector<MSVCUndecoratedNameSpecifier> m_specifiers;
+};
+
+#endif
diff --git a/source/Plugins/Language/ClangCommon/CMakeLists.txt b/source/Plugins/Language/ClangCommon/CMakeLists.txt
new file mode 100644
index 000000000000..854320dd312e
--- /dev/null
+++ b/source/Plugins/Language/ClangCommon/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_lldb_library(lldbPluginClangCommon PLUGIN
+ ClangHighlighter.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+)
diff --git a/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
new file mode 100644
index 000000000000..1fe8482263eb
--- /dev/null
+++ b/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
@@ -0,0 +1,237 @@
+//===-- ClangHighlighter.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangHighlighter.h"
+
+#include "lldb/Target/Language.h"
+#include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/StreamString.h"
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace lldb_private;
+
+bool ClangHighlighter::isKeyword(llvm::StringRef token) const {
+ return keywords.find(token) != keywords.end();
+}
+
+ClangHighlighter::ClangHighlighter() {
+#define KEYWORD(X, N) keywords.insert(#X);
+#include "clang/Basic/TokenKinds.def"
+}
+
+/// Determines which style should be applied to the given token.
+/// \param highlighter
+/// The current highlighter that should use the style.
+/// \param token
+/// The current token.
+/// \param tok_str
+/// The string in the source code the token represents.
+/// \param options
+/// The style we use for coloring the source code.
+/// \param in_pp_directive
+/// If we are currently in a preprocessor directive. NOTE: This is
+/// passed by reference and will be updated if the current token starts
+/// or ends a preprocessor directive.
+/// \return
+/// The ColorStyle that should be applied to the token.
+static HighlightStyle::ColorStyle
+determineClangStyle(const ClangHighlighter &highlighter,
+ const clang::Token &token, llvm::StringRef tok_str,
+ const HighlightStyle &options, bool &in_pp_directive) {
+ using namespace clang;
+
+ if (token.is(tok::comment)) {
+ // If we were in a preprocessor directive before, we now left it.
+ in_pp_directive = false;
+ return options.comment;
+ } else if (in_pp_directive || token.getKind() == tok::hash) {
+ // Let's assume that the rest of the line is a PP directive.
+ in_pp_directive = true;
+ // Preprocessor directives are hard to match, so we have to hack this in.
+ return options.pp_directive;
+ } else if (tok::isStringLiteral(token.getKind()))
+ return options.string_literal;
+ else if (tok::isLiteral(token.getKind()))
+ return options.scalar_literal;
+ else if (highlighter.isKeyword(tok_str))
+ return options.keyword;
+ else
+ switch (token.getKind()) {
+ case tok::raw_identifier:
+ case tok::identifier:
+ return options.identifier;
+ case tok::l_brace:
+ case tok::r_brace:
+ return options.braces;
+ case tok::l_square:
+ case tok::r_square:
+ return options.square_brackets;
+ case tok::l_paren:
+ case tok::r_paren:
+ return options.parentheses;
+ case tok::comma:
+ return options.comma;
+ case tok::coloncolon:
+ case tok::colon:
+ return options.colon;
+
+ case tok::amp:
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::star:
+ case tok::starequal:
+ case tok::plus:
+ case tok::plusplus:
+ case tok::plusequal:
+ case tok::minus:
+ case tok::arrow:
+ case tok::minusminus:
+ case tok::minusequal:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::slash:
+ case tok::slashequal:
+ case tok::percent:
+ case tok::percentequal:
+ case tok::less:
+ case tok::lessless:
+ case tok::lessequal:
+ case tok::lesslessequal:
+ case tok::spaceship:
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::greaterequal:
+ case tok::greatergreaterequal:
+ case tok::caret:
+ case tok::caretequal:
+ case tok::pipe:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::question:
+ case tok::equal:
+ case tok::equalequal:
+ return options.operators;
+ default:
+ break;
+ }
+ return HighlightStyle::ColorStyle();
+}
+
+void ClangHighlighter::Highlight(const HighlightStyle &options,
+ llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines,
+ Stream &result) const {
+ using namespace clang;
+
+ FileSystemOptions file_opts;
+ FileManager file_mgr(file_opts);
+
+ unsigned line_number = previous_lines.count('\n') + 1U;
+
+ // Let's build the actual source code Clang needs and setup some utility
+ // objects.
+ std::string full_source = previous_lines.str() + line.str();
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
+ llvm::IntrusiveRefCntPtr<DiagnosticOptions> diags_opts(
+ new DiagnosticOptions());
+ DiagnosticsEngine diags(diag_ids, diags_opts);
+ clang::SourceManager SM(diags, file_mgr);
+ auto buf = llvm::MemoryBuffer::getMemBuffer(full_source);
+
+ FileID FID = SM.createFileID(clang::SourceManager::Unowned, buf.get());
+
+ // Let's just enable the latest ObjC and C++ which should get most tokens
+ // right.
+ LangOptions Opts;
+ Opts.ObjC = true;
+ // FIXME: This should probably set CPlusPlus, CPlusPlus11, ... too
+ Opts.CPlusPlus17 = true;
+ Opts.LineComment = true;
+
+ Lexer lex(FID, buf.get(), SM, Opts);
+ // The lexer should keep whitespace around.
+ lex.SetKeepWhitespaceMode(true);
+
+ // Keeps track if we have entered a PP directive.
+ bool in_pp_directive = false;
+
+ // True once we actually lexed the user provided line.
+ bool found_user_line = false;
+
+ // True if we already highlighted the token under the cursor, false otherwise.
+ bool highlighted_cursor = false;
+ Token token;
+ bool exit = false;
+ while (!exit) {
+ // Returns true if this is the last token we get from the lexer.
+ exit = lex.LexFromRawLexer(token);
+
+ bool invalid = false;
+ unsigned current_line_number =
+ SM.getSpellingLineNumber(token.getLocation(), &invalid);
+ if (current_line_number != line_number)
+ continue;
+ found_user_line = true;
+
+ // We don't need to print any tokens without a spelling line number.
+ if (invalid)
+ continue;
+
+ // Same as above but with the column number.
+ invalid = false;
+ unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid);
+ if (invalid)
+ continue;
+ // Column numbers start at 1, but indexes in our string start at 0.
+ --start;
+
+ // Annotations don't have a length, so let's skip them.
+ if (token.isAnnotation())
+ continue;
+
+ // Extract the token string from our source code.
+ llvm::StringRef tok_str = line.substr(start, token.getLength());
+
+ // If the token is just an empty string, we can skip all the work below.
+ if (tok_str.empty())
+ continue;
+
+ // If the cursor is inside this token, we have to apply the 'selected'
+ // highlight style before applying the actual token color.
+ llvm::StringRef to_print = tok_str;
+ StreamString storage;
+ auto end = start + token.getLength();
+ if (cursor_pos && end > *cursor_pos && !highlighted_cursor) {
+ highlighted_cursor = true;
+ options.selected.Apply(storage, tok_str);
+ to_print = storage.GetString();
+ }
+
+ // See how we are supposed to highlight this token.
+ HighlightStyle::ColorStyle color =
+ determineClangStyle(*this, token, tok_str, options, in_pp_directive);
+
+ color.Apply(result, to_print);
+ }
+
+ // If we went over the whole file but couldn't find our own file, then
+ // somehow our setup was wrong. When we're in release mode we just give the
+ // user the normal line and pretend we don't know how to highlight it. In
+ // debug mode we bail out with an assert as this should never happen.
+ if (!found_user_line) {
+ result << line;
+ assert(false && "We couldn't find the user line in the input file?");
+ }
+}
diff --git a/source/Plugins/Language/ClangCommon/ClangHighlighter.h b/source/Plugins/Language/ClangCommon/ClangHighlighter.h
new file mode 100644
index 000000000000..579c4315228f
--- /dev/null
+++ b/source/Plugins/Language/ClangCommon/ClangHighlighter.h
@@ -0,0 +1,38 @@
+//===-- ClangHighlighter.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangHighlighter_h_
+#define liblldb_ClangHighlighter_h_
+
+#include "lldb/Utility/Stream.h"
+#include "llvm/ADT/StringSet.h"
+
+#include "lldb/Core/Highlighter.h"
+
+namespace lldb_private {
+
+class ClangHighlighter : public Highlighter {
+ llvm::StringSet<> keywords;
+
+public:
+ ClangHighlighter();
+ llvm::StringRef GetName() const override { return "clang"; }
+
+ void Highlight(const HighlightStyle &options, llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines, Stream &s) const override;
+
+ /// Returns true if the given string represents a keywords in any Clang
+ /// supported language.
+ bool isKeyword(llvm::StringRef token) const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangHighlighter_h_
diff --git a/source/Plugins/Language/Go/CMakeLists.txt b/source/Plugins/Language/Go/CMakeLists.txt
deleted file mode 100644
index 793e417a618a..000000000000
--- a/source/Plugins/Language/Go/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-add_lldb_library(lldbPluginGoLanguage PLUGIN
- GoLanguage.cpp
- GoFormatterFunctions.cpp
-
- LINK_LIBS
- clangAST
- lldbCore
- lldbDataFormatters
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
-)
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.cpp b/source/Plugins/Language/Go/GoFormatterFunctions.cpp
deleted file mode 100644
index aac75205c6ef..000000000000
--- a/source/Plugins/Language/Go/GoFormatterFunctions.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-#include <map>
-
-// Other libraries and framework includes
-// Project includes
-#include "GoFormatterFunctions.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/DataFormatters/StringPrinter.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-namespace {
-class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
-public:
- GoSliceSyntheticFrontEnd(ValueObject &valobj)
- : SyntheticChildrenFrontEnd(valobj) {
- Update();
- }
-
- ~GoSliceSyntheticFrontEnd() override = default;
-
- size_t CalculateNumChildren() override { return m_len; }
-
- lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
- if (idx < m_len) {
- ValueObjectSP &cached = m_children[idx];
- if (!cached) {
- StreamString idx_name;
- idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- lldb::addr_t object_at_idx = m_base_data_address;
- object_at_idx += idx * m_type.GetByteSize(nullptr);
- cached = CreateValueObjectFromAddress(
- idx_name.GetString(), object_at_idx,
- m_backend.GetExecutionContextRef(), m_type);
- }
- return cached;
- }
- return ValueObjectSP();
- }
-
- bool Update() override {
- size_t old_count = m_len;
-
- ConstString array_const_str("array");
- ValueObjectSP array_sp =
- m_backend.GetChildMemberWithName(array_const_str, true);
- if (!array_sp) {
- m_children.clear();
- return old_count == 0;
- }
- m_type = array_sp->GetCompilerType().GetPointeeType();
- m_base_data_address = array_sp->GetPointerValue();
-
- ConstString len_const_str("len");
- ValueObjectSP len_sp =
- m_backend.GetChildMemberWithName(len_const_str, true);
- if (len_sp) {
- m_len = len_sp->GetValueAsUnsigned(0);
- m_children.clear();
- }
-
- return old_count == m_len;
- }
-
- bool MightHaveChildren() override { return true; }
-
- size_t GetIndexOfChildWithName(const ConstString &name) override {
- return ExtractIndexFromString(name.AsCString());
- }
-
-private:
- CompilerType m_type;
- lldb::addr_t m_base_data_address;
- size_t m_len;
- std::map<size_t, lldb::ValueObjectSP> m_children;
-};
-
-} // anonymous namespace
-
-bool lldb_private::formatters::GoStringSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- if (valobj.IsPointerType()) {
- Status err;
- ValueObjectSP deref = valobj.Dereference(err);
- if (!err.Success())
- return false;
- return GoStringSummaryProvider(*deref, stream, opts);
- }
-
- ConstString str_name("str");
- ConstString len_name("len");
-
- ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true);
- ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true);
- if (!data_sp || !len_sp)
- return false;
- bool success;
- lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success);
-
- if (!success)
- return false;
-
- uint64_t length = len_sp->GetValueAsUnsigned(0);
- if (length == 0) {
- stream.Printf("\"\"");
- return true;
- }
-
- StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(valobj_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetSourceSize(length);
- options.SetNeedsZeroTermination(false);
- options.SetLanguage(eLanguageTypeGo);
-
- if (!StringPrinter::ReadStringAndDumpToStream<
- StringPrinter::StringElementType::UTF8>(options)) {
- stream.Printf("Summary Unavailable");
- return true;
- }
-
- return true;
-}
-
-SyntheticChildrenFrontEnd *
-lldb_private::formatters::GoSliceSyntheticFrontEndCreator(
- CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- if (!valobj_sp)
- return nullptr;
-
- lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
- if (!process_sp)
- return nullptr;
- return new GoSliceSyntheticFrontEnd(*valobj_sp);
-}
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.h b/source/Plugins/Language/Go/GoFormatterFunctions.h
deleted file mode 100644
index 1bf1892d6669..000000000000
--- a/source/Plugins/Language/Go/GoFormatterFunctions.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- GoFormatterFunctions.h-----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_GoFormatterFunctions_h_
-#define liblldb_GoFormatterFunctions_h_
-
-// C Includes
-#include <stdint.h>
-#include <time.h>
-
-// C++ Includes
-// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-
-// Project includes
-#include "lldb/lldb-forward.h"
-
-#include "lldb/DataFormatters/FormatClasses.h"
-#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h"
-
-namespace lldb_private {
-namespace formatters {
-
-bool GoStringSummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options);
-
-SyntheticChildrenFrontEnd *
-GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP);
-
-} // namespace formatters
-} // namespace lldb_private
-
-#endif // liblldb_GoFormatterFunctions_h_
diff --git a/source/Plugins/Language/Go/GoLanguage.cpp b/source/Plugins/Language/Go/GoLanguage.cpp
deleted file mode 100644
index 66b4530abc76..000000000000
--- a/source/Plugins/Language/Go/GoLanguage.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-//===-- GoLanguage.cpp ------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <string.h>
-// C++ Includes
-#include <functional>
-#include <mutex>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Threading.h"
-
-// Project includes
-#include "GoLanguage.h"
-#include "Plugins/Language/Go/GoFormatterFunctions.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Utility/ConstString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-void GoLanguage::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language",
- CreateInstance);
-}
-
-void GoLanguage::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString GoLanguage::GetPluginNameStatic() {
- static ConstString g_name("Go");
- return g_name;
-}
-
-//------------------------------------------------------------------
-// PluginInterface protocol
-//------------------------------------------------------------------
-lldb_private::ConstString GoLanguage::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t GoLanguage::GetPluginVersion() { return 1; }
-
-//------------------------------------------------------------------
-// Static Functions
-//------------------------------------------------------------------
-Language *GoLanguage::CreateInstance(lldb::LanguageType language) {
- if (language == eLanguageTypeGo)
- return new GoLanguage();
- return nullptr;
-}
-
-HardcodedFormatters::HardcodedSummaryFinder
-GoLanguage::GetHardcodedSummaries() {
- static llvm::once_flag g_initialize;
- static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
-
- llvm::call_once(g_initialize, []() -> void {
- g_formatters.push_back(
- [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
- FormatManager &) -> TypeSummaryImpl::SharedPointer {
- static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
- new CXXFunctionSummaryFormat(
- TypeSummaryImpl::Flags().SetDontShowChildren(true),
- lldb_private::formatters::GoStringSummaryProvider,
- "Go string summary provider"));
- if (GoASTContext::IsGoString(valobj.GetCompilerType())) {
- return formatter_sp;
- }
- if (GoASTContext::IsGoString(
- valobj.GetCompilerType().GetPointeeType())) {
- return formatter_sp;
- }
- return nullptr;
- });
- g_formatters.push_back(
- [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
- FormatManager &) -> TypeSummaryImpl::SharedPointer {
- static lldb::TypeSummaryImplSP formatter_sp(new StringSummaryFormat(
- TypeSummaryImpl::Flags().SetHideItemNames(true),
- "(len ${var.len}, cap ${var.cap})"));
- if (GoASTContext::IsGoSlice(valobj.GetCompilerType())) {
- return formatter_sp;
- }
- if (GoASTContext::IsGoSlice(
- valobj.GetCompilerType().GetPointeeType())) {
- return formatter_sp;
- }
- return nullptr;
- });
- });
- return g_formatters;
-}
-
-HardcodedFormatters::HardcodedSyntheticFinder
-GoLanguage::GetHardcodedSynthetics() {
- static llvm::once_flag g_initialize;
- static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
-
- llvm::call_once(g_initialize, []() -> void {
- g_formatters.push_back(
- [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
- FormatManager &fmt_mgr) -> SyntheticChildren::SharedPointer {
- static CXXSyntheticChildren::SharedPointer formatter_sp(
- new CXXSyntheticChildren(
- SyntheticChildren::Flags(), "slice synthetic children",
- lldb_private::formatters::GoSliceSyntheticFrontEndCreator));
- if (GoASTContext::IsGoSlice(valobj.GetCompilerType())) {
- return formatter_sp;
- }
- return nullptr;
- });
- });
-
- return g_formatters;
-}
diff --git a/source/Plugins/Language/Go/GoLanguage.h b/source/Plugins/Language/Go/GoLanguage.h
deleted file mode 100644
index ebec1d7205fa..000000000000
--- a/source/Plugins/Language/Go/GoLanguage.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- GoLanguage.h --------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_GoLanguage_h_
-#define liblldb_GoLanguage_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "lldb/Target/Language.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class GoLanguage : public Language {
-public:
- GoLanguage() = default;
-
- ~GoLanguage() override = default;
-
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeGo;
- }
-
- HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries() override;
-
- HardcodedFormatters::HardcodedSyntheticFinder
- GetHardcodedSynthetics() override;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::Language *CreateInstance(lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_GoLanguage_h_
diff --git a/source/Plugins/Language/Java/CMakeLists.txt b/source/Plugins/Language/Java/CMakeLists.txt
deleted file mode 100644
index f0cbcd8d3f59..000000000000
--- a/source/Plugins/Language/Java/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-add_lldb_library(lldbPluginJavaLanguage PLUGIN
- JavaFormatterFunctions.cpp
- JavaLanguage.cpp
-
- LINK_LIBS
- lldbCore
- lldbDataFormatters
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
-)
diff --git a/source/Plugins/Language/Java/JavaFormatterFunctions.cpp b/source/Plugins/Language/Java/JavaFormatterFunctions.cpp
deleted file mode 100644
index 498795c90be8..000000000000
--- a/source/Plugins/Language/Java/JavaFormatterFunctions.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//===-- JavaFormatterFunctions.cpp-------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "JavaFormatterFunctions.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/DataFormatters/StringPrinter.h"
-#include "lldb/Symbol/JavaASTContext.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-namespace {
-
-class JavaArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
-public:
- JavaArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp) {
- if (valobj_sp)
- Update();
- }
-
- size_t CalculateNumChildren() override {
- ValueObjectSP valobj = GetDereferencedValueObject();
- if (!valobj)
- return 0;
-
- CompilerType type = valobj->GetCompilerType();
- uint32_t size = JavaASTContext::CalculateArraySize(type, *valobj);
- if (size == UINT32_MAX)
- return 0;
- return size;
- }
-
- lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
- ValueObjectSP valobj = GetDereferencedValueObject();
- if (!valobj)
- return nullptr;
-
- ProcessSP process_sp = valobj->GetProcessSP();
- if (!process_sp)
- return nullptr;
-
- CompilerType type = valobj->GetCompilerType();
- CompilerType element_type = type.GetArrayElementType();
- lldb::addr_t address =
- valobj->GetAddressOf() +
- JavaASTContext::CalculateArrayElementOffset(type, idx);
-
- Status error;
- size_t byte_size = element_type.GetByteSize(nullptr);
- DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
- size_t bytes_read = process_sp->ReadMemory(address, buffer_sp->GetBytes(),
- byte_size, error);
- if (error.Fail() || byte_size != bytes_read)
- return nullptr;
-
- StreamString name;
- name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- DataExtractor data(buffer_sp, process_sp->GetByteOrder(),
- process_sp->GetAddressByteSize());
- return CreateValueObjectFromData(
- name.GetString(), data, valobj->GetExecutionContextRef(), element_type);
- }
-
- bool Update() override { return false; }
-
- bool MightHaveChildren() override { return true; }
-
- size_t GetIndexOfChildWithName(const ConstString &name) override {
- return ExtractIndexFromString(name.GetCString());
- }
-
-private:
- ValueObjectSP GetDereferencedValueObject() {
- if (!m_backend.IsPointerOrReferenceType())
- return m_backend.GetSP();
-
- Status error;
- return m_backend.Dereference(error);
- }
-};
-
-} // end of anonymous namespace
-
-bool lldb_private::formatters::JavaStringSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
- if (valobj.IsPointerOrReferenceType()) {
- Status error;
- ValueObjectSP deref = valobj.Dereference(error);
- if (error.Fail())
- return false;
- return JavaStringSummaryProvider(*deref, stream, opts);
- }
-
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- ConstString data_name("value");
- ConstString length_name("count");
-
- ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true);
- ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true);
- if (!data_sp || !length_sp)
- return false;
-
- bool success = false;
- uint64_t length = length_sp->GetValueAsUnsigned(0, &success);
- if (!success)
- return false;
-
- if (length == 0) {
- stream.Printf("\"\"");
- return true;
- }
- lldb::addr_t valobj_addr = data_sp->GetAddressOf();
-
- StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(valobj_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetSourceSize(length);
- options.SetNeedsZeroTermination(false);
- options.SetLanguage(eLanguageTypeJava);
-
- if (StringPrinter::ReadStringAndDumpToStream<
- StringPrinter::StringElementType::UTF16>(options))
- return true;
-
- stream.Printf("Summary Unavailable");
- return true;
-}
-
-bool lldb_private::formatters::JavaArraySummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- if (valobj.IsPointerOrReferenceType()) {
- Status error;
- ValueObjectSP deref = valobj.Dereference(error);
- if (error.Fail())
- return false;
- return JavaArraySummaryProvider(*deref, stream, options);
- }
-
- CompilerType type = valobj.GetCompilerType();
- uint32_t size = JavaASTContext::CalculateArraySize(type, valobj);
- if (size == UINT32_MAX)
- return false;
- stream.Printf("[%u]{...}", size);
- return true;
-}
-
-SyntheticChildrenFrontEnd *
-lldb_private::formatters::JavaArraySyntheticFrontEndCreator(
- CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- return valobj_sp ? new JavaArraySyntheticFrontEnd(valobj_sp) : nullptr;
-}
diff --git a/source/Plugins/Language/Java/JavaFormatterFunctions.h b/source/Plugins/Language/Java/JavaFormatterFunctions.h
deleted file mode 100644
index d1983429529c..000000000000
--- a/source/Plugins/Language/Java/JavaFormatterFunctions.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- JavaFormatterFunctions.h---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_JavaFormatterFunctions_h_
-#define liblldb_JavaFormatterFunctions_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-forward.h"
-
-namespace lldb_private {
-namespace formatters {
-
-bool JavaStringSummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options);
-
-bool JavaArraySummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options);
-
-SyntheticChildrenFrontEnd *
-JavaArraySyntheticFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP valobj_sp);
-
-} // namespace formatters
-} // namespace lldb_private
-
-#endif // liblldb_JavaFormatterFunctions_h_
diff --git a/source/Plugins/Language/Java/JavaLanguage.cpp b/source/Plugins/Language/Java/JavaLanguage.cpp
deleted file mode 100644
index b17862f0b6a2..000000000000
--- a/source/Plugins/Language/Java/JavaLanguage.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-//===-- JavaLanguage.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <string.h>
-// C++ Includes
-#include <functional>
-#include <mutex>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Threading.h"
-
-// Project includes
-#include "JavaFormatterFunctions.h"
-#include "JavaLanguage.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/JavaASTContext.h"
-#include "lldb/Utility/ConstString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-void JavaLanguage::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java Language",
- CreateInstance);
-}
-
-void JavaLanguage::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString JavaLanguage::GetPluginNameStatic() {
- static ConstString g_name("Java");
- return g_name;
-}
-
-lldb_private::ConstString JavaLanguage::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t JavaLanguage::GetPluginVersion() { return 1; }
-
-Language *JavaLanguage::CreateInstance(lldb::LanguageType language) {
- if (language == eLanguageTypeJava)
- return new JavaLanguage();
- return nullptr;
-}
-
-bool JavaLanguage::IsNilReference(ValueObject &valobj) {
- if (!valobj.GetCompilerType().IsReferenceType())
- return false;
-
- // If we failed to read the value then it is not a nil reference.
- return valobj.GetValueAsUnsigned(UINT64_MAX) == 0;
-}
-
-lldb::TypeCategoryImplSP JavaLanguage::GetFormatters() {
- static llvm::once_flag g_initialize;
- static TypeCategoryImplSP g_category;
-
- llvm::call_once(g_initialize, [this]() -> void {
- DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
- if (g_category) {
- llvm::StringRef array_regexp("^.*\\[\\]&?$");
-
- lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(
- TypeSummaryImpl::Flags().SetDontShowChildren(true),
- lldb_private::formatters::JavaStringSummaryProvider,
- "java.lang.String summary provider"));
- g_category->GetTypeSummariesContainer()->Add(
- ConstString("java::lang::String"), string_summary_sp);
-
- lldb::TypeSummaryImplSP array_summary_sp(new CXXFunctionSummaryFormat(
- TypeSummaryImpl::Flags().SetDontShowChildren(true),
- lldb_private::formatters::JavaArraySummaryProvider,
- "Java array summary provider"));
- g_category->GetRegexTypeSummariesContainer()->Add(
- RegularExpressionSP(new RegularExpression(array_regexp)),
- array_summary_sp);
-
-#ifndef LLDB_DISABLE_PYTHON
- AddCXXSynthetic(
- g_category,
- lldb_private::formatters::JavaArraySyntheticFrontEndCreator,
- "Java array synthetic children", ConstString(array_regexp),
- SyntheticChildren::Flags().SetCascades(true), true);
-#endif
- }
- });
- return g_category;
-}
diff --git a/source/Plugins/Language/Java/JavaLanguage.h b/source/Plugins/Language/Java/JavaLanguage.h
deleted file mode 100644
index 5b652502a3d1..000000000000
--- a/source/Plugins/Language/Java/JavaLanguage.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===-- JavaLanguage.h ------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_JavaLanguage_h_
-#define liblldb_JavaLanguage_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "lldb/Target/Language.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class JavaLanguage : public Language {
-public:
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeJava;
- }
-
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::Language *CreateInstance(lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- bool IsNilReference(ValueObject &valobj) override;
-
- lldb::TypeCategoryImplSP GetFormatters() override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_JavaLanguage_h_
diff --git a/source/Plugins/Language/OCaml/CMakeLists.txt b/source/Plugins/Language/OCaml/CMakeLists.txt
deleted file mode 100644
index e779ae2acd08..000000000000
--- a/source/Plugins/Language/OCaml/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-add_lldb_library(lldbPluginOCamlLanguage PLUGIN
- OCamlLanguage.cpp
-
- LINK_LIBS
- lldbCore
- lldbDataFormatters
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
-)
-
diff --git a/source/Plugins/Language/OCaml/OCamlLanguage.cpp b/source/Plugins/Language/OCaml/OCamlLanguage.cpp
deleted file mode 100644
index ec24a36fe8f3..000000000000
--- a/source/Plugins/Language/OCaml/OCamlLanguage.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- OCamlLanguage.cpp ----------------------------------------*- C++
-//-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <string.h>
-// C++ Includes
-#include <functional>
-#include <mutex>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "OCamlLanguage.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/OCamlASTContext.h"
-#include "lldb/Utility/ConstString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-void OCamlLanguage::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "OCaml Language",
- CreateInstance);
-}
-
-void OCamlLanguage::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString OCamlLanguage::GetPluginNameStatic() {
- static ConstString g_name("OCaml");
- return g_name;
-}
-
-lldb_private::ConstString OCamlLanguage::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t OCamlLanguage::GetPluginVersion() { return 1; }
-
-Language *OCamlLanguage::CreateInstance(lldb::LanguageType language) {
- if (language == eLanguageTypeOCaml)
- return new OCamlLanguage();
- return nullptr;
-}
-
-bool OCamlLanguage::IsNilReference(ValueObject &valobj) {
- if (!valobj.GetCompilerType().IsReferenceType())
- return false;
-
- // If we failed to read the value then it is not a nil reference.
- return valobj.GetValueAsUnsigned(UINT64_MAX) == 0;
-}
diff --git a/source/Plugins/Language/OCaml/OCamlLanguage.h b/source/Plugins/Language/OCaml/OCamlLanguage.h
deleted file mode 100644
index 21837fe5add4..000000000000
--- a/source/Plugins/Language/OCaml/OCamlLanguage.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===-- OCamlLanguage.h ------------------------------------------*- C++
-//-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_OCamlLanguage_h_
-#define liblldb_OCamlLanguage_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "lldb/Target/Language.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class OCamlLanguage : public Language {
-public:
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeOCaml;
- }
-
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::Language *CreateInstance(lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- bool IsNilReference(ValueObject &valobj) override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_OCamlLanguage_h_
diff --git a/source/Plugins/Language/ObjC/CF.cpp b/source/Plugins/Language/ObjC/CF.cpp
index 9bb8eeab1d2e..e3dab5a1442d 100644
--- a/source/Plugins/Language/ObjC/CF.cpp
+++ b/source/Plugins/Language/ObjC/CF.cpp
@@ -149,7 +149,7 @@ bool lldb_private::formatters::CFBitVectorSummaryProvider(
}
}
- if (is_type_ok == false)
+ if (!is_type_ok)
return false;
Status error;
diff --git a/source/Plugins/Language/ObjC/CMakeLists.txt b/source/Plugins/Language/ObjC/CMakeLists.txt
index 95ace3a3633a..afb68d4de831 100644
--- a/source/Plugins/Language/ObjC/CMakeLists.txt
+++ b/source/Plugins/Language/ObjC/CMakeLists.txt
@@ -31,6 +31,7 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN
lldbTarget
lldbUtility
lldbPluginAppleObjCRuntime
+ lldbPluginClangCommon
EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS}
)
diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp
index 8f278fc2d513..48085378939e 100644
--- a/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/Mangled.h"
@@ -746,6 +742,59 @@ bool lldb_private::formatters::NSURLSummaryProvider(
return false;
}
+/// Bias value for tagged pointer exponents.
+/// Recommended values:
+/// 0x3e3: encodes all dates between distantPast and distantFuture
+/// except for the range within about 1e-28 second of the reference date.
+/// 0x3ef: encodes all dates for a few million years beyond distantPast and
+/// distantFuture, except within about 1e-25 second of the reference date.
+const int TAGGED_DATE_EXPONENT_BIAS = 0x3ef;
+
+typedef union {
+ struct {
+ uint64_t fraction:52; // unsigned
+ uint64_t exponent:11; // signed
+ uint64_t sign:1;
+ };
+ uint64_t i;
+ double d;
+} DoubleBits;
+typedef union {
+ struct {
+ uint64_t fraction:52; // unsigned
+ uint64_t exponent:7; // signed
+ uint64_t sign:1;
+ uint64_t unused:4; // placeholder for pointer tag bits
+ };
+ uint64_t i;
+} TaggedDoubleBits;
+
+static uint64_t decodeExponent(uint64_t exp) {
+ // Tagged exponent field is 7-bit signed. Sign-extend the value to 64 bits
+ // before performing arithmetic.
+ return llvm::SignExtend64<7>(exp) + TAGGED_DATE_EXPONENT_BIAS;
+}
+
+static uint64_t decodeTaggedTimeInterval(uint64_t encodedTimeInterval) {
+ if (encodedTimeInterval == 0)
+ return 0.0;
+ if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
+ return (uint64_t)-0.0;
+
+ TaggedDoubleBits encodedBits = {};
+ encodedBits.i = encodedTimeInterval;
+ DoubleBits decodedBits;
+
+ // Sign and fraction are represented exactly.
+ // Exponent is encoded.
+ assert(encodedBits.unused == 0);
+ decodedBits.sign = encodedBits.sign;
+ decodedBits.fraction = encodedBits.fraction;
+ decodedBits.exponent = decodeExponent(encodedBits.exponent);
+
+ return decodedBits.d;
+}
+
bool lldb_private::formatters::NSDateSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ProcessSP process_sp = valobj.GetProcessSP();
@@ -785,9 +834,9 @@ bool lldb_private::formatters::NSDateSummaryProvider(
if (class_name.IsEmpty())
return false;
+ uint64_t info_bits = 0, value_bits = 0;
if ((class_name == g_NSDate) || (class_name == g___NSDate) ||
(class_name == g___NSTaggedDate)) {
- uint64_t info_bits = 0, value_bits = 0;
if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
date_value_bits = ((value_bits << 8) | (info_bits << 4));
memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
@@ -817,6 +866,14 @@ bool lldb_private::formatters::NSDateSummaryProvider(
stream.Printf("0001-12-30 00:00:00 +0000");
return true;
}
+
+ // Accomodate for the __NSTaggedDate format introduced in Foundation 1600.
+ if (class_name == g___NSTaggedDate) {
+ auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
+ if (runtime && runtime->GetFoundationVersion() >= 1600)
+ date_value = decodeTaggedTimeInterval(value_bits << 4);
+ }
+
// this snippet of code assumes that time_t == seconds since Jan-1-1970 this
// is generally true and POSIXly happy, but might break if a library vendor
// decides to get creative
diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp
index f6d159201951..6c110da9ecc2 100644
--- a/source/Plugins/Language/ObjC/NSArray.cpp
+++ b/source/Plugins/Language/ObjC/NSArray.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
-// Project includes
#include "Cocoa.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
@@ -218,6 +214,25 @@ namespace Foundation1437 {
}
+namespace CallStackArray {
+struct DataDescriptor_32 {
+ uint32_t _data;
+ uint32_t _used;
+ uint32_t _offset;
+ const uint32_t _size = 0;
+};
+
+struct DataDescriptor_64 {
+ uint64_t _data;
+ uint64_t _used;
+ uint64_t _offset;
+ const uint64_t _size = 0;
+};
+
+using NSCallStackArraySyntheticFrontEnd =
+ GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
+} // namespace CallStackArray
+
template <typename D32, typename D64, bool Inline>
class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
@@ -368,6 +383,7 @@ bool lldb_private::formatters::NSArraySummaryProvider(
static const ConstString g_NSArrayCF("__NSCFArray");
static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
+ static const ConstString g_NSCallStackArray("_NSCallStackArray");
if (class_name.IsEmpty())
return false;
@@ -417,7 +433,9 @@ bool lldb_private::formatters::NSArraySummaryProvider(
value = 0;
} else if (class_name == g_NSArray1) {
value = 1;
- } else if (class_name == g_NSArrayCF) {
+ } else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) {
+ // __NSCFArray and _NSCallStackArray store the number of elements as a
+ // pointer-sized value at offset `2 * ptr_size`.
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(
valobj_addr + 2 * ptr_size, ptr_size, 0, error);
@@ -817,6 +835,7 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
static const ConstString g_NSArray1("__NSSingleObjectArrayI");
static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
+ static const ConstString g_NSCallStackArray("_NSCallStackArray");
if (class_name.IsEmpty())
return nullptr;
@@ -846,6 +865,8 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp));
else
return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp));
+ } else if (class_name == g_NSCallStackArray) {
+ return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp));
} else {
auto &map(NSArray_Additionals::GetAdditionalSynthetics());
auto iter = map.find(class_name), end = map.end();
diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp
index 5be051b46bd6..9a7fc2bd97cb 100644
--- a/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"
-// Project includes
#include "NSDictionary.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
diff --git a/source/Plugins/Language/ObjC/NSError.cpp b/source/Plugins/Language/ObjC/NSError.cpp
index 77721e2db326..975bda5179f2 100644
--- a/source/Plugins/Language/ObjC/NSError.cpp
+++ b/source/Plugins/Language/ObjC/NSError.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/ObjC/NSException.cpp b/source/Plugins/Language/ObjC/NSException.cpp
index c6970efae4d3..2404ef9d1003 100644
--- a/source/Plugins/Language/ObjC/NSException.cpp
+++ b/source/Plugins/Language/ObjC/NSException.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
@@ -33,52 +29,78 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-bool lldb_private::formatters::NSException_SummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
+ ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp,
+ ValueObjectSP *reserved_sp) {
ProcessSP process_sp(valobj.GetProcessSP());
if (!process_sp)
return false;
- lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
+ lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
CompilerType valobj_type(valobj.GetCompilerType());
Flags type_flags(valobj_type.GetTypeInfo());
if (type_flags.AllClear(eTypeHasValue)) {
if (valobj.IsBaseClass() && valobj.GetParent())
- ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- } else
- ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ ptr = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ } else {
+ ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
- if (ptr_value == LLDB_INVALID_ADDRESS)
+ if (ptr == LLDB_INVALID_ADDRESS)
return false;
size_t ptr_size = process_sp->GetAddressByteSize();
- lldb::addr_t name_location = ptr_value + 1 * ptr_size;
- lldb::addr_t reason_location = ptr_value + 2 * ptr_size;
Status error;
- lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error);
+ auto name = process_sp->ReadPointerFromMemory(ptr + 1 * ptr_size, error);
if (error.Fail() || name == LLDB_INVALID_ADDRESS)
return false;
-
- lldb::addr_t reason =
- process_sp->ReadPointerFromMemory(reason_location, error);
+ auto reason = process_sp->ReadPointerFromMemory(ptr + 2 * ptr_size, error);
if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
return false;
+ auto userinfo = process_sp->ReadPointerFromMemory(ptr + 3 * ptr_size, error);
+ if (error.Fail() || userinfo == LLDB_INVALID_ADDRESS)
+ return false;
+ auto reserved = process_sp->ReadPointerFromMemory(ptr + 4 * ptr_size, error);
+ if (error.Fail() || reserved == LLDB_INVALID_ADDRESS)
+ return false;
InferiorSizedWord name_isw(name, *process_sp);
InferiorSizedWord reason_isw(reason, *process_sp);
+ InferiorSizedWord userinfo_isw(userinfo, *process_sp);
+ InferiorSizedWord reserved_isw(reserved, *process_sp);
CompilerType voidstar = process_sp->GetTarget()
.GetScratchClangASTContext()
->GetBasicType(lldb::eBasicTypeVoid)
.GetPointerType();
- ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData(
- "name_str", name_isw.GetAsData(process_sp->GetByteOrder()),
- valobj.GetExecutionContextRef(), voidstar);
- ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData(
- "reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()),
- valobj.GetExecutionContextRef(), voidstar);
+ if (name_sp)
+ *name_sp = ValueObject::CreateValueObjectFromData(
+ "name", name_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+ if (reason_sp)
+ *reason_sp = ValueObject::CreateValueObjectFromData(
+ "reason", reason_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+ if (userinfo_sp)
+ *userinfo_sp = ValueObject::CreateValueObjectFromData(
+ "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+ if (reserved_sp)
+ *reserved_sp = ValueObject::CreateValueObjectFromData(
+ "reserved", reserved_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+
+ return true;
+}
+
+bool lldb_private::formatters::NSException_SummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ lldb::ValueObjectSP name_sp;
+ lldb::ValueObjectSP reason_sp;
+ if (!ExtractFields(valobj, &name_sp, &reason_sp, nullptr, nullptr))
+ return false;
if (!name_sp || !reason_sp)
return false;
@@ -101,83 +123,55 @@ public:
: SyntheticChildrenFrontEnd(*valobj_sp) {}
~NSExceptionSyntheticFrontEnd() override = default;
- // no need to delete m_child_ptr - it's kept alive by the cluster manager on
- // our behalf
size_t CalculateNumChildren() override {
- if (m_child_ptr)
- return 1;
- if (m_child_sp)
- return 1;
- return 0;
+ return 4;
}
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
- if (idx != 0)
- return lldb::ValueObjectSP();
-
- if (m_child_ptr)
- return m_child_ptr->GetSP();
- return m_child_sp;
+ switch (idx) {
+ case 0: return m_name_sp;
+ case 1: return m_reason_sp;
+ case 2: return m_userinfo_sp;
+ case 3: return m_reserved_sp;
+ }
+ return lldb::ValueObjectSP();
}
bool Update() override {
- m_child_ptr = nullptr;
- m_child_sp.reset();
-
- ProcessSP process_sp(m_backend.GetProcessSP());
- if (!process_sp)
- return false;
+ m_name_sp.reset();
+ m_reason_sp.reset();
+ m_userinfo_sp.reset();
+ m_reserved_sp.reset();
- lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS;
-
- CompilerType valobj_type(m_backend.GetCompilerType());
- Flags type_flags(valobj_type.GetTypeInfo());
- if (type_flags.AllClear(eTypeHasValue)) {
- if (m_backend.IsBaseClass() && m_backend.GetParent())
- userinfo_location =
- m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- } else
- userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
- if (userinfo_location == LLDB_INVALID_ADDRESS)
- return false;
-
- size_t ptr_size = process_sp->GetAddressByteSize();
-
- userinfo_location += 3 * ptr_size;
- Status error;
- lldb::addr_t userinfo =
- process_sp->ReadPointerFromMemory(userinfo_location, error);
- if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
- return false;
- InferiorSizedWord isw(userinfo, *process_sp);
- m_child_sp = CreateValueObjectFromData(
- "userInfo", isw.GetAsData(process_sp->GetByteOrder()),
- m_backend.GetExecutionContextRef(),
- process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID));
- return false;
+ return ExtractFields(m_backend, &m_name_sp, &m_reason_sp, &m_userinfo_sp,
+ &m_reserved_sp);
}
bool MightHaveChildren() override { return true; }
size_t GetIndexOfChildWithName(const ConstString &name) override {
+ // NSException has 4 members:
+ // NSString *name;
+ // NSString *reason;
+ // NSDictionary *userInfo;
+ // id reserved;
+ static ConstString g___name("name");
+ static ConstString g___reason("reason");
static ConstString g___userInfo("userInfo");
- if (name == g___userInfo)
- return 0;
+ static ConstString g___reserved("reserved");
+ if (name == g___name) return 0;
+ if (name == g___reason) return 1;
+ if (name == g___userInfo) return 2;
+ if (name == g___reserved) return 3;
return UINT32_MAX;
}
private:
- // the child here can be "real" (i.e. an actual child of the root) or
- // synthetized from raw memory if the former, I need to store a plain pointer
- // to it - or else a loop of references will cause this entire hierarchy of
- // values to leak if the latter, then I need to store a SharedPointer to it -
- // so that it only goes away when everyone else in the cluster goes away oh
- // joy!
- ValueObject *m_child_ptr;
- ValueObjectSP m_child_sp;
+ ValueObjectSP m_name_sp;
+ ValueObjectSP m_reason_sp;
+ ValueObjectSP m_userinfo_sp;
+ ValueObjectSP m_reserved_sp;
};
SyntheticChildrenFrontEnd *
diff --git a/source/Plugins/Language/ObjC/NSIndexPath.cpp b/source/Plugins/Language/ObjC/NSIndexPath.cpp
index 9533e96004a5..41df9abb3eb2 100644
--- a/source/Plugins/Language/ObjC/NSIndexPath.cpp
+++ b/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
@@ -130,11 +126,7 @@ public:
return false;
}
- bool MightHaveChildren() override {
- if (m_impl.m_mode == Mode::Invalid)
- return false;
- return true;
- }
+ bool MightHaveChildren() override { return m_impl.m_mode != Mode::Invalid; }
size_t GetIndexOfChildWithName(const ConstString &name) override {
const char *item_name = name.GetCString();
diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp
index 2da4bc034f32..7e03d7574af0 100644
--- a/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/source/Plugins/Language/ObjC/NSSet.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "NSSet.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp
index 0b12edb53d7a..f882b2adc260 100644
--- a/source/Plugins/Language/ObjC/NSString.cpp
+++ b/source/Plugins/Language/ObjC/NSString.cpp
@@ -225,10 +225,10 @@ bool lldb_private::formatters::NSStringSummaryProvider(
options.SetStream(&stream);
options.SetQuote('"');
options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetNeedsZeroTermination(!has_explicit_length);
options.SetIgnoreMaxLength(summary_options.GetCapping() ==
TypeSummaryCapping::eTypeSummaryUncapped);
- options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetBinaryZeroIsTerminator(!has_explicit_length);
options.SetLanguage(summary_options.GetLanguage());
return StringPrinter::ReadStringAndDumpToStream<
StringPrinter::StringElementType::UTF16>(options);
@@ -245,10 +245,10 @@ bool lldb_private::formatters::NSStringSummaryProvider(
options.SetStream(&stream);
options.SetQuote('"');
options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetNeedsZeroTermination(!has_explicit_length);
options.SetIgnoreMaxLength(summary_options.GetCapping() ==
TypeSummaryCapping::eTypeSummaryUncapped);
- options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetBinaryZeroIsTerminator(!has_explicit_length);
options.SetLanguage(summary_options.GetLanguage());
return StringPrinter::ReadStringAndDumpToStream<
StringPrinter::StringElementType::UTF16>(options);
@@ -260,10 +260,7 @@ bool lldb_private::formatters::NSStringSummaryProvider(
Status error;
explicit_length =
process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
- if (error.Fail() || explicit_length == 0)
- has_explicit_length = false;
- else
- has_explicit_length = true;
+ has_explicit_length = !(error.Fail() || explicit_length == 0);
location++;
}
options.SetLocation(location);
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 47874b3be8fd..0598d69f6ebb 100644
--- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "ObjCLanguage.h"
#include "lldb/Core/PluginManager.h"
@@ -413,6 +409,9 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
"NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
AddCXXSummary(
objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
+ "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags);
+ AddCXXSummary(
+ objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
"NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
AddCXXSummary(objc_category_sp,
lldb_private::formatters::NSArraySummaryProvider,
@@ -532,6 +531,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(objc_category_sp,
lldb_private::formatters::NSArraySyntheticFrontEndCreator,
+ "NSArray synthetic children", ConstString("_NSCallStackArray"),
+ ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp,
+ lldb_private::formatters::NSArraySyntheticFrontEndCreator,
"NSArray synthetic children",
ConstString("CFMutableArrayRef"),
ScriptedSyntheticChildren::Flags());
@@ -1102,3 +1105,12 @@ bool ObjCLanguage::IsNilReference(ValueObject &valobj) {
bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
return canReadValue && isZero;
}
+
+bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
+ const auto suffixes = {".h", ".m", ".M"};
+ for (auto suffix : suffixes) {
+ if (file_path.endswith_lower(suffix))
+ return true;
+ }
+ return false;
+}
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.h b/source/Plugins/Language/ObjC/ObjCLanguage.h
index 9782c5da0d67..114f9323de02 100644
--- a/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -10,13 +10,10 @@
#ifndef liblldb_ObjCLanguage_h_
#define liblldb_ObjCLanguage_h_
-// C Includes
-// C++ Includes
#include <cstring>
#include <vector>
-// Other libraries and framework includes
-// Project includes
+#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
@@ -24,6 +21,8 @@
namespace lldb_private {
class ObjCLanguage : public Language {
+ ClangHighlighter m_highlighter;
+
public:
class MethodName {
public:
@@ -121,6 +120,10 @@ public:
bool IsNilReference(ValueObject &valobj) override;
+ bool IsSourceFile(llvm::StringRef file_path) const override;
+
+ const Highlighter *GetHighlighter() const override { return &m_highlighter; }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt b/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
index 75df9794d75d..1aa5cc1ed488 100644
--- a/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
+++ b/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
@@ -1,7 +1,8 @@
add_lldb_library(lldbPluginObjCPlusPlusLanguage PLUGIN
ObjCPlusPlusLanguage.cpp
-
+
LINK_LIBS
lldbCore
lldbTarget
+ lldbPluginClangCommon
)
diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
index bfc22c9ee650..5e6d86e05318 100644
--- a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
+++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -16,6 +16,15 @@
using namespace lldb;
using namespace lldb_private;
+bool ObjCPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
+ const auto suffixes = {".h", ".mm"};
+ for (auto suffix : suffixes) {
+ if (file_path.endswith_lower(suffix))
+ return true;
+ }
+ return false;
+}
+
void ObjCPlusPlusLanguage::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C++ Language",
CreateInstance);
diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
index 588b52215c10..b64f0f81e001 100644
--- a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
+++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -10,16 +10,15 @@
#ifndef liblldb_ObjCPlusPlusLanguage_h_
#define liblldb_ObjCPlusPlusLanguage_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
class ObjCPlusPlusLanguage : public Language {
+ ClangHighlighter m_highlighter;
+
public:
ObjCPlusPlusLanguage() = default;
@@ -29,6 +28,10 @@ public:
return lldb::eLanguageTypeObjC_plus_plus;
}
+ bool IsSourceFile(llvm::StringRef file_path) const override;
+
+ const Highlighter *GetHighlighter() const override { return &m_highlighter; }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------