Author: sas Date: Wed Apr 8 16:52:45 2015 New Revision: 234441 URL: http://llvm.org/viewvc/llvm-project?rev=234441&view=rev Log: Fix resolution of certain recursive types.
Summary: If a struct type S has a member T that has a member that is a function that returns a typedef of S* the respective field would be duplicated, which caused an assert down the line in RecordLayoutBuilder. This patch adds a check that removes the possibility of trying to resolve the same type twice within the same callstack. This commit also adds unit tests for these failures. Fixes https://llvm.org/bugs/show_bug.cgi?id=20486. Patch by Cristian Hancila. Test Plan: Run unit tests. Reviewers: clayborg spyffe Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D8561 Added: lldb/trunk/test/types/TestRecursiveTypes.py lldb/trunk/test/types/recursive_type_1.cpp lldb/trunk/test/types/recursive_type_2.cpp lldb/trunk/test/types/recursive_type_main.cpp Modified: lldb/trunk/include/lldb/Expression/ClangASTSource.h lldb/trunk/source/Expression/ClangASTSource.cpp lldb/trunk/source/Symbol/ClangASTImporter.cpp Modified: lldb/trunk/include/lldb/Expression/ClangASTSource.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangASTSource.h?rev=234441&r1=234440&r2=234441&view=diff ============================================================================== --- lldb/trunk/include/lldb/Expression/ClangASTSource.h (original) +++ lldb/trunk/include/lldb/Expression/ClangASTSource.h Wed Apr 8 16:52:45 2015 @@ -51,6 +51,7 @@ public: m_lookups_enabled (false), m_target (target), m_ast_context (NULL), + m_active_lexical_decls (), m_active_lookups () { m_ast_importer = m_target->GetClangASTImporter(); @@ -404,6 +405,7 @@ protected: const lldb::TargetSP m_target; ///< The target to use in finding variables and types. clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. ClangASTImporter *m_ast_importer; ///< The target's AST importer. + std::set<const clang::Decl *> m_active_lexical_decls; std::set<const char *> m_active_lookups; }; Modified: lldb/trunk/source/Expression/ClangASTSource.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangASTSource.cpp?rev=234441&r1=234440&r2=234441&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangASTSource.cpp (original) +++ lldb/trunk/source/Expression/ClangASTSource.cpp Wed Apr 8 16:52:45 2015 @@ -30,6 +30,31 @@ using namespace clang; using namespace lldb_private; +//------------------------------------------------------------------ +// Scoped class that will remove an active lexical decl from the set +// when it goes out of scope. +//------------------------------------------------------------------ +namespace { + class ScopedLexicalDeclEraser + { + public: + ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls, + const clang::Decl *decl) + : m_active_lexical_decls(decls), m_decl(decl) + { + } + + ~ScopedLexicalDeclEraser() + { + m_active_lexical_decls.erase(m_decl); + } + + private: + std::set<const clang::Decl *> &m_active_lexical_decls; + const clang::Decl *m_decl; + }; +} + ClangASTSource::~ClangASTSource() { m_ast_importer->ForgetDestination(m_ast_context); @@ -191,6 +216,12 @@ ClangASTSource::CompleteType (TagDecl *t dumper.ToLog(log, " [CTD] "); } + auto iter = m_active_lexical_decls.find(tag_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(tag_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + if (!m_ast_importer->CompleteTagDecl (tag_decl)) { // We couldn't complete the type. Maybe there's a definition @@ -402,6 +433,12 @@ ClangASTSource::FindExternalLexicalDecls if (!context_decl) return ELR_Failure; + auto iter = m_active_lexical_decls.find(context_decl); + if (iter != m_active_lexical_decls.end()) + return ELR_Failure; + m_active_lexical_decls.insert(context_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=234441&r1=234440&r2=234441&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Wed Apr 8 16:52:45 2015 @@ -286,7 +286,12 @@ ClangASTImporter::RequireCompleteType (c if (const TagType *tag_type = type->getAs<TagType>()) { - return CompleteTagDecl(tag_type->getDecl()); + TagDecl *tag_decl = tag_type->getDecl(); + + if (tag_decl->getDefinition() || tag_decl->isBeingDefined()) + return true; + + return CompleteTagDecl(tag_decl); } if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { Added: lldb/trunk/test/types/TestRecursiveTypes.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/types/TestRecursiveTypes.py?rev=234441&view=auto ============================================================================== --- lldb/trunk/test/types/TestRecursiveTypes.py (added) +++ lldb/trunk/test/types/TestRecursiveTypes.py Wed Apr 8 16:52:45 2015 @@ -0,0 +1,68 @@ +""" +Test that recursive types are handled correctly. +""" + +import lldb +import lldbutil +import sys +import unittest2 +from lldbtest import * + +class RecursiveTypesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # disable "There is a running process, kill it and restart?" prompt + self.runCmd("settings set auto-confirm true") + self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) + # Find the line number to break for main.c. + self.line = line_number('recursive_type_main.cpp', + '// Test at this line.') + + self.d1 = {'CXX_SOURCES': 'recursive_type_main.cpp recursive_type_1.cpp'} + self.d2 = {'CXX_SOURCES': 'recursive_type_main.cpp recursive_type_2.cpp'} + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @dsym_test + def test_recursive_dsym_type_1(self): + """Test that recursive structs are displayed correctly.""" + self.buildDsym(dictionary=self.d1) + self.print_struct() + + @dwarf_test + def test_recursive_dwarf_type_1(self): + """Test that recursive structs are displayed correctly.""" + self.buildDwarf(dictionary=self.d1) + self.print_struct() + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @dsym_test + def test_recursive_dsym_type_2(self): + """Test that recursive structs are displayed correctly.""" + self.buildDsym(dictionary=self.d2) + self.print_struct() + + @dwarf_test + def test_recursive_dwarf_type_2(self): + """Test that recursive structs are displayed correctly.""" + self.buildDwarf(dictionary=self.d2) + self.print_struct() + + def print_struct(self): + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "recursive_type_main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("print tpi", RUN_SUCCEEDED) + self.expect("print *tpi", RUN_SUCCEEDED) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/types/recursive_type_1.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/types/recursive_type_1.cpp?rev=234441&view=auto ============================================================================== --- lldb/trunk/test/types/recursive_type_1.cpp (added) +++ lldb/trunk/test/types/recursive_type_1.cpp Wed Apr 8 16:52:45 2015 @@ -0,0 +1,12 @@ +typedef struct t *tp; +typedef tp (*get_tp)(); + +struct s { + get_tp get_tp_p; +}; + +struct t { + struct s *s; +}; + +struct t t; Added: lldb/trunk/test/types/recursive_type_2.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/types/recursive_type_2.cpp?rev=234441&view=auto ============================================================================== --- lldb/trunk/test/types/recursive_type_2.cpp (added) +++ lldb/trunk/test/types/recursive_type_2.cpp Wed Apr 8 16:52:45 2015 @@ -0,0 +1,10 @@ +typedef struct t *tp; +typedef tp (*get_tp)(); + +struct t { + struct { + get_tp get_tp_p; + }; +}; + +struct t t; Added: lldb/trunk/test/types/recursive_type_main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/types/recursive_type_main.cpp?rev=234441&view=auto ============================================================================== --- lldb/trunk/test/types/recursive_type_main.cpp (added) +++ lldb/trunk/test/types/recursive_type_main.cpp Wed Apr 8 16:52:45 2015 @@ -0,0 +1,8 @@ +typedef struct t *tp; +extern struct t t; + +int main() { + tp tpi = &t; + // Test at this line. + return 0; +} _______________________________________________ lldb-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
