<div dir="ltr">I see there's SBType, does this represent something different?  I was thinking you could make a method like <div><br></div><div>SBType *</div><div>SBTarget::LookupType(const char* type_name, eLanguage lang);</div><div><br></div><div>Even if it didn't support every possible usage of the "type lookup" command, it would be a start.</div><div><br></div><div>At one point on the list it was discussed whether tests which use runCmd and then matching the output should be separated from the rest of the test suite, so there's a more clearly enforced distinction about which tests use the command API and which tests use the python API.  At least Jim thought that was a good idea and supported the move, but nobody else really chimed in.  If you agree, maybe you could be the first?  :)  Something like lldb/test/commands/type-lookup.  Eventually the goal would just be to have 3 top level directories, </div><div><br></div><div>lldb</div><div>|__test</div><div>    |__commands</div><div>    |__python-api</div><div>    |__unit-tests</div><div><br></div><div>With the existing sub-trees divided up accordingly between the 3.   (This is all assuming of course that making the SBTarget::LookupType method I suggested earlier doesn't work for some reason)</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Oct 1, 2015 at 1:01 PM Enrico Granata <<a href="mailto:egranata@apple.com">egranata@apple.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Oct 1, 2015, at 12:49 PM, Zachary Turner <<a href="mailto:zturner@google.com" target="_blank">zturner@google.com</a>> wrote:</div><br><div><div dir="ltr">Hi Enrico,<div><br></div><div>Could you add some tests for this?</div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Sure. I am still churning through a thing or two before declaring victory, but I can add tests as I make progress</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div dir="ltr"><div>  python API tests and appropriate methods added to SBTarget</div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>There currently is no SB API component to this. It is a purely command-line facility.</div><div>If you feel it would be useful to have SB API for this, it will need to be designed (e.g. “type lookup” is allowed to transact in things that are not strictly speaking compiler types - we have no API way to represent this kind of concept)</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div dir="ltr"><div> would be ideal.</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Oct 1, 2015 at 11:17 AM Enrico Granata via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: enrico<br>
Date: Thu Oct  1 13:16:18 2015<br>
New Revision: 249047<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=249047&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=249047&view=rev</a><br>
Log:<br>
Add a 'type lookup' command. This command is meant to look up type information by name in a language-specific way.<br>
<br>
Currently, it only supports Objective-C - C++ types can be looked up through debug info via 'image lookup -t', whereas ObjC types via this command are looked up by runtime introspection<br>
<br>
This behavior is in line with type lookup's behavior in Xcode 7, but I am definitely open to feedback as to what makes the most sense here<br>
<br>
<br>
Modified:<br>
    lldb/trunk/include/lldb/Target/Language.h<br>
    lldb/trunk/source/Commands/CommandObjectType.cpp<br>
    lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp<br>
    lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h<br>
    lldb/trunk/source/Target/Language.cpp<br>
<br>
Modified: lldb/trunk/include/lldb/Target/Language.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Language.h?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Language.h?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Target/Language.h (original)<br>
+++ lldb/trunk/include/lldb/Target/Language.h Thu Oct  1 13:16:18 2015<br>
@@ -13,6 +13,8 @@<br>
 // C Includes<br>
 // C++ Includes<br>
 #include <functional><br>
+#include <memory><br>
+#include <set><br>
 #include <vector><br>
<br>
 // Other libraries and framework includes<br>
@@ -29,6 +31,42 @@ class Language :<br>
 public PluginInterface<br>
 {<br>
 public:<br>
+<br>
+    class TypeScavenger<br>
+    {<br>
+    public:<br>
+        class Result<br>
+        {<br>
+        public:<br>
+            virtual bool<br>
+            IsValid () = 0;<br>
+<br>
+            virtual bool<br>
+            DumpToStream (Stream& stream,<br>
+                          bool print_help_if_available) = 0;<br>
+<br>
+            virtual ~Result() = default;<br>
+        };<br>
+<br>
+        typedef std::set<std::unique_ptr<Result>> ResultSet;<br>
+<br>
+        virtual ~TypeScavenger () = default;<br>
+<br>
+        size_t<br>
+        Find (ExecutionContextScope *exe_scope,<br>
+              const char *key,<br>
+              ResultSet &results,<br>
+              bool append = true);<br>
+<br>
+    protected:<br>
+        TypeScavenger () = default;<br>
+<br>
+        virtual bool<br>
+        Find_Impl (ExecutionContextScope *exe_scope,<br>
+                   const char *key,<br>
+                   ResultSet &results) = 0;<br>
+    };<br>
+<br>
     ~Language() override;<br>
<br>
     static Language*<br>
@@ -65,6 +103,9 @@ public:<br>
     virtual lldb_private::formatters::StringPrinter::EscapingHelper<br>
     GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType);<br>
<br>
+    virtual std::unique_ptr<TypeScavenger><br>
+    GetTypeScavenger ();<br>
+<br>
     // These are accessors for general information about the Languages lldb knows about:<br>
<br>
     static lldb::LanguageType<br>
@@ -91,7 +132,6 @@ public:<br>
<br>
     static bool<br>
     LanguageIsPascal (lldb::LanguageType language);<br>
-<br>
<br>
 protected:<br>
     //------------------------------------------------------------------<br>
<br>
Modified: lldb/trunk/source/Commands/CommandObjectType.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Commands/CommandObjectType.cpp (original)<br>
+++ lldb/trunk/source/Commands/CommandObjectType.cpp Thu Oct  1 13:16:18 2015<br>
@@ -4558,6 +4558,218 @@ CommandObjectTypeFilterAdd::CommandOptio<br>
     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }<br>
 };<br>
<br>
+//----------------------------------------------------------------------<br>
+// "type lookup"<br>
+//----------------------------------------------------------------------<br>
+class CommandObjectTypeLookup : public CommandObjectRaw<br>
+{<br>
+protected:<br>
+<br>
+    class CommandOptions : public OptionGroup<br>
+    {<br>
+    public:<br>
+<br>
+        CommandOptions () :<br>
+        OptionGroup(),<br>
+        m_show_help(false),<br>
+        m_language(eLanguageTypeUnknown)<br>
+        {}<br>
+<br>
+        virtual<br>
+        ~CommandOptions () {}<br>
+<br>
+        virtual uint32_t<br>
+        GetNumDefinitions ()<br>
+        {<br>
+            return 3;<br>
+        }<br>
+<br>
+        virtual const OptionDefinition*<br>
+        GetDefinitions ()<br>
+        {<br>
+            return g_option_table;<br>
+        }<br>
+<br>
+        virtual Error<br>
+        SetOptionValue (CommandInterpreter &interpreter,<br>
+                        uint32_t option_idx,<br>
+                        const char *option_value)<br>
+        {<br>
+            Error error;<br>
+<br>
+            const int short_option = g_option_table[option_idx].short_option;<br>
+<br>
+            switch (short_option)<br>
+            {<br>
+                case 'h':<br>
+                    m_show_help = true;<br>
+                    break;<br>
+<br>
+                case 'l':<br>
+                    m_language = Language::GetLanguageTypeFromString(option_value);<br>
+                    break;<br>
+<br>
+                default:<br>
+                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);<br>
+                    break;<br>
+            }<br>
+<br>
+            return error;<br>
+        }<br>
+<br>
+        virtual void<br>
+        OptionParsingStarting (CommandInterpreter &interpreter)<br>
+        {<br>
+            m_show_help = false;<br>
+            m_language = eLanguageTypeUnknown;<br>
+        }<br>
+<br>
+        // Options table: Required for subclasses of Options.<br>
+<br>
+        static OptionDefinition g_option_table[];<br>
+        bool m_show_help;<br>
+        lldb::LanguageType m_language;<br>
+    };<br>
+<br>
+    OptionGroupOptions m_option_group;<br>
+    CommandOptions m_command_options;<br>
+<br>
+public:<br>
+<br>
+    CommandObjectTypeLookup (CommandInterpreter &interpreter) :<br>
+    CommandObjectRaw (interpreter,<br>
+                      "type lookup",<br>
+                      "Lookup a type by name in the select target.",<br>
+                      "type lookup <typename>",<br>
+                      eCommandRequiresTarget),<br>
+    m_option_group(interpreter),<br>
+    m_command_options()<br>
+    {<br>
+        m_option_group.Append(&m_command_options);<br>
+        m_option_group.Finalize();<br>
+    }<br>
+<br>
+    virtual<br>
+    ~CommandObjectTypeLookup ()<br>
+    {<br>
+    }<br>
+<br>
+    virtual<br>
+    Options *<br>
+    GetOptions ()<br>
+    {<br>
+        return &m_option_group;<br>
+    }<br>
+<br>
+    virtual bool<br>
+    DoExecute (const char *raw_command_line, CommandReturnObject &result)<br>
+    {<br>
+        if (!raw_command_line || !raw_command_line[0])<br>
+        {<br>
+            result.SetError("type lookup cannot be invoked without a type name as argument");<br>
+            return false;<br>
+        }<br>
+<br>
+        m_option_group.NotifyOptionParsingStarting();<br>
+<br>
+        const char * name_of_type = NULL;<br>
+<br>
+        if (raw_command_line[0] == '-')<br>
+        {<br>
+            // We have some options and these options MUST end with --.<br>
+            const char *end_options = NULL;<br>
+            const char *s = raw_command_line;<br>
+            while (s && s[0])<br>
+            {<br>
+                end_options = ::strstr (s, "--");<br>
+                if (end_options)<br>
+                {<br>
+                    end_options += 2; // Get past the "--"<br>
+                    if (::isspace (end_options[0]))<br>
+                    {<br>
+                        name_of_type = end_options;<br>
+                        while (::isspace (*name_of_type))<br>
+                            ++name_of_type;<br>
+                        break;<br>
+                    }<br>
+                }<br>
+                s = end_options;<br>
+            }<br>
+<br>
+            if (end_options)<br>
+            {<br>
+                Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));<br>
+                if (!ParseOptions (args, result))<br>
+                    return false;<br>
+<br>
+                Error error (m_option_group.NotifyOptionParsingFinished());<br>
+                if (error.Fail())<br>
+                {<br>
+                    result.AppendError (error.AsCString());<br>
+                    result.SetStatus (eReturnStatusFailed);<br>
+                    return false;<br>
+                }<br>
+            }<br>
+        }<br>
+        if (nullptr == name_of_type)<br>
+            name_of_type = raw_command_line;<br>
+<br>
+        TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());<br>
+        const bool fill_all_in = true;<br>
+        ExecutionContext exe_ctx(target_sp.get(), fill_all_in);<br>
+        ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();<br>
+<br>
+        bool any_found = false;<br>
+<br>
+        std::vector<Language*> languages;<br>
+<br>
+        if (m_command_options.m_language == eLanguageTypeUnknown)<br>
+        {<br>
+            // FIXME: hardcoding languages is not good<br>
+            languages.push_back(Language::FindPlugin(eLanguageTypeObjC));<br>
+            languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));<br>
+        }<br>
+        else<br>
+        {<br>
+            languages.push_back(Language::FindPlugin(m_command_options.m_language));<br>
+        }<br>
+<br>
+        for (Language* language : languages)<br>
+        {<br>
+            if (!language)<br>
+                continue;<br>
+<br>
+            if (auto scavenger = language->GetTypeScavenger())<br>
+            {<br>
+                Language::TypeScavenger::ResultSet search_results;<br>
+                if (scavenger->Find(best_scope, name_of_type, search_results) > 0)<br>
+                {<br>
+                    for (const auto& search_result : search_results)<br>
+                    {<br>
+                        if (search_result && search_result->IsValid())<br>
+                        {<br>
+                            any_found = true;<br>
+                            search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help);<br>
+                        }<br>
+                    }<br>
+                }<br>
+            }<br>
+        }<br>
+<br>
+        result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult);<br>
+        return true;<br>
+    }<br>
+<br>
+};<br>
+<br>
+OptionDefinition<br>
+CommandObjectTypeLookup::CommandOptions::g_option_table[] =<br>
+{<br>
+    { LLDB_OPT_SET_ALL, false, "show-help",        'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,    "Display available help for types"},<br>
+    { LLDB_OPT_SET_ALL, false, "language",         'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,    "Which language's types should the search scope be"},<br>
+    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }<br>
+};<br>
+<br>
 template <typename FormatterType><br>
 class CommandObjectFormatterInfo : public CommandObjectRaw<br>
 {<br>
@@ -4778,6 +4990,7 @@ CommandObjectType::CommandObjectType (Co<br>
 #ifndef LLDB_DISABLE_PYTHON<br>
     LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));<br>
 #endif<br>
+    LoadSubCommand ("lookup",   CommandObjectSP (new CommandObjectTypeLookup (interpreter)));<br>
 }<br>
<br>
<br>
<br>
Modified: lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp (original)<br>
+++ lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp Thu Oct  1 13:16:18 2015<br>
@@ -656,3 +656,91 @@ ObjCLanguage::GetPossibleFormattersMatch<br>
<br>
     return result;<br>
 }<br>
+<br>
+std::unique_ptr<Language::TypeScavenger><br>
+ObjCLanguage::GetTypeScavenger ()<br>
+{<br>
+    class ObjCTypeScavenger : public Language::TypeScavenger<br>
+    {<br>
+    private:<br>
+        class ObjCScavengerResult : public Language::TypeScavenger::Result<br>
+        {<br>
+        public:<br>
+            ObjCScavengerResult (CompilerType type) :<br>
+                Language::TypeScavenger::Result(),<br>
+                m_compiler_type(type)<br>
+            {<br>
+            }<br>
+<br>
+            bool<br>
+            IsValid () override<br>
+            {<br>
+                return m_compiler_type.IsValid();<br>
+            }<br>
+<br>
+            bool<br>
+            DumpToStream (Stream& stream,<br>
+                          bool print_help_if_available) override<br>
+            {<br>
+                if (IsValid())<br>
+                {<br>
+                    m_compiler_type.DumpTypeDescription(&stream);<br>
+                    stream.EOL();<br>
+                    return true;<br>
+                }<br>
+                return false;<br>
+            }<br>
+<br>
+            virtual ~ObjCScavengerResult() = default;<br>
+        private:<br>
+            CompilerType m_compiler_type;<br>
+        };<br>
+<br>
+    protected:<br>
+        ObjCTypeScavenger() = default;<br>
+<br>
+        virtual ~ObjCTypeScavenger() = default;<br>
+<br>
+        bool<br>
+        Find_Impl (ExecutionContextScope *exe_scope,<br>
+                   const char *key,<br>
+                   ResultSet &results) override<br>
+        {<br>
+            bool result = false;<br>
+<br>
+            Process* process = exe_scope->CalculateProcess().get();<br>
+            if (process)<br>
+            {<br>
+                const bool create_on_demand = false;<br>
+                auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);<br>
+                if (objc_runtime)<br>
+                {<br>
+                    auto decl_vendor = objc_runtime->GetDeclVendor();<br>
+                    if (decl_vendor)<br>
+                    {<br>
+                        std::vector<clang::NamedDecl *> decls;<br>
+                        ConstString name(key);<br>
+                        decl_vendor->FindDecls(name, true, UINT32_MAX, decls);<br>
+                        for (auto decl : decls)<br>
+                        {<br>
+                            if (decl)<br>
+                            {<br>
+                                if (CompilerType candidate = ClangASTContext::GetTypeForDecl(decl))<br>
+                                {<br>
+                                    result = true;<br>
+                                    std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(candidate));<br>
+                                    results.insert(std::move(result));<br>
+                                }<br>
+                            }<br>
+                        }<br>
+                    }<br>
+                }<br>
+            }<br>
+            return result;<br>
+        }<br>
+<br>
+        friend class ObjCLanguage;<br>
+    };<br>
+<br>
+    return std::unique_ptr<TypeScavenger>(new ObjCTypeScavenger());<br>
+}<br>
<br>
Modified: lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h (original)<br>
+++ lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h Thu Oct  1 13:16:18 2015<br>
@@ -146,6 +146,9 @@ public:<br>
     std::vector<ConstString><br>
     GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;<br>
<br>
+    std::unique_ptr<TypeScavenger><br>
+    GetTypeScavenger () override;<br>
+<br>
     //------------------------------------------------------------------<br>
     // Static Functions<br>
     //------------------------------------------------------------------<br>
<br>
Modified: lldb/trunk/source/Target/Language.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Language.cpp?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Language.cpp?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Target/Language.cpp (original)<br>
+++ lldb/trunk/source/Target/Language.cpp Thu Oct  1 13:16:18 2015<br>
@@ -287,6 +287,34 @@ Language::LanguageIsPascal (LanguageType<br>
     }<br>
 }<br>
<br>
+std::unique_ptr<Language::TypeScavenger><br>
+Language::GetTypeScavenger ()<br>
+{<br>
+    return nullptr;<br>
+}<br>
+<br>
+size_t<br>
+Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,<br>
+                               const char *key,<br>
+                               ResultSet &results,<br>
+                               bool append)<br>
+{<br>
+    if (!exe_scope || !exe_scope->CalculateTarget().get())<br>
+        return false;<br>
+<br>
+    if (!key || !key[0])<br>
+        return false;<br>
+<br>
+    if (!append)<br>
+        results.clear();<br>
+<br>
+    size_t old_size = results.size();<br>
+<br>
+    if (this->Find_Impl(exe_scope, key, results))<br>
+        return results.size() - old_size;<br>
+    return 0;<br>
+}<br>
+<br>
 //----------------------------------------------------------------------<br>
 // Constructor<br>
 //----------------------------------------------------------------------<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits</a><br>
</blockquote></div>
</div></blockquote></div></div><div style="word-wrap:break-word"><div></div><br><div>
<div style="color:rgb(0,0,0);font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br>Thanks,</div><div style="color:rgb(0,0,0);font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><i>- Enrico</i><br>📩 egranata@<font color="#ff2600"></font>.com ☎️ 27683</div>
</div>
<br></div></blockquote></div>