summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal (nealsid) <nealsid@icloud.com>2021-04-21 15:11:17 +0200
committerRaphael Isemann <teemperor@gmail.com>2021-04-21 15:12:59 +0200
commite2039142f6b196e9a491c8e0b18faa033c4d9f10 (patch)
tree248a7bdec20408c55df6539b296a716d22d5b8d9
parent8e336511f18ab56cd0c8d93b5c18219df411963a (diff)
downloadllvm-e2039142f6b196e9a491c8e0b18faa033c4d9f10.tar.gz
Some FormatEntity.cpp cleanup and unit testing
Just fixing a few things I noticed as I am working on another feature for format strings in the prompt: forward decls, adding constexpr constructors, various checks, and unit tests for FormatEntity::Parse and new Definition constructors, etc. Reviewed By: teemperor Differential Revision: https://reviews.llvm.org/D98153
-rw-r--r--lldb/include/lldb/Core/FormatEntity.h61
-rw-r--r--lldb/source/Core/FormatEntity.cpp420
-rw-r--r--lldb/unittests/Core/CMakeLists.txt1
-rw-r--r--lldb/unittests/Core/FormatEntityTest.cpp159
4 files changed, 417 insertions, 224 deletions
diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h
index 91999f64ab5f..ca16e02c54a5 100644
--- a/lldb/include/lldb/Core/FormatEntity.h
+++ b/lldb/include/lldb/Core/FormatEntity.h
@@ -9,9 +9,6 @@
#ifndef LLDB_CORE_FORMATENTITY_H
#define LLDB_CORE_FORMATENTITY_H
-#include "lldb/Utility/CompletionRequest.h"
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-types.h"
#include <algorithm>
@@ -23,12 +20,16 @@
namespace lldb_private {
class Address;
+class CompletionRequest;
class ExecutionContext;
+class FileSpec;
+class Status;
class Stream;
class StringList;
class SymbolContext;
class ValueObject;
}
+
namespace llvm {
class StringRef;
}
@@ -103,20 +104,52 @@ public:
};
struct Definition {
+ /// The name/string placeholder that corresponds to this definition.
const char *name;
- const char *string; // Insert this exact string into the output
- Entry::Type type;
- uint64_t data;
- uint32_t num_children;
- Definition *children; // An array of "num_children" Definition entries,
- bool keep_separator;
+ /// Insert this exact string into the output
+ const char *string = nullptr;
+ /// Entry::Type corresponding to this definition.
+ const Entry::Type type;
+ /// Data that is returned as the value of the format string.
+ const uint64_t data = 0;
+ /// The number of children of this node in the tree of format strings.
+ const uint32_t num_children = 0;
+ /// An array of "num_children" Definition entries.
+ const Definition *children = nullptr;
+ /// Whether the separator is kept during parsing or not. It's used
+ /// for entries with parameters.
+ const bool keep_separator = false;
+
+ constexpr Definition(const char *name, const FormatEntity::Entry::Type t)
+ : name(name), type(t) {}
+
+ constexpr Definition(const char *name, const char *string)
+ : name(name), string(string), type(Entry::Type::EscapeCode) {}
+
+ constexpr Definition(const char *name, const FormatEntity::Entry::Type t,
+ const uint64_t data)
+ : name(name), string(nullptr), type(t), data(data) {}
+
+ constexpr Definition(const char *name, const FormatEntity::Entry::Type t,
+ const uint64_t num_children,
+ const Definition *children,
+ const bool keep_separator = false)
+ : name(name), type(t), num_children(num_children), children(children),
+ keep_separator(keep_separator) {}
};
+ template <size_t N>
+ static constexpr Definition
+ DefinitionWithChildren(const char *name, const FormatEntity::Entry::Type t,
+ const Definition (&children)[N],
+ bool keep_separator = false) {
+ return Definition(name, t, N, children, keep_separator);
+ }
+
Entry(Type t = Type::Invalid, const char *s = nullptr,
const char *f = nullptr)
- : string(s ? s : ""), printf_format(f ? f : ""), children(),
- definition(nullptr), type(t), fmt(lldb::eFormatDefault), number(0),
- deref(false) {}
+ : string(s ? s : ""), printf_format(f ? f : ""), children(), type(t),
+ fmt(lldb::eFormatDefault), number(0), deref(false) {}
Entry(llvm::StringRef s);
Entry(char ch);
@@ -133,7 +166,6 @@ public:
string.clear();
printf_format.clear();
children.clear();
- definition = nullptr;
type = Type::Invalid;
fmt = lldb::eFormatDefault;
number = 0;
@@ -157,8 +189,6 @@ public:
}
if (children != rhs.children)
return false;
- if (definition != rhs.definition)
- return false;
if (type != rhs.type)
return false;
if (fmt != rhs.fmt)
@@ -171,7 +201,6 @@ public:
std::string string;
std::string printf_format;
std::vector<Entry> children;
- Definition *definition;
Type type;
lldb::Format fmt;
lldb::addr_t number;
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index 0ffd59938897..77b6b1682a9c 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -41,11 +41,13 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
@@ -76,203 +78,196 @@ struct RegisterInfo;
using namespace lldb;
using namespace lldb_private;
-enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
-
-#define ENTRY(n, t) \
- { n, nullptr, FormatEntity::Entry::Type::t, 0, 0, nullptr, false }
-#define ENTRY_VALUE(n, t, v) \
- { n, nullptr, FormatEntity::Entry::Type::t, v, 0, nullptr, false }
-#define ENTRY_CHILDREN(n, t, c) \
- { \
- n, nullptr, FormatEntity::Entry::Type::t, 0, \
- static_cast<uint32_t>(llvm::array_lengthof(c)), c, false \
- }
-#define ENTRY_CHILDREN_KEEP_SEP(n, t, c) \
- { \
- n, nullptr, FormatEntity::Entry::Type::t, 0, \
- static_cast<uint32_t>(llvm::array_lengthof(c)), c, true \
- }
-#define ENTRY_STRING(n, s) \
- { n, s, FormatEntity::Entry::Type::EscapeCode, 0, 0, nullptr, false }
-static FormatEntity::Entry::Definition g_string_entry[] = {
- ENTRY("*", ParentString)};
-
-static FormatEntity::Entry::Definition g_addr_entries[] = {
- ENTRY("load", AddressLoad),
- ENTRY("file", AddressFile),
- ENTRY("load", AddressLoadOrFile),
-};
+using Definition = lldb_private::FormatEntity::Entry::Definition;
+using Entry = FormatEntity::Entry;
+using EntryType = FormatEntity::Entry::Type;
-static FormatEntity::Entry::Definition g_file_child_entries[] = {
- ENTRY_VALUE("basename", ParentNumber, FileKind::Basename),
- ENTRY_VALUE("dirname", ParentNumber, FileKind::Dirname),
- ENTRY_VALUE("fullpath", ParentNumber, FileKind::Fullpath)};
-
-static FormatEntity::Entry::Definition g_frame_child_entries[] = {
- ENTRY("index", FrameIndex),
- ENTRY("pc", FrameRegisterPC),
- ENTRY("fp", FrameRegisterFP),
- ENTRY("sp", FrameRegisterSP),
- ENTRY("flags", FrameRegisterFlags),
- ENTRY("no-debug", FrameNoDebug),
- ENTRY_CHILDREN("reg", FrameRegisterByName, g_string_entry),
- ENTRY("is-artificial", FrameIsArtificial),
-};
-
-static FormatEntity::Entry::Definition g_function_child_entries[] = {
- ENTRY("id", FunctionID),
- ENTRY("name", FunctionName),
- ENTRY("name-without-args", FunctionNameNoArgs),
- ENTRY("name-with-args", FunctionNameWithArgs),
- ENTRY("mangled-name", FunctionMangledName),
- ENTRY("addr-offset", FunctionAddrOffset),
- ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete),
- ENTRY("line-offset", FunctionLineOffset),
- ENTRY("pc-offset", FunctionPCOffset),
- ENTRY("initial-function", FunctionInitial),
- ENTRY("changed", FunctionChanged),
- ENTRY("is-optimized", FunctionIsOptimized)};
-
-static FormatEntity::Entry::Definition g_line_child_entries[] = {
- ENTRY_CHILDREN("file", LineEntryFile, g_file_child_entries),
- ENTRY("number", LineEntryLineNumber),
- ENTRY("column", LineEntryColumn),
- ENTRY("start-addr", LineEntryStartAddress),
- ENTRY("end-addr", LineEntryEndAddress),
-};
-
-static FormatEntity::Entry::Definition g_module_child_entries[] = {
- ENTRY_CHILDREN("file", ModuleFile, g_file_child_entries),
-};
+enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
-static FormatEntity::Entry::Definition g_process_child_entries[] = {
- ENTRY("id", ProcessID),
- ENTRY_VALUE("name", ProcessFile, FileKind::Basename),
- ENTRY_CHILDREN("file", ProcessFile, g_file_child_entries),
+constexpr Definition g_string_entry[] = {
+ Definition("*", EntryType::ParentString)};
+
+constexpr Definition g_addr_entries[] = {
+ Definition("load", EntryType::AddressLoad),
+ Definition("file", EntryType::AddressFile)};
+
+constexpr Definition g_file_child_entries[] = {
+ Definition("basename", EntryType::ParentNumber, FileKind::Basename),
+ Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
+ Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
+
+constexpr Definition g_frame_child_entries[] = {
+ Definition("index", EntryType::FrameIndex),
+ Definition("pc", EntryType::FrameRegisterPC),
+ Definition("fp", EntryType::FrameRegisterFP),
+ Definition("sp", EntryType::FrameRegisterSP),
+ Definition("flags", EntryType::FrameRegisterFlags),
+ Definition("no-debug", EntryType::FrameNoDebug),
+ Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
+ g_string_entry),
+ Definition("is-artificial", EntryType::FrameIsArtificial),
};
-static FormatEntity::Entry::Definition g_svar_child_entries[] = {
- ENTRY("*", ParentString)};
-
-static FormatEntity::Entry::Definition g_var_child_entries[] = {
- ENTRY("*", ParentString)};
-
-static FormatEntity::Entry::Definition g_thread_child_entries[] = {
- ENTRY("id", ThreadID),
- ENTRY("protocol_id", ThreadProtocolID),
- ENTRY("index", ThreadIndexID),
- ENTRY_CHILDREN("info", ThreadInfo, g_string_entry),
- ENTRY("queue", ThreadQueue),
- ENTRY("name", ThreadName),
- ENTRY("stop-reason", ThreadStopReason),
- ENTRY("stop-reason-raw", ThreadStopReasonRaw),
- ENTRY("return-value", ThreadReturnValue),
- ENTRY("completed-expression", ThreadCompletedExpression),
+constexpr Definition g_function_child_entries[] = {
+ Definition("id", EntryType::FunctionID),
+ Definition("name", EntryType::FunctionName),
+ Definition("name-without-args", EntryType::FunctionNameNoArgs),
+ Definition("name-with-args", EntryType::FunctionNameWithArgs),
+ Definition("mangled-name", EntryType::FunctionMangledName),
+ Definition("addr-offset", EntryType::FunctionAddrOffset),
+ Definition("concrete-only-addr-offset-no-padding",
+ EntryType::FunctionAddrOffsetConcrete),
+ Definition("line-offset", EntryType::FunctionLineOffset),
+ Definition("pc-offset", EntryType::FunctionPCOffset),
+ Definition("initial-function", EntryType::FunctionInitial),
+ Definition("changed", EntryType::FunctionChanged),
+ Definition("is-optimized", EntryType::FunctionIsOptimized)};
+
+constexpr Definition g_line_child_entries[] = {
+ Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
+ g_file_child_entries),
+ Definition("number", EntryType::LineEntryLineNumber),
+ Definition("column", EntryType::LineEntryColumn),
+ Definition("start-addr", EntryType::LineEntryStartAddress),
+ Definition("end-addr", EntryType::LineEntryEndAddress),
};
-static FormatEntity::Entry::Definition g_target_child_entries[] = {
- ENTRY("arch", TargetArch),
-};
+constexpr Definition g_module_child_entries[] = {Entry::DefinitionWithChildren(
+ "file", EntryType::ModuleFile, g_file_child_entries)};
+
+constexpr Definition g_process_child_entries[] = {
+ Definition("id", EntryType::ProcessID),
+ Definition("name", EntryType::ProcessFile, FileKind::Basename),
+ Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
+ g_file_child_entries)};
+
+constexpr Definition g_svar_child_entries[] = {
+ Definition("*", EntryType::ParentString)};
+
+constexpr Definition g_var_child_entries[] = {
+ Definition("*", EntryType::ParentString)};
+
+constexpr Definition g_thread_child_entries[] = {
+ Definition("id", EntryType::ThreadID),
+ Definition("protocol_id", EntryType::ThreadProtocolID),
+ Definition("index", EntryType::ThreadIndexID),
+ Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
+ g_string_entry),
+ Definition("queue", EntryType::ThreadQueue),
+ Definition("name", EntryType::ThreadName),
+ Definition("stop-reason", EntryType::ThreadStopReason),
+ Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
+ Definition("return-value", EntryType::ThreadReturnValue),
+ Definition("completed-expression", EntryType::ThreadCompletedExpression)};
+
+constexpr Definition g_target_child_entries[] = {
+ Definition("arch", EntryType::TargetArch)};
#define _TO_STR2(_val) #_val
#define _TO_STR(_val) _TO_STR2(_val)
-static FormatEntity::Entry::Definition g_ansi_fg_entries[] = {
- ENTRY_STRING("black",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
- ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
- ENTRY_STRING("green",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
- ENTRY_STRING("yellow",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
- ENTRY_STRING("blue",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
- ENTRY_STRING("purple",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
- ENTRY_STRING("cyan",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
- ENTRY_STRING("white",
- ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
-};
-
-static FormatEntity::Entry::Definition g_ansi_bg_entries[] = {
- ENTRY_STRING("black",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
- ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
- ENTRY_STRING("green",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
- ENTRY_STRING("yellow",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
- ENTRY_STRING("blue",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
- ENTRY_STRING("purple",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
- ENTRY_STRING("cyan",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
- ENTRY_STRING("white",
- ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
-};
-
-static FormatEntity::Entry::Definition g_ansi_entries[] = {
- ENTRY_CHILDREN("fg", Invalid, g_ansi_fg_entries),
- ENTRY_CHILDREN("bg", Invalid, g_ansi_bg_entries),
- ENTRY_STRING("normal",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
- ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
- ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
- ENTRY_STRING("italic",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
- ENTRY_STRING("underline",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
- ENTRY_STRING("slow-blink",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
- ENTRY_STRING("fast-blink",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
- ENTRY_STRING("negative",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
- ENTRY_STRING("conceal",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
- ENTRY_STRING("crossed-out",
- ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
+constexpr Definition g_ansi_fg_entries[] = {
+ Definition("black",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
+ Definition("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
+ Definition("green",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
+ Definition("yellow",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
+ Definition("blue", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
+ Definition("purple",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
+ Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
+ Definition("white",
+ ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_script_child_entries[] = {
- ENTRY("frame", ScriptFrame), ENTRY("process", ScriptProcess),
- ENTRY("target", ScriptTarget), ENTRY("thread", ScriptThread),
- ENTRY("var", ScriptVariable), ENTRY("svar", ScriptVariableSynthetic),
- ENTRY("thread", ScriptThread),
+constexpr Definition g_ansi_bg_entries[] = {
+ Definition("black",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
+ Definition("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
+ Definition("green",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
+ Definition("yellow",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
+ Definition("blue", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
+ Definition("purple",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
+ Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
+ Definition("white",
+ ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_top_level_entries[] = {
- ENTRY_CHILDREN("addr", AddressLoadOrFile, g_addr_entries),
- ENTRY("addr-file-or-load", AddressLoadOrFile),
- ENTRY_CHILDREN("ansi", Invalid, g_ansi_entries),
- ENTRY("current-pc-arrow", CurrentPCArrow),
- ENTRY_CHILDREN("file", File, g_file_child_entries),
- ENTRY("language", Lang),
- ENTRY_CHILDREN("frame", Invalid, g_frame_child_entries),
- ENTRY_CHILDREN("function", Invalid, g_function_child_entries),
- ENTRY_CHILDREN("line", Invalid, g_line_child_entries),
- ENTRY_CHILDREN("module", Invalid, g_module_child_entries),
- ENTRY_CHILDREN("process", Invalid, g_process_child_entries),
- ENTRY_CHILDREN("script", Invalid, g_script_child_entries),
- ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, g_svar_child_entries),
- ENTRY_CHILDREN("thread", Invalid, g_thread_child_entries),
- ENTRY_CHILDREN("target", Invalid, g_target_child_entries),
- ENTRY_CHILDREN_KEEP_SEP("var", Variable, g_var_child_entries),
+constexpr Definition g_ansi_entries[] = {
+ Entry::DefinitionWithChildren("fg", EntryType::Invalid, g_ansi_fg_entries),
+ Entry::DefinitionWithChildren("bg", EntryType::Invalid, g_ansi_bg_entries),
+ Definition("normal", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
+ Definition("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
+ Definition("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
+ Definition("italic", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
+ Definition("underline",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
+ Definition("slow-blink",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
+ Definition("fast-blink",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
+ Definition("negative",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
+ Definition("conceal",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
+ Definition("crossed-out",
+ ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
};
-static FormatEntity::Entry::Definition g_root =
- ENTRY_CHILDREN("<root>", Root, g_top_level_entries);
+constexpr Definition g_script_child_entries[] = {
+ Definition("frame", EntryType::ScriptFrame),
+ Definition("process", EntryType::ScriptProcess),
+ Definition("target", EntryType::ScriptTarget),
+ Definition("thread", EntryType::ScriptThread),
+ Definition("var", EntryType::ScriptVariable),
+ Definition("svar", EntryType::ScriptVariableSynthetic),
+ Definition("thread", EntryType::ScriptThread)};
+
+constexpr Definition g_top_level_entries[] = {
+ Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
+ g_addr_entries),
+ Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
+ Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
+ Definition("current-pc-arrow", EntryType::CurrentPCArrow),
+ Entry::DefinitionWithChildren("file", EntryType::File,
+ g_file_child_entries),
+ Definition("language", EntryType::Lang),
+ Entry::DefinitionWithChildren("frame", EntryType::Invalid,
+ g_frame_child_entries),
+ Entry::DefinitionWithChildren("function", EntryType::Invalid,
+ g_function_child_entries),
+ Entry::DefinitionWithChildren("line", EntryType::Invalid,
+ g_line_child_entries),
+ Entry::DefinitionWithChildren("module", EntryType::Invalid,
+ g_module_child_entries),
+ Entry::DefinitionWithChildren("process", EntryType::Invalid,
+ g_process_child_entries),
+ Entry::DefinitionWithChildren("script", EntryType::Invalid,
+ g_script_child_entries),
+ Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
+ g_svar_child_entries, true),
+ Entry::DefinitionWithChildren("thread", EntryType::Invalid,
+ g_thread_child_entries),
+ Entry::DefinitionWithChildren("target", EntryType::Invalid,
+ g_target_child_entries),
+ Entry::DefinitionWithChildren("var", EntryType::Variable,
+ g_var_child_entries, true)};
+
+constexpr Definition g_root = Entry::DefinitionWithChildren(
+ "<root>", EntryType::Root, g_top_level_entries);
FormatEntity::Entry::Entry(llvm::StringRef s)
: string(s.data(), s.size()), printf_format(), children(),
- definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault),
- number(0), deref(false) {}
+ type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
FormatEntity::Entry::Entry(char ch)
- : string(1, ch), printf_format(), children(), definition(nullptr),
- type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {}
+ : string(1, ch), printf_format(), children(), type(Type::String),
+ fmt(lldb::eFormatDefault), number(0), deref(false) {}
void FormatEntity::Entry::AppendChar(char ch) {
if (children.empty() || children.back().type != Entry::Type::String)
@@ -598,9 +593,7 @@ static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
}
static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
- uint32_t reg_num, Format format)
-
-{
+ uint32_t reg_num, Format format) {
if (frame) {
RegisterContext *reg_ctx = frame->GetRegisterContext().get();
@@ -624,7 +617,6 @@ static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
}
static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
- StackFrame *frame,
bool deref_pointer) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
const char *ptr_deref_format = "[%d]";
@@ -956,9 +948,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc,
bool success = true;
for (int64_t index = index_lower; index <= index_higher; ++index) {
- ValueObject *item =
- ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false)
- .get();
+ ValueObject *item = ExpandIndexedExpression(target, index, false).get();
if (!item) {
LLDB_LOGF(log,
@@ -1523,17 +1513,22 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return initial_function;
case Entry::Type::FunctionName: {
+ if (!sc)
+ return false;
+
Language *language_plugin = nullptr;
bool language_plugin_handled = false;
StreamString ss;
+
if (sc->function)
language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin) {
+
+ if (language_plugin)
language_plugin_handled = language_plugin->GetFunctionDisplayName(
sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
- }
+
if (language_plugin_handled) {
s << ss.GetString();
return true;
@@ -1543,6 +1538,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
name = sc->function->GetName().AsCString(nullptr);
else if (sc->symbol)
name = sc->symbol->GetName().AsCString(nullptr);
+
if (name) {
s.PutCString(name);
@@ -1564,6 +1560,9 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionNameNoArgs: {
+ if (!sc)
+ return false;
+
Language *language_plugin = nullptr;
bool language_plugin_handled = false;
StreamString ss;
@@ -1571,11 +1570,12 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin) {
+
+ if (language_plugin)
language_plugin_handled = language_plugin->GetFunctionDisplayName(
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
ss);
- }
+
if (language_plugin_handled) {
s << ss.GetString();
return true;
@@ -1594,6 +1594,9 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionNameWithArgs: {
+ if (!sc)
+ return false;
+
Language *language_plugin = nullptr;
bool language_plugin_handled = false;
StreamString ss;
@@ -1601,10 +1604,11 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
- if (language_plugin) {
+
+ if (language_plugin)
language_plugin_handled = language_plugin->GetFunctionDisplayName(
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
- }
+
if (language_plugin_handled) {
s << ss.GetString();
return true;
@@ -1756,6 +1760,9 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionMangledName: {
+ if (!sc)
+ return false;
+
const char *name = nullptr;
if (sc->symbol)
name =
@@ -1778,7 +1785,6 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
}
return true;
}
-
case Entry::Type::FunctionAddrOffset:
if (addr) {
if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
@@ -1796,9 +1802,11 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
case Entry::Type::FunctionLineOffset:
- return (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
- sc->line_entry.range.GetBaseAddress(),
- false, false, false));
+ if (sc)
+ return (DumpAddressOffsetFromFunction(
+ s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
+ false));
+ return false;
case Entry::Type::FunctionPCOffset:
if (exe_ctx) {
@@ -1817,7 +1825,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
case Entry::Type::FunctionIsOptimized: {
bool is_optimized = false;
- if (sc->function && sc->function->GetIsOptimized()) {
+ if (sc && sc->function && sc->function->GetIsOptimized()) {
is_optimized = true;
}
return is_optimized;
@@ -1891,8 +1899,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return false;
}
-static bool DumpCommaSeparatedChildEntryNames(
- Stream &s, const FormatEntity::Entry::Definition *parent) {
+static bool DumpCommaSeparatedChildEntryNames(Stream &s,
+ const Definition *parent) {
if (parent->children) {
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
@@ -1906,8 +1914,7 @@ static bool DumpCommaSeparatedChildEntryNames(
}
static Status ParseEntry(const llvm::StringRef &format_str,
- const FormatEntity::Entry::Definition *parent,
- FormatEntity::Entry &entry) {
+ const Definition *parent, FormatEntity::Entry &entry) {
Status error;
const size_t sep_pos = format_str.find_first_of(".[:");
@@ -1917,7 +1924,7 @@ static Status ParseEntry(const llvm::StringRef &format_str,
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
- const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ const Definition *entry_def = parent->children + i;
if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
llvm::StringRef value;
if (sep_char)
@@ -1990,16 +1997,15 @@ static Status ParseEntry(const llvm::StringRef &format_str,
return error;
}
-static const FormatEntity::Entry::Definition *
-FindEntry(const llvm::StringRef &format_str,
- const FormatEntity::Entry::Definition *parent,
- llvm::StringRef &remainder) {
+static const Definition *FindEntry(const llvm::StringRef &format_str,
+ const Definition *parent,
+ llvm::StringRef &remainder) {
Status error;
std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
- const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ const Definition *entry_def = parent->children + i;
if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
if (p.second.empty()) {
if (format_str.back() == '.')
@@ -2363,8 +2369,7 @@ static std::string MakeMatch(const llvm::StringRef &prefix,
return match;
}
-static void AddMatches(const FormatEntity::Entry::Definition *def,
- const llvm::StringRef &prefix,
+static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
const llvm::StringRef &match_prefix,
StringList &matches) {
const size_t n = def->num_children;
@@ -2418,8 +2423,7 @@ void FormatEntity::AutoComplete(CompletionRequest &request) {
// We have a partially specified variable, find it
llvm::StringRef remainder;
- const FormatEntity::Entry::Definition *entry_def =
- FindEntry(partial_variable, &g_root, remainder);
+ const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
if (!entry_def)
return;
diff --git a/lldb/unittests/Core/CMakeLists.txt b/lldb/unittests/Core/CMakeLists.txt
index de99856486f1..b524fd4e3647 100644
--- a/lldb/unittests/Core/CMakeLists.txt
+++ b/lldb/unittests/Core/CMakeLists.txt
@@ -1,5 +1,6 @@
add_lldb_unittest(LLDBCoreTests
CommunicationTest.cpp
+ FormatEntityTest.cpp
MangledTest.cpp
ModuleSpecTest.cpp
RichManglingContextTest.cpp
diff --git a/lldb/unittests/Core/FormatEntityTest.cpp b/lldb/unittests/Core/FormatEntityTest.cpp
new file mode 100644
index 000000000000..c22dd4399573
--- /dev/null
+++ b/lldb/unittests/Core/FormatEntityTest.cpp
@@ -0,0 +1,159 @@
+//===-- FormatEntityTest.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/Utility/Status.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+using Definition = FormatEntity::Entry::Definition;
+using Entry = FormatEntity::Entry;
+
+TEST(FormatEntityTest, DefinitionConstructionNameAndType) {
+ Definition d("foo", FormatEntity::Entry::Type::Invalid);
+
+ EXPECT_EQ(d.name, "foo");
+ EXPECT_EQ(d.string, nullptr);
+ EXPECT_EQ(d.type, FormatEntity::Entry::Type::Invalid);
+ EXPECT_EQ(d.data, 0UL);
+ EXPECT_EQ(d.num_children, 0UL);
+ EXPECT_EQ(d.children, nullptr);
+ EXPECT_FALSE(d.keep_separator);
+}
+
+TEST(FormatEntityTest, DefinitionConstructionNameAndString) {
+ Definition d("foo", "string");
+
+ EXPECT_EQ(d.name, "foo");
+ EXPECT_EQ(d.string, "string");
+ EXPECT_EQ(d.type, FormatEntity::Entry::Type::EscapeCode);
+ EXPECT_EQ(d.data, 0UL);
+ EXPECT_EQ(d.num_children, 0UL);
+ EXPECT_EQ(d.children, nullptr);
+ EXPECT_FALSE(d.keep_separator);
+}
+
+TEST(FormatEntityTest, DefinitionConstructionNameTypeData) {
+ Definition d("foo", FormatEntity::Entry::Type::Invalid, 33);
+
+ EXPECT_EQ(d.name, "foo");
+ EXPECT_EQ(d.string, nullptr);
+ EXPECT_EQ(d.type, FormatEntity::Entry::Type::Invalid);
+ EXPECT_EQ(d.data, 33UL);
+ EXPECT_EQ(d.num_children, 0UL);
+ EXPECT_EQ(d.children, nullptr);
+ EXPECT_FALSE(d.keep_separator);
+}
+
+TEST(FormatEntityTest, DefinitionConstructionNameTypeChildren) {
+ Definition d("foo", FormatEntity::Entry::Type::Invalid, 33);
+ Definition parent("parent", FormatEntity::Entry::Type::Invalid, 1, &d);
+ EXPECT_EQ(parent.name, "parent");
+ EXPECT_EQ(parent.string, nullptr);
+ EXPECT_EQ(parent.type, FormatEntity::Entry::Type::Invalid);
+ EXPECT_EQ(parent.num_children, 1UL);
+ EXPECT_EQ(parent.children, &d);
+ EXPECT_FALSE(parent.keep_separator);
+
+ EXPECT_EQ(parent.children[0].name, "foo");
+ EXPECT_EQ(parent.children[0].string, nullptr);
+ EXPECT_EQ(parent.children[0].type, FormatEntity::Entry::Type::Invalid);
+ EXPECT_EQ(parent.children[0].data, 33UL);
+ EXPECT_EQ(parent.children[0].num_children, 0UL);
+ EXPECT_EQ(parent.children[0].children, nullptr);
+ EXPECT_FALSE(d.keep_separator);
+}
+
+constexpr llvm::StringRef lookupStrings[] = {
+ "${addr.load}",
+ "${addr.file}",
+ "${ansi.fg.black}",
+ "${ansi.fg.red}",
+ "${ansi.fg.green}",
+ "${ansi.fg.yellow}",
+ "${ansi.fg.blue}",
+ "${ansi.fg.purple}",
+ "${ansi.fg.cyan}",
+ "${ansi.fg.white}",
+ "${ansi.bg.black}",
+ "${ansi.bg.red}",
+ "${ansi.bg.green}",
+ "${ansi.bg.yellow}",
+ "${ansi.bg.blue}",
+ "${ansi.bg.purple}",
+ "${ansi.bg.cyan}",
+ "${ansi.bg.white}",
+ "${file.basename}",
+ "${file.dirname}",
+ "${file.fullpath}",
+ "${frame.index}",
+ "${frame.pc}",
+ "${frame.fp}",
+ "${frame.sp}",
+ "${frame.flags}",
+ "${frame.no-debug}",
+ "${frame.reg.*}",
+ "${frame.is-artificial}",
+ "${function.id}",
+ "${function.name}",
+ "${function.name-without-args}",
+ "${function.name-with-args}",
+ "${function.mangled-name}",
+ "${function.addr-offset}",
+ "${function.concrete-only-addr-offset-no-padding}",
+ "${function.line-offset}",
+ "${function.pc-offset}",
+ "${function.initial-function}",
+ "${function.changed}",
+ "${function.is-optimized}",
+ "${line.file.basename}",
+ "${line.file.dirname}",
+ "${line.file.fullpath}",
+ "${line.number}",
+ "${line.column}",
+ "${line.start-addr}",
+ "${line.end-addr}",
+ "${module.file.basename}",
+ "${module.file.dirname}",
+ "${module.file.fullpath}",
+ "${process.id}",
+ "${process.name}",
+ "${process.file.basename}",
+ "${process.file.dirname}",
+ "${process.file.fullpath}",
+ "${script.frame}",
+ "${script.process}",
+ "${script.target}",
+ "${script.thread}",
+ "${script.var}",
+ "${script.svar}",
+ "${script.thread}",
+ "${svar.dummy-svar-to-test-wildcard}",
+ "${thread.id}",
+ "${thread.protocol_id}",
+ "${thread.index}",
+ "${thread.info.*}",
+ "${thread.queue}",
+ "${thread.name}",
+ "${thread.stop-reason}",
+ "${thread.stop-reason-raw}",
+ "${thread.return-value}",
+ "${thread.completed-expression}",
+ "${target.arch}",
+ "${var.dummy-var-to-test-wildcard}"};
+
+TEST(FormatEntity, LookupAllEntriesInTree) {
+ for (const llvm::StringRef testString : lookupStrings) {
+ Entry e;
+ EXPECT_TRUE(FormatEntity::Parse(testString, e).Success())
+ << "Formatting " << testString << " did not succeed";
+ }
+}