teemperor created this revision.
teemperor added reviewers: labath, shafik, aprantl.
Herald added subscribers: lldb-commits, JDevlieghere.
Herald added a project: LLDB.
teemperor added a comment.
teemperor edited the summary of this revision.

(I'm aware that a lot of the touched code here could be improved, but I would 
prefer that I at least can trust my compiler before I refactor the remaining 
Metadata stuff...)


LLDB associates additional information with Types and Declarations which it 
calls ClangASTMetadata.
ClangASTMetadata is stored by the ClangASTSourceCommon which is implemented by 
having a large map of
`void *` keys to associated `ClangASTMetadata` values. To make this whole 
mechanism even unsafer
we also decided to use `clang::Decl *` as one of pointers we throw in there 
(beside `clang::Type *`).

The Decl class hierarchy uses multiple inheritance which means that not all 
pointers have the
same address when they are implicitly converted to pointers of their parent 
classes. For example
`clang::Decl *` and `clang::DeclContext *` won't end up being the same address 
when they
are implicitly converted from one of the many Decl-subclasses that inherit from 
both.

As we use the addresses as the keys in our Metadata map, this means that any 
implicit type
conversions to parent classes (or anything else that changes the addresses) 
will break our metadata tracking
in obscure ways.

Just to illustrate how broken this whole mechanism currently is:

  // m_ast is our ClangASTContext. Let's double check that from 
GetTranslationUnitDecl
  // in ClangASTContext and ASTContext return the same thing (one method just 
calls the other).
  assert(m_ast->GetTranslationUnitDecl() == 
m_ast->getASTContext()->getTranslationUnitDecl());
  // Ok, both methods have the same TU*. Let's store metadata with the result 
of one method call.
  m_ast->SetMetadataAsUserID(m_ast->GetTranslationUnitDecl(), 1234U);
  // Retrieve the same Metadata for the TU by using the TU* from the other 
method... which fails?
  
EXPECT_EQ(m_ast->GetMetadata(m_ast->getASTContext()->getTranslationUnitDecl())->GetUserID(),
 1234U);
  // Turns out that getTranslationUnitDecl one time returns a 
TranslationUnitDecl* but the other time
  // we return one of the parent classes of TranslationUnitDecl (DeclContext).

This patch splits up the `void *` API into two where one does the `clang::Type 
*` tracking and one the `clang::Decl *` mapping.
Type and Decl are disjoint class hierarchies so there is no implicit conversion 
possible that could influence
the address values.

I had to change the storing of `clang::QualType` opaque pointers to their 
`clang::Type *` equivalents as
opaque pointers are already `void *` pointers to begin with. We don't seem to 
ever set any qualifier in any of these
QualTypes to this conversion should be NFC.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D71409

Files:
  lldb/include/lldb/Symbol/ClangASTContext.h
  lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/source/Symbol/ClangASTContext.cpp
  lldb/source/Symbol/ClangExternalASTSourceCommon.cpp

Index: lldb/source/Symbol/ClangExternalASTSourceCommon.cpp
===================================================================
--- lldb/source/Symbol/ClangExternalASTSourceCommon.cpp
+++ lldb/source/Symbol/ClangExternalASTSourceCommon.cpp
@@ -52,17 +52,19 @@
 }
 
 ClangASTMetadata *
-ClangExternalASTSourceCommon::GetMetadata(const void *object) {
-  auto It = m_metadata.find(object);
-  if (It != m_metadata.end())
+ClangExternalASTSourceCommon::GetMetadata(const clang::Decl *object) {
+  auto It = m_decl_metadata.find(object);
+  if (It != m_decl_metadata.end())
     return &It->second;
-  else
-    return nullptr;
+  return nullptr;
 }
 
-void ClangExternalASTSourceCommon::SetMetadata(const void *object,
-                                               ClangASTMetadata &metadata) {
-  m_metadata[object] = metadata;
+ClangASTMetadata *
+ClangExternalASTSourceCommon::GetMetadata(const clang::Type *object) {
+  auto It = m_type_metadata.find(object);
+  if (It != m_type_metadata.end())
+    return &It->second;
+  return nullptr;
 }
 
 void ClangASTMetadata::Dump(Stream *s) {
Index: lldb/source/Symbol/ClangASTContext.cpp
===================================================================
--- lldb/source/Symbol/ClangASTContext.cpp
+++ lldb/source/Symbol/ClangASTContext.cpp
@@ -2398,14 +2398,31 @@
   }
 }
 
-void ClangASTContext::SetMetadataAsUserID(const void *object,
+void ClangASTContext::SetMetadataAsUserID(const clang::Decl *decl,
                                           user_id_t user_id) {
   ClangASTMetadata meta_data;
   meta_data.SetUserID(user_id);
-  SetMetadata(object, meta_data);
+  SetMetadata(decl, meta_data);
 }
 
-void ClangASTContext::SetMetadata(const void *object,
+void ClangASTContext::SetMetadataAsUserID(const clang::Type *type,
+                                          user_id_t user_id) {
+  ClangASTMetadata meta_data;
+  meta_data.SetUserID(user_id);
+  SetMetadata(type, meta_data);
+}
+
+void ClangASTContext::SetMetadata(const clang::Decl *object,
+                                  ClangASTMetadata &metadata) {
+  ClangExternalASTSourceCommon *external_source =
+      ClangExternalASTSourceCommon::Lookup(
+          getASTContext()->getExternalSource());
+
+  if (external_source)
+    external_source->SetMetadata(object, metadata);
+}
+
+void ClangASTContext::SetMetadata(const clang::Type *object,
                                   ClangASTMetadata &metadata) {
   ClangExternalASTSourceCommon *external_source =
       ClangExternalASTSourceCommon::Lookup(
@@ -2416,14 +2433,23 @@
 }
 
 ClangASTMetadata *ClangASTContext::GetMetadata(clang::ASTContext *ast,
-                                               const void *object) {
+                                               const clang::Decl *object) {
   ClangExternalASTSourceCommon *external_source =
       ClangExternalASTSourceCommon::Lookup(ast->getExternalSource());
 
   if (external_source)
     return external_source->GetMetadata(object);
-  else
-    return nullptr;
+  return nullptr;
+}
+
+ClangASTMetadata *ClangASTContext::GetMetadata(clang::ASTContext *ast,
+                                               const clang::Type *object) {
+  ClangExternalASTSourceCommon *external_source =
+      ClangExternalASTSourceCommon::Lookup(ast->getExternalSource());
+
+  if (external_source)
+    return external_source->GetMetadata(object);
+  return nullptr;
 }
 
 bool ClangASTContext::SetTagTypeKind(clang::QualType tag_qual_type,
@@ -5101,7 +5127,7 @@
                     clang::QualType qual_type,
                     const ExecutionContext *exe_ctx) {
   if (qual_type->isIncompleteArrayType())
-    if (auto *metadata = ast.GetMetadata(qual_type.getAsOpaquePtr()))
+    if (auto *metadata = ast.GetMetadata(qual_type.getTypePtr()))
       return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(),
                                                  exe_ctx);
   return llvm::None;
@@ -8860,8 +8886,11 @@
 void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
   StreamFile s(stdout, false);
   DumpTypeDescription(type, &s);
+
+  CompilerType ct(this, type);
+  const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr();
   ClangASTMetadata *metadata =
-      ClangASTContext::GetMetadata(getASTContext(), type);
+      ClangASTContext::GetMetadata(getASTContext(), clang_type);
   if (metadata) {
     metadata->Dump(&s);
   }
@@ -9489,7 +9518,7 @@
 
 ClangASTMetadata *
 ClangASTContext::DeclContextGetMetaData(const CompilerDeclContext &dc,
-                                        const void *object) {
+                                        const Decl *object) {
   clang::ASTContext *ast = DeclContextGetClangASTContext(dc);
   if (ast)
     return ClangASTContext::GetMetadata(ast, object);
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -1336,7 +1336,8 @@
       dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl, clang_type,
       Type::ResolveState::Full);
   type_sp->SetEncodingType(element_type);
-  m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID());
+  const clang::Type *type = ClangUtil::GetQualType(clang_type).getTypePtr();
+  m_ast.SetMetadataAsUserID(type, die.GetID());
   return type_sp;
 }
 
Index: lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
===================================================================
--- lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
+++ lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
@@ -126,15 +126,26 @@
   ClangExternalASTSourceCommon();
   ~ClangExternalASTSourceCommon() override;
 
-  ClangASTMetadata *GetMetadata(const void *object);
-  void SetMetadata(const void *object, ClangASTMetadata &metadata);
+  ClangASTMetadata *GetMetadata(const clang::Decl *object);
+  void SetMetadata(const clang::Decl *object,
+                   const ClangASTMetadata &metadata) {
+    m_decl_metadata[object] = metadata;
+  }
+
+  ClangASTMetadata *GetMetadata(const clang::Type *object);
+  void SetMetadata(const clang::Type *object,
+                   const ClangASTMetadata &metadata) {
+    m_type_metadata[object] = metadata;
+  }
 
   static ClangExternalASTSourceCommon *Lookup(clang::ExternalASTSource *source);
 
 private:
-  typedef llvm::DenseMap<const void *, ClangASTMetadata> MetadataMap;
+  typedef llvm::DenseMap<const clang::Decl *, ClangASTMetadata> DeclMetadataMap;
+  typedef llvm::DenseMap<const clang::Type *, ClangASTMetadata> TypeMetadataMap;
 
-  MetadataMap m_metadata;
+  DeclMetadataMap m_decl_metadata;
+  TypeMetadataMap m_type_metadata;
 };
 
 } // namespace lldb_private
Index: lldb/include/lldb/Symbol/ClangASTContext.h
===================================================================
--- lldb/include/lldb/Symbol/ClangASTContext.h
+++ lldb/include/lldb/Symbol/ClangASTContext.h
@@ -130,16 +130,24 @@
 
   static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl);
 
-  void SetMetadataAsUserID(const void *object, lldb::user_id_t user_id);
+  void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id);
+  void SetMetadataAsUserID(const clang::Type *type, lldb::user_id_t user_id);
 
-  void SetMetadata(const void *object, ClangASTMetadata &meta_data);
+  void SetMetadata(const clang::Decl *object, ClangASTMetadata &meta_data);
+  void SetMetadata(const clang::Type *object, ClangASTMetadata &meta_data);
+  ClangASTMetadata *GetMetadata(const clang::Decl *object) {
+    return GetMetadata(getASTContext(), object);
+  }
+
+  static ClangASTMetadata *GetMetadata(clang::ASTContext *ast,
+                                       const clang::Decl *object);
 
-  ClangASTMetadata *GetMetadata(const void *object) {
+  ClangASTMetadata *GetMetadata(const clang::Type *object) {
     return GetMetadata(getASTContext(), object);
   }
 
   static ClangASTMetadata *GetMetadata(clang::ASTContext *ast,
-                                       const void *object);
+                                       const clang::Type *object);
 
   // Basic Types
   CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
@@ -472,7 +480,7 @@
   DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc);
 
   static ClangASTMetadata *DeclContextGetMetaData(const CompilerDeclContext &dc,
-                                                  const void *object);
+                                                  const clang::Decl *object);
 
   static clang::ASTContext *
   DeclContextGetClangASTContext(const CompilerDeclContext &dc);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to