shafik updated this revision to Diff 226366.
shafik added a comment.

- Updated test to add dwarfdump test


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68961/new/

https://reviews.llvm.org/D68961

Files:
  include/lldb/Symbol/ClangASTContext.h
  packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
  packages/Python/lldbsuite/test/python_api/type/main.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
  source/Symbol/ClangASTContext.cpp
  test/Shell/SymbolFile/DWARF/anon_class_w_and_wo_export_symbols.ll
  test/Shell/SymbolFile/DWARF/clang-ast-from-dwarf-unamed-and-anon-structs.cpp

Index: test/Shell/SymbolFile/DWARF/clang-ast-from-dwarf-unamed-and-anon-structs.cpp
===================================================================
--- /dev/null
+++ test/Shell/SymbolFile/DWARF/clang-ast-from-dwarf-unamed-and-anon-structs.cpp
@@ -0,0 +1,19 @@
+// Test to verify we are corectly generating anonymous flags when parsing
+// anonymous class and unnamed structs from DWARF to the a clang AST node.
+
+// RUN: %clang++ -g -c -o %t.o %s
+// RUN: lldb-test symbols -dump-clang-ast %t.o | FileCheck %s
+
+struct A {
+  struct {
+    int x;
+  };
+  struct {
+    int y;
+  } C;
+} a;
+
+// CHECK: A::(anonymous struct)
+// CHECK: |-DefinitionData is_anonymous pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+// CHECK: A::(anonymous struct)
+// CHECK: |-DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
Index: test/Shell/SymbolFile/DWARF/anon_class_w_and_wo_export_symbols.ll
===================================================================
--- /dev/null
+++ test/Shell/SymbolFile/DWARF/anon_class_w_and_wo_export_symbols.ll
@@ -0,0 +1,77 @@
+; This test verifies that we do the right thing with DIFlagExportSymbols which is the new
+; behavioir and without the DIFlagExportSymbols which is the old behavior for the given
+; definitions below.
+;
+;```
+; struct A{
+;   struct {
+;    int x;
+;   };
+;   struct {
+;    int y;
+;   };
+;   struct {
+;    int z;
+;   } unnamed;
+; } a;
+;```
+;
+; RUN: %clang++ -g -c -o %t.o %s
+; RUN: lldb-test symbols -dump-clang-ast %t.o | FileCheck %s
+; RUN: dwarfdump %t.o | FileCheck %s --check-prefix DWARFDUMP
+
+%struct.A = type { %struct.anon, %struct.anon.0, %struct.anon.1 }
+%struct.anon = type { i32 }
+%struct.anon.0 = type { i32 }
+%struct.anon.1 = type { i32 }
+
+@a = global %struct.A zeroinitializer, align 4, !dbg !0
+
+!llvm.module.flags = !{!21, !22}
+!llvm.dbg.cu = !{!2}
+!llvm.ident = !{!23}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 11, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "anon_old_new.cpp", directory: "/dir")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 1, size: 96, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTS1A")
+; CHECK: struct A definition
+!7 = !{!8, !13, !17}
+!8 = !DIDerivedType(tag: DW_TAG_member, scope: !6, file: !3, line: 2, baseType: !9, size: 32)
+!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !6, file: !3, line: 2, size: 32, flags: DIFlagExportSymbols | DIFlagTypePassByValue, elements: !10, identifier: "_ZTSN1AUt_E")
+; Correctly identify an anonymous class with DIFlagExportSymbols
+; CHECK: struct definition
+; CHECK: DefinitionData is_anonymous pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+!10 = !{!11}
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !9, file: !3, line: 3, baseType: !12, size: 32)
+!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!13 = !DIDerivedType(tag: DW_TAG_member, scope: !6, file: !3, line: 5, baseType: !14, size: 32, offset: 32)
+!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !6, file: !3, line: 5, size: 32, flags: DIFlagTypePassByValue, elements: !15, identifier: "_ZTSN1AUt0_E")
+; Correctly identify an anonymous class without DIFlagExportSymbols
+; This works b/c we have additional checks when we fields to A.
+; CHECK: struct definition
+; CHECK: DefinitionData is_anonymous pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+!15 = !{!16}
+!16 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !14, file: !3, line: 6, baseType: !12, size: 32)
+!17 = !DIDerivedType(tag: DW_TAG_member, name: "unnamed", scope: !6, file: !3, line: 10, baseType: !18, size: 32, offset: 64)
+!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !6, file: !3, line: 8, size: 32, flags: DIFlagTypePassByValue, elements: !19, identifier: "_ZTSN1AUt1_E")
+; Correctly identify an unamed class
+; CHECK: struct definition
+; CHECK: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
+!19 = !{!20}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !18, file: !3, line: 9, baseType: !12, size: 32)
+!21 = !{i32 2, !"Dwarf Version", i32 4}
+!22 = !{i32 2, !"Debug Info Version", i32 3}
+!23 = !{!"clang version 10.0.0"}
+
+; DWARFDUMP: DW_TAG_structure_type
+; DWARFDUMP: DW_AT_name	("A")
+;
+; DWARFDUMP: DW_TAG_structure_type
+; DWARFDUMP: DW_AT_export_symbols	(true)
+;
+; DWARFDUMP: DW_TAG_structure_type
+; DWARFDUMP-NOT: DW_AT_export_symbols   (true)
Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ source/Symbol/ClangASTContext.cpp
@@ -1346,11 +1346,9 @@
 
 #pragma mark Structure, Unions, Classes
 
-CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
-                                               AccessType access_type,
-                                               const char *name, int kind,
-                                               LanguageType language,
-                                               ClangASTMetadata *metadata) {
+CompilerType ClangASTContext::CreateRecordType(
+    DeclContext *decl_ctx, AccessType access_type, const char *name, int kind,
+    LanguageType language, ClangASTMetadata *metadata, bool exports_symbols) {
   ASTContext *ast = getASTContext();
   assert(ast != nullptr);
 
@@ -1401,10 +1399,7 @@
     // Anonymous classes is a GNU/MSVC extension that clang supports. It
     // requires the anonymous class be embedded within a class. So the new
     // heuristic verifies this condition.
-    //
-    // FIXME: An unnamed class within a class is also wrongly recognized as an
-    // anonymous struct.
-    if (isa<CXXRecordDecl>(decl_ctx))
+    if (isa<CXXRecordDecl>(decl_ctx) && exports_symbols)
       decl->setAnonymousStructOrUnion(true);
   }
 
@@ -8988,7 +8983,7 @@
     TypeSP type = type_list.GetTypeAtIndex(i);
 
     if (!symbol_name.empty())
-      if (symbol_name.compare(type->GetName().GetStringRef()) != 0)
+      if (symbol_name != type->GetName().GetStringRef())
         continue;
 
     s << type->GetName().AsCString() << "\n";
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -181,6 +181,7 @@
   bool is_scoped_enum = false;
   bool is_vector = false;
   bool is_virtual = false;
+  bool exports_symbols = false;
   clang::StorageClass storage = clang::SC_None;
   const char *mangled_name = nullptr;
   lldb_private::ConstString name;
Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -347,6 +347,9 @@
     case DW_AT_GNU_vector:
       is_vector = form_value.Boolean();
       break;
+    case DW_AT_export_symbols:
+      exports_symbols = form_value.Boolean();
+      break;
     }
   }
 }
@@ -1543,7 +1546,7 @@
       clang_type_was_created = true;
       clang_type = m_ast.CreateRecordType(
           decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind,
-          attrs.class_language, &metadata);
+          attrs.class_language, &metadata, attrs.exports_symbols);
     }
   }
 
Index: packages/Python/lldbsuite/test/python_api/type/main.cpp
===================================================================
--- packages/Python/lldbsuite/test/python_api/type/main.cpp
+++ packages/Python/lldbsuite/test/python_api/type/main.cpp
@@ -15,6 +15,14 @@
         TASK_TYPE_1,
         TASK_TYPE_2
     } type;
+    // This struct is anonymous b/c it does not have a name
+    // and it is not unnamed class.
+    // Anonymous classes are a GNU extension.
+    struct {
+      int y;
+    };
+    // This struct is an unnamed class see [class.pre]p1
+    // http://eel.is/c++draft/class#pre-1.sentence-6
     struct {
       int x;
     } my_type_is_nameless;
Index: packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
===================================================================
--- packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
+++ packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
@@ -73,13 +73,17 @@
                         self.assertTrue(enum_member)
                         self.DebugSBType(enum_member.type)
                 elif field.name == "my_type_is_nameless":
-                    self.assertTrue(
+                    self.assertFalse(
                         field.type.IsAnonymousType(),
-                        "my_type_is_nameless has an anonymous type")
+                        "my_type_is_nameless is not an anonymous type")
                 elif field.name == "my_type_is_named":
                     self.assertFalse(
                         field.type.IsAnonymousType(),
                         "my_type_is_named has a named type")
+                elif field.name == None:
+                    self.assertTrue(
+                        field.type.IsAnonymousType(),
+                        "Nameless type is not anonymous")
 
         # Pass an empty string.  LLDB should not crash. :-)
         fuzz_types = target.FindTypes(None)
Index: include/lldb/Symbol/ClangASTContext.h
===================================================================
--- include/lldb/Symbol/ClangASTContext.h
+++ include/lldb/Symbol/ClangASTContext.h
@@ -261,7 +261,8 @@
   CompilerType CreateRecordType(clang::DeclContext *decl_ctx,
                                 lldb::AccessType access_type, const char *name,
                                 int kind, lldb::LanguageType language,
-                                ClangASTMetadata *metadata = nullptr);
+                                ClangASTMetadata *metadata = nullptr,
+                                bool exports_symbols = false);
 
   class TemplateParameterInfos {
   public:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to