<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I have identified an issue in the expression parse. If you compile this code:<div class=""><br class=""></div><div class="">struct Foo { typedef unsigned node; };<br class="">struct Bar { typedef int node; };<br class="">int main(int argc, const char **argv) {<br class="">    Foo::node foo_carp = 22;<br class="">    Bar::node bar_node = 33;<br class="">    return 0;<br class="">}<br class=""><br class=""></div><div class=""><br class=""></div><div class="">Then then do:</div><div class=""><br class=""></div><div class="">(lldb) file a.out</div><div class="">(lldb) b main</div><div class="">(lldb) run</div><div class="">(lldb) <span style="font-size: 11px;" class="">p (node *)&bar_node</span></div><div class=""><span style="font-size: 11px;" class=""><br class=""></span></div><div class=""><span style="font-size: 11px;" class="">This should fail because there is no "node" type in the global namespace. But we don't fail, we pick the first type whose base name matches "node" and return it and start using it regardless of where the type is located decl context wise... </span></div><div class=""><span style="font-size: 11px;" class=""><br class=""></span></div><div class=""><span style="font-size: 11px;" class="">The issue happens when we call:</span></div><div class=""><span style="font-size: 11px;" class=""><br class=""></span></div><div class=""><span style="font-size: 11px;" class="">void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context, lldb::ModuleSP module_sp, CompilerDeclContext &namespace_decl, unsigned int current_id);<br class=""></span></div><div class=""><span style="font-size: 11px;" class=""><br class=""></span></div><div class=""><span style="font-size: 11px;" class="">In this code we end up doing:</span></div><div class=""><span style="font-size: 11px;" class=""><br class=""></span></div><div class=""><span style="font-size: 11px;" class="">    TypeList types;<br class="">    SymbolContext null_sc;<br class="">    const bool exact_match = false;<br class="">    llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;<br class="">    if (module_sp && namespace_decl)<br class="">      module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);<br class="">    else<br class="">      m_target->GetImages().FindTypes(null_sc, name, exact_match, 1,<br class="">                                      searched_symbol_files, types);<br class=""><br class="">    if (size_t num_types = types.GetSize()) {<br class="">      for (size_t ti = 0; ti < num_types; ++ti) {<br class=""></span><br class=""></div><div class="">So if we don't have a valid namespace_decl, which will be the case when we are searching at the translation unit level, we end up searching the target for the first match for the type whose _basename_ matches "name" regardless if of the module we are currently running the expression in, and regardless of the translation unit decl context being a requirement. So we find any type whose basename matches "name" from _any_ decl context. That is really bad!</div><div class=""><br class=""></div><div class="">A few things wrong here:</div><div class="">1 - we seem to assume if we have a namespace (which is a parameter whose type is CompilerDeclContext &), that it must go with the module_sp. Why? Because a CompilerDeclContext has a "TypeSystem *" inside of it, and each module has a their own "TypeSystem *" for a give language. We then call module_sp->FindTypesInNamespace(...) with the CompilerDeclContext * to namespace_decl. This eventually makes its way down to SymbolFileDWARF::FindTypes(...) which will do the check:</div><div class=""><br class=""></div><div class="">  if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))<br class="">    return 0;<br class=""><br class="">So if the CompilerDeclContext's type system doesn't match the type system of the DWARF file that is makes it into, it will ignore the search entirely. This means if we have a namespace from an expression like "p std::foo", and we find the namespace "foo" in one module, we will only search a specific module for "foo" within "std", even though another module could contain "std::foo". So if the first module that has debug info for namespace "std" doesn't contain "foo", we don't find the type?</div><div class=""><br class=""></div><div class="">2 - If we don't have a namespace, we want things only at the translation unit level, yet we search all modules in the target in the target image list order. It seems we should be checking by starting with the current module, then expanding to any module except the current module if the type lookup fails in the current module. Then we need to search for more than 1 type so we can weed any results out that don't have a decl context of a translation unit level or anonymous namespace from the current translation unit. </div><div class=""><br class=""></div><div class="">So to fix this I might propose the following:</div><div class=""><br class=""></div><div class="">Modify all "FindTypes()" functions to take a new version of something like the <span style="background-color: rgb(255, 255, 255);" class=""><span style="font-size: 11px;" class="">DWARFDeclContext from DWARFDeclContext.h. This is an object that contains a enumeration for the decl context type plus an optional name . This think things like "translation unit with name 'main.c'", class with name "Foo", namespace with  name "std", function with name "erase". This new item could be something like:</span></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><span style="font-size: 11px;" class=""><br class=""></span></span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">class DeclContextMatch {</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">  enum class Kind {</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    TranslationUnit,</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    Namespace,</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    Class,</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    Struct,</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    Union,</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    Function</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">  };</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">  struct Entry {</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    Kind kind;</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">    ConstString name;</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">  };</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">  std::vector<Entry> m_entries;</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">  void Append(</span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch::Kind k, const char *name = nullptr);</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">};</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">We would stop passing the "</span><span style="font-size: 11px;" class="">const CompilerDeclContext *parent_decl_ctx" to the ::FindTypes(...) calls and instead pass a "</span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch *"</span><span style="background-color: rgb(255, 255, 255);" class=""><span style="font-size: 11px;" class=""> so that clients can easily weed out things that don't match in an abstract way that doesn't tie the containing decl context to the current module. So if I was doing to search for "node" at the translation unit level, I would fill in:</span></span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch dcm;</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">dcm.Append(</span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch::Kind::</span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">TranslationUnit);</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">target->GetImages.FindTypes(null_sc, name, &</span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">dcm, ...)</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><br class=""></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">Since the </span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch isn't specific to any module (unlike </span>CompilerDeclContext instances which are), the search can happen and each SymbolFile subclass can search how ever they need to by only returning matches that match the <span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch if one is given. If no </span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch is supplied, then we search for any type whose basename matches the name requested. If </span><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">DeclContextMatch is given, only matching types are returned.</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><span style="font-size: 11px;" class="">This has to be causing all sorts of problems in our expressions, so we really need to fix this ASAP. Comments and suggestions are welcome.</span></span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class="">Greg</span></div><div class=""><span style="font-size: 11px; background-color: rgb(255, 255, 255);" class=""><br class=""></span></div></body></html>