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: 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: 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: 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: 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(decl_ctx)) + if (isa(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: 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