/// imported while completing the original Decls).
class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener {
ClangASTImporter::ImporterDelegateSP m_delegate;
- llvm::SmallVector<NamedDecl *, 32> m_decls_to_complete;
+ /// List of declarations in the target context that need to be completed.
+ /// Every declaration should only be completed once and therefore should only
+ /// be once in this list.
+ llvm::SetVector<NamedDecl *> m_decls_to_complete;
+ /// Set of declarations that already were successfully completed (not just
+ /// added to m_decls_to_complete).
llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed;
clang::ASTContext *m_dst_ctx;
clang::ASTContext *m_src_ctx;
NamedDecl *decl = m_decls_to_complete.pop_back_val();
m_decls_already_completed.insert(decl);
+ // The decl that should be completed has to be imported into the target
+ // context from some other context.
+ assert(to_context_md->hasOrigin(decl));
// We should only complete decls coming from the source context.
assert(to_context_md->getOrigin(decl).ctx == m_src_ctx);
// Check if we already completed this type.
if (m_decls_already_completed.count(to_named_decl) != 0)
return;
- m_decls_to_complete.push_back(to_named_decl);
+ // Queue this type to be completed.
+ m_decls_to_complete.insert(to_named_decl);
}
};
} // namespace
--- /dev/null
+"""
+Tests declaring RecordDecls in non-top-level expressions.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @no_debug_info_test
+ def test_fwd_decl(self):
+ # Declare a forward decl and import it to the scratch AST.
+ self.expect_expr("struct S; S *s = nullptr; s", result_type="S *")
+
+ @no_debug_info_test
+ def test_struct(self):
+ # Declare a struct and import it to the scratch AST.
+ self.expect("expr struct S {}; S s; s", substrs=["= {}"])
+
+ @no_debug_info_test
+ def test_struct_with_fwd_decl(self):
+ # Import the forward decl to the scratch AST.
+ self.expect_expr("struct S; S *s = nullptr; s", result_type="S *")
+ # Merge the definition into the scratch AST.
+ self.expect("expr struct S {}; S s; s", substrs=["= {}"])
+
+ @no_debug_info_test
+ def test_struct_with_fwd_decl_same_expr(self):
+ # Test both a forward decl and a definition in one expression and
+ # import them into the scratch AST.
+ self.expect("expr struct S; struct S{}; S s; s", substrs=["= {}"])