summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h3
-rw-r--r--lldb/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py8
-rw-r--r--lldb/packages/Python/lldbsuite/test/python_api/type/main.cpp8
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp5
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h1
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp15
-rw-r--r--lldb/test/Shell/SymbolFile/DWARF/anon_class_w_and_wo_export_symbols.ll77
-rw-r--r--lldb/test/Shell/SymbolFile/DWARF/clang-ast-from-dwarf-unamed-and-anon-structs.cpp19
8 files changed, 122 insertions, 14 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index c5d840973ae..e59e756276c 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -261,7 +261,8 @@ public:
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:
diff --git a/lldb/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py b/lldb/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
index b3b321c6ca8..75a793a95b2 100644
--- a/lldb/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
+++ b/lldb/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py
@@ -73,13 +73,17 @@ class TypeAndTypeListTestCase(TestBase):
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)
diff --git a/lldb/packages/Python/lldbsuite/test/python_api/type/main.cpp b/lldb/packages/Python/lldbsuite/test/python_api/type/main.cpp
index 8f5b93927c7..b43b617b0f9 100644
--- a/lldb/packages/Python/lldbsuite/test/python_api/type/main.cpp
+++ b/lldb/packages/Python/lldbsuite/test/python_api/type/main.cpp
@@ -15,6 +15,14 @@ public:
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;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 636e6032b87..42e25f727e4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -347,6 +347,9 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
case DW_AT_GNU_vector:
is_vector = form_value.Boolean();
break;
+ case DW_AT_export_symbols:
+ exports_symbols = form_value.Boolean();
+ break;
}
}
}
@@ -1546,7 +1549,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
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);
}
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 106f9254a44..1f46178108b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -181,6 +181,7 @@ struct ParsedDWARFTypeAttributes {
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;
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 565b15a007d..4a44ee0b1c7 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -1347,11 +1347,9 @@ CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) {
#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);
@@ -1402,10 +1400,7 @@ CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx,
// 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);
}
@@ -8989,7 +8984,7 @@ void ClangASTContext::DumpFromSymbolFile(Stream &s,
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";
diff --git a/lldb/test/Shell/SymbolFile/DWARF/anon_class_w_and_wo_export_symbols.ll b/lldb/test/Shell/SymbolFile/DWARF/anon_class_w_and_wo_export_symbols.ll
new file mode 100644
index 00000000000..b0a9f229505
--- /dev/null
+++ b/lldb/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: llvm-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)
diff --git a/lldb/test/Shell/SymbolFile/DWARF/clang-ast-from-dwarf-unamed-and-anon-structs.cpp b/lldb/test/Shell/SymbolFile/DWARF/clang-ast-from-dwarf-unamed-and-anon-structs.cpp
new file mode 100644
index 00000000000..f1254fe3b1b
--- /dev/null
+++ b/lldb/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
OpenPOWER on IntegriCloud