[lldb] Add a display name to ClangASTContext instances
authorRaphael Isemann <teemperor@gmail.com>
Tue, 21 Jan 2020 11:44:11 +0000 (12:44 +0100)
committerRaphael Isemann <teemperor@gmail.com>
Wed, 22 Jan 2020 07:54:10 +0000 (08:54 +0100)
Summary:
I often struggle to understand what exactly LLDB is doing by looking at our expression evaluation logging as our messages look like this:
```
CompleteTagDecl[2] on (ASTContext*)0x7ff31f01d240 Completing (TagDecl*)0x7ff31f01d568 named DeclName1
```

From the log messages it's unclear what this ASTContext is. Is it the scratch context, the expression context, some decl vendor context or a context from a module?
The pointer value isn't helpful for anyone unless I'm in a debugger where I could inspect the memory at the address. But even with a debugger it's not easy to
figure out what this ASTContext is without having deeper understanding about all the different ASTContext instances in LLDB (e.g., valid SourceLocation
from the file system usually means that this is the Objective-C decl vendor, a file name from multiple expressions is probably the scratch context, etc.).

This patch adds a name field to ClangASTContext instances that we can use to store a name which can be used for logging and debugging. With this
our log messages now look like this:
```
CompleteTagDecl[2] on scratch ASTContext. Completing (TagDecl*)0x7ff31f01d568 named Foo
```
We can now also just print a ClangASTContext from the debugger and see a useful name in the `m_display_name` field, e.g.
```
  m_display_name = "AST for /Users/user/test/main.o";
```

Reviewers: shafik, labath, JDevlieghere, mib

Reviewed By: shafik

Subscribers: clayborg, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D72391

lldb/include/lldb/Symbol/ClangASTContext.h
lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
lldb/source/Symbol/ClangASTContext.cpp
lldb/unittests/Symbol/TestClangASTContext.cpp
lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h

index 338417b..d59fee8 100644 (file)
@@ -57,17 +57,20 @@ public:
 
   /// Constructs a ClangASTContext with an ASTContext using the given triple.
   ///
+  /// \param name The name for the ClangASTContext (for logging purposes)
   /// \param triple The llvm::Triple used for the ASTContext. The triple defines
   ///               certain characteristics of the ASTContext and its types
   ///               (e.g., whether certain primitive types exist or what their
   ///               signedness is).
-  explicit ClangASTContext(llvm::Triple triple);
+  explicit ClangASTContext(llvm::StringRef name, llvm::Triple triple);
 
   /// Constructs a ClangASTContext that uses an existing ASTContext internally.
   /// Useful when having an existing ASTContext created by Clang.
   ///
+  /// \param name The name for the ClangASTContext (for logging purposes)
   /// \param existing_ctxt An existing ASTContext.
-  explicit ClangASTContext(clang::ASTContext &existing_ctxt);
+  explicit ClangASTContext(llvm::StringRef name,
+                           clang::ASTContext &existing_ctxt);
 
   ~ClangASTContext() override;
 
@@ -104,6 +107,10 @@ public:
     return llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get());
   }
 
+  /// Returns the display name of this ClangASTContext that indicates what
+  /// purpose it serves in LLDB. Used for example in logs.
+  llvm::StringRef getDisplayName() const { return m_display_name; }
+
   clang::ASTContext &getASTContext();
 
   clang::MangleContext *getMangleContext();
@@ -947,6 +954,10 @@ private:
   std::unique_ptr<clang::MangleContext> m_mangle_ctx_up;
   uint32_t m_pointer_byte_size = 0;
   bool m_ast_owned = false;
+  /// A string describing what this ClangASTContext represents (e.g.,
+  /// AST for debug information, an expression, some other utility ClangAST).
+  /// Useful for logging and debugging.
+  std::string m_display_name;
 
   typedef llvm::DenseMap<const clang::Decl *, ClangASTMetadata> DeclMetadataMap;
   /// Maps Decls to their associated ClangASTMetadata.
index fed0e6e..d47113b 100644 (file)
@@ -203,8 +203,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
     LLDB_LOG(log,
              "    CompleteTagDecl[{0}] on (ASTContext*){1} Completing "
              "(TagDecl*){2} named {3}",
-             current_id, static_cast<void *>(m_ast_context),
-             static_cast<void *>(tag_decl), tag_decl->getName());
+             current_id, m_clang_ast_context->getDisplayName(), tag_decl,
+             tag_decl->getName());
 
     LLDB_LOG(log, "      CTD[%u] Before:\n{0}", current_id,
              ClangUtil::DumpDecl(tag_decl));
@@ -336,9 +336,10 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
 
   LLDB_LOG(log,
-           "    [CompleteObjCInterfaceDecl] on (ASTContext*){0} Completing "
-           "an ObjCInterfaceDecl named {1}",
-           m_ast_context, interface_decl->getName());
+           "    [CompleteObjCInterfaceDecl] on (ASTContext*){0} '{1}' "
+           "Completing an ObjCInterfaceDecl named {1}",
+           m_ast_context, m_clang_ast_context->getDisplayName(),
+           interface_decl->getName());
   LLDB_LOG(log, "      [COID] Before:\n{0}",
            ClangUtil::DumpDecl(interface_decl));
 
@@ -441,24 +442,25 @@ void ClangASTSource::FindExternalLexicalDecls(
   if (log) {
     if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
       LLDB_LOG(log,
-               "FindExternalLexicalDecls[{0}] on (ASTContext*){1} in '{2}' "
-               "(%sDecl*){3}",
-               current_id, static_cast<void *>(m_ast_context),
+               "FindExternalLexicalDecls[{0}] on (ASTContext*){1} '{2}' in "
+               "'{3}' (%sDecl*){4}",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
                context_named_decl->getNameAsString().c_str(),
                context_decl->getDeclKindName(),
                static_cast<const void *>(context_decl));
     else if (context_decl)
-      LLDB_LOG(
-          log,
-          "FindExternalLexicalDecls[{0}] on (ASTContext*){1} in ({2}Decl*){3}",
-          current_id, static_cast<void *>(m_ast_context),
-          context_decl->getDeclKindName(),
-          static_cast<const void *>(context_decl));
+      LLDB_LOG(log,
+               "FindExternalLexicalDecls[{0}] on (ASTContext*){1} '{2}' in "
+               "({3}Decl*){4}",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+               context_decl->getDeclKindName(),
+               static_cast<const void *>(context_decl));
     else
-      LLDB_LOG(
-          log,
-          "FindExternalLexicalDecls[{0}] on (ASTContext*){1} in a NULL context",
-          current_id, static_cast<const void *>(m_ast_context));
+      LLDB_LOG(log,
+               "FindExternalLexicalDecls[{0}] on (ASTContext*){1} '{2}' in a "
+               "NULL context",
+               current_id, m_ast_context,
+               m_clang_ast_context->getDisplayName());
   }
 
   ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(context_decl);
@@ -466,10 +468,10 @@ void ClangASTSource::FindExternalLexicalDecls(
   if (!original.Valid())
     return;
 
-  LLDB_LOG(
-      log, "  FELD[{0}] Original decl (ASTContext*){1:x} (Decl*){2:x}:\n{3}",
-      current_id, static_cast<void *>(original.ctx),
-      static_cast<void *>(original.decl), ClangUtil::DumpDecl(original.decl));
+  LLDB_LOG(log, "  FELD[{0}] Original decl {1} (Decl*){2:x}:\n{3}", current_id,
+           static_cast<void *>(original.ctx),
+           static_cast<void *>(original.decl),
+           ClangUtil::DumpDecl(original.decl));
 
   if (ObjCInterfaceDecl *original_iface_decl =
           dyn_cast<ObjCInterfaceDecl>(original.decl)) {
@@ -563,20 +565,22 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
     if (!context.m_decl_context)
       LLDB_LOG(log,
                "ClangASTSource::FindExternalVisibleDecls[{0}] on "
-               "(ASTContext*){1} for '{2}' in a NULL DeclContext",
-               current_id, m_ast_context, name);
+               "(ASTContext*){1} '{2}' for '{3}' in a NULL DeclContext",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+               name);
     else if (const NamedDecl *context_named_decl =
                  dyn_cast<NamedDecl>(context.m_decl_context))
       LLDB_LOG(log,
                "ClangASTSource::FindExternalVisibleDecls[{0}] on "
-               "(ASTContext*){1} for '{2}' in '{3}'",
-               current_id, m_ast_context, name, context_named_decl->getName());
+               "(ASTContext*){1} '{2}' for '{3}' in '{4}'",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+               name, context_named_decl->getName());
     else
       LLDB_LOG(log,
                "ClangASTSource::FindExternalVisibleDecls[{0}] on "
-               "(ASTContext*){1} for '{2}' in a '{3}'",
-               current_id, m_ast_context, name,
-               context.m_decl_context->getDeclKindName());
+               "(ASTContext*){1} '{2}' for '{3}' in a '{4}'",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+               name, context.m_decl_context->getDeclKindName());
   }
 
   context.m_namespace_map = std::make_shared<ClangASTImporter::NamespaceMap>();
@@ -1042,9 +1046,10 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
   ConstString selector_name(ss.GetString());
 
   LLDB_LOG(log,
-           "ClangASTSource::FindObjCMethodDecls[{0}] on (ASTContext*){1} "
-           "for selector [{2} {3}]",
-           current_id, m_ast_context, interface_decl->getName(), selector_name);
+           "ClangASTSource::FindObjCMethodDecls[{0}] on (ASTContext*){1} '{2}' "
+           "for selector [{3} {4}]",
+           current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+           interface_decl->getName(), selector_name);
   SymbolContextList sc_list;
 
   const bool include_symbols = false;
@@ -1337,9 +1342,9 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
 
   LLDB_LOG(log,
            "ClangASTSource::FindObjCPropertyAndIvarDecls[{0}] on "
-           "(ASTContext*){1} for '{2}.{3}'",
-           current_id, m_ast_context, parser_iface_decl->getName(),
-           context.m_decl_name.getAsString());
+           "(ASTContext*){1} '{2}' for '{3}.{4}'",
+           current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+           parser_iface_decl->getName(), context.m_decl_name.getAsString());
 
   if (FindObjCPropertyAndIvarDeclsWithOrigin(
           current_id, context, *this, origin_iface_decl))
@@ -1553,9 +1558,10 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size,
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
 
   LLDB_LOG(log,
-           "LayoutRecordType[{0}] on (ASTContext*){1} for (RecordDecl*){2} "
-           "[name = '{3}']",
-           current_id, m_ast_context, record, record->getName());
+           "LayoutRecordType[{0}] on (ASTContext*){1} '{2}' for (RecordDecl*)"
+           "{3} [name = '{4}']",
+           current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+           record, record->getName());
 
   DeclFromParser<const RecordDecl> parser_record(record);
   DeclFromUser<const RecordDecl> origin_record(
@@ -1676,15 +1682,16 @@ void ClangASTSource::CompleteNamespaceMap(
   if (log) {
     if (parent_map && parent_map->size())
       LLDB_LOG(log,
-               "CompleteNamespaceMap[{0}] on (ASTContext*){1} Searching for "
-               "namespace {2} in namespace {3}",
-               current_id, m_ast_context, name,
-               parent_map->begin()->second.GetName());
+               "CompleteNamespaceMap[{0}] on (ASTContext*){1} '{2}' Searching "
+               "for namespace {3} in namespace {4}",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+               name, parent_map->begin()->second.GetName());
     else
       LLDB_LOG(log,
-               "CompleteNamespaceMap[{0}] on (ASTContext*){1} Searching for "
-               "namespace {2}",
-               current_id, m_ast_context, name);
+               "CompleteNamespaceMap[{0}] on (ASTContext*){1} '{2}' Searching "
+               "for namespace {3}",
+               current_id, m_ast_context, m_clang_ast_context->getDisplayName(),
+               name);
   }
 
   if (parent_map) {
index 8dfdd76..92f3b79 100644 (file)
@@ -606,7 +606,8 @@ ClangExpressionParser::ClangExpressionParser(
   m_compiler->createASTContext();
   clang::ASTContext &ast_context = m_compiler->getASTContext();
 
-  m_ast_context.reset(new ClangASTContext(ast_context));
+  m_ast_context.reset(new ClangASTContext(
+      "Expression ASTContext for '" + m_filename + "'", ast_context));
 
   std::string module_name("$__lldb_module");
 
index 40bf740..f394265 100644 (file)
@@ -160,7 +160,9 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
       m_parser(std::move(parser)) {
 
   // Initialize our ClangASTContext.
-  m_ast_context.reset(new ClangASTContext(m_compiler_instance->getASTContext()));
+  m_ast_context.reset(
+      new ClangASTContext("ClangModulesDeclVendor ASTContext",
+                          m_compiler_instance->getASTContext()));
 }
 
 void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
index 7384306..3259dd0 100644 (file)
@@ -143,10 +143,9 @@ private:
 
 AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
     : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime),
-      m_ast_ctx(runtime.GetProcess()
-                    ->GetTarget()
-                    .GetArchitecture()
-                    .GetTriple()),
+      m_ast_ctx(
+          "AppleObjCDeclVendor AST",
+          runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()),
       m_type_realizer_sp(m_runtime.GetEncodingToType()) {
   m_external_source = new AppleObjCExternalASTSource(*this);
   llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
index 66f04be..e12340c 100644 (file)
@@ -23,10 +23,9 @@ AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser(
     ObjCLanguageRuntime &runtime)
     : ObjCLanguageRuntime::EncodingToType(), m_runtime(runtime) {
   if (!m_scratch_ast_ctx_up)
-    m_scratch_ast_ctx_up.reset(new ClangASTContext(runtime.GetProcess()
-                                                       ->GetTarget()
-                                                       .GetArchitecture()
-                                                       .GetTriple()));
+    m_scratch_ast_ctx_up.reset(new ClangASTContext(
+        "AppleObjCTypeEncodingParser ASTContext",
+        runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()));
 }
 
 std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) {
index 6d2bf3a..b286cde 100644 (file)
@@ -499,7 +499,9 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
   Opts.NoInlineDefine = !Opt;
 }
 
-ClangASTContext::ClangASTContext(llvm::Triple target_triple) {
+ClangASTContext::ClangASTContext(llvm::StringRef name,
+                                 llvm::Triple target_triple) {
+  m_display_name = name.str();
   if (!target_triple.str().empty())
     SetTargetTriple(target_triple.str());
   // The caller didn't pass an ASTContext so create a new one for this
@@ -507,7 +509,9 @@ ClangASTContext::ClangASTContext(llvm::Triple target_triple) {
   CreateASTContext();
 }
 
-ClangASTContext::ClangASTContext(ASTContext &existing_ctxt) {
+ClangASTContext::ClangASTContext(llvm::StringRef name,
+                                 ASTContext &existing_ctxt) {
+  m_display_name = name.str();
   SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str());
 
   m_ast_up.reset(&existing_ctxt);
@@ -556,9 +560,11 @@ lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language,
     }
   }
 
-  if (module)
-    return std::make_shared<ClangASTContext>(triple);
-  else if (target && target->IsValid())
+  if (module) {
+    std::string ast_name =
+        "ASTContext for '" + module->GetFileSpec().GetPath() + "'";
+    return std::make_shared<ClangASTContext>(ast_name, triple);
+  } else if (target && target->IsValid())
     return std::make_shared<ClangASTContextForExpressions>(*target, triple);
   return lldb::TypeSystemSP();
 }
@@ -9252,7 +9258,8 @@ ClangASTContext::DeclContextGetClangASTContext(const CompilerDeclContext &dc) {
 
 ClangASTContextForExpressions::ClangASTContextForExpressions(
     Target &target, llvm::Triple triple)
-    : ClangASTContext(triple), m_target_wp(target.shared_from_this()),
+    : ClangASTContext("scratch ASTContext", triple),
+      m_target_wp(target.shared_from_this()),
       m_persistent_variables(new ClangPersistentVariables) {
   m_scratch_ast_source_up.reset(new ClangASTSource(
       target.shared_from_this(), target.GetClangASTImporter()));
index 653c9ce..1d9277d 100644 (file)
@@ -26,7 +26,8 @@ public:
   SubsystemRAII<FileSystem, HostInfo> subsystems;
 
   void SetUp() override {
-    m_ast.reset(new ClangASTContext(HostInfo::GetTargetTriple()));
+    m_ast.reset(
+        new ClangASTContext("test ASTContext", HostInfo::GetTargetTriple()));
   }
 
   void TearDown() override { m_ast.reset(); }
@@ -220,6 +221,16 @@ TEST_F(TestClangASTContext, TestBuiltinTypeForEncodingAndBitSize) {
   VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);
 }
 
+TEST_F(TestClangASTContext, TestDisplayName) {
+  ClangASTContext ast("some name", llvm::Triple());
+  EXPECT_EQ("some name", ast.getDisplayName());
+}
+
+TEST_F(TestClangASTContext, TestDisplayNameEmpty) {
+  ClangASTContext ast("", llvm::Triple());
+  EXPECT_EQ("", ast.getDisplayName());
+}
+
 TEST_F(TestClangASTContext, TestIsClangType) {
   clang::ASTContext &context = m_ast->getASTContext();
   lldb::opaque_compiler_type_t bool_ctype =
index 8f0368d..b681ae8 100644 (file)
@@ -39,7 +39,7 @@ public:
 // defining here, causing this test to fail, feel free to delete it.
 TEST_F(DWARFASTParserClangTests,
        EnsureAllDIEsInDeclContextHaveBeenParsedParsesOnlyMatchingEntries) {
-  ClangASTContext ast_ctx(HostInfoBase::GetTargetTriple());
+  ClangASTContext ast_ctx("dummy ASTContext", HostInfoBase::GetTargetTriple());
   DWARFASTParserClangStub ast_parser(ast_ctx);
 
   DWARFUnit *unit = nullptr;
index 2c94aa5..5523b6f 100644 (file)
@@ -22,7 +22,8 @@ inline clang::DeclarationName getDeclarationName(ClangASTContext &ast,
 }
 
 inline std::unique_ptr<ClangASTContext> createAST() {
-  return std::make_unique<ClangASTContext>(HostInfo::GetTargetTriple());
+  return std::make_unique<ClangASTContext>("test ASTContext",
+                                           HostInfo::GetTargetTriple());
 }
 
 inline CompilerType createRecord(ClangASTContext &ast, llvm::StringRef name) {