shafik created this revision.
shafik added reviewers: martong, teemperor.
Herald added a subscriber: rnkovacs.

This fix was motivated by a crashes in expression parsing during code 
generation in which we had a `RecordDecl` that had incomplete `FieldDecl`. 
During code generation when computing the layout for the `RecordDecl` we crash 
because we have several incomplete `FieldDecl`.

This fixes the issue by assuring that during `ImportDefinition(...)` for a 
`RecordDecl` we also import the definitions for each `FieldDecl`.


https://reviews.llvm.org/D71378

Files:
  clang/lib/AST/ASTImporter.cpp
  
lldb/packages/Python/lldbsuite/test/commands/expression/codegen-crash-typedefdecl-not-in_declcontext/TestCodegenCrashTypedefDeclNotInDeclContext.py
  
lldb/packages/Python/lldbsuite/test/commands/expression/codegen-crash-typedefdecl-not-in_declcontext/main.cpp
  
lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py

Index: lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py
+++ lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py
@@ -1,4 +1,4 @@
 from lldbsuite.test import lldbinline
 from lldbsuite.test import decorators
 
-lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIf(bugnumber="rdar://53756116")])
+lldbinline.MakeInlineTest(__file__, globals(), [])
Index: lldb/packages/Python/lldbsuite/test/commands/expression/codegen-crash-typedefdecl-not-in_declcontext/main.cpp
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/commands/expression/codegen-crash-typedefdecl-not-in_declcontext/main.cpp
@@ -0,0 +1,41 @@
+// This is a reproducer for a crash in codegen. It happens when we have a
+// RecordDecl used in an expression and one of the FieldDecl are not complete.
+// This case happens when:
+// - A RecordDecl (E) has a FieldDecl which is a reference member variable
+// - The underlying type of the FieldDec is a TypedefDecl
+// - The typedef refers to a ClassTemplateSpecialization (DWrapper)
+// - The typedef is not present in the DeclContext of B
+// - The typedef shows up as a return value of a member function of E (f())
+template <typename T>
+struct DWrapper {};
+
+struct D {};
+
+namespace NS {
+typedef DWrapper<D> DW;
+}
+
+struct B {
+  NS::DW spd;
+  int a=0;
+};
+
+struct E {
+   E(B &b): b_ref(b){}
+   NS::DW f(){ return {}; };
+   void g() {
+       return; //%self.expect("p b_ref", substrs=['(B) $0 =', '(spd = NS::DW', 'a = 0)'])
+   }
+
+   B &b_ref;
+};
+
+int main() {
+  B b;
+  E e(b);
+
+  e.g();
+
+  return 0;
+}
+
Index: lldb/packages/Python/lldbsuite/test/commands/expression/codegen-crash-typedefdecl-not-in_declcontext/TestCodegenCrashTypedefDeclNotInDeclContext.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/commands/expression/codegen-crash-typedefdecl-not-in_declcontext/TestCodegenCrashTypedefDeclNotInDeclContext.py
@@ -0,0 +1,4 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(), [])
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1683,6 +1683,33 @@
   Error ChildErrors = Error::success();
   for (auto *From : FromDC->decls()) {
     ExpectedDecl ImportedOrErr = import(From);
+
+    // If we are in the process of ImportDefinition(...) for a RecordDecl we
+    // want to make sure that we are also completeing each FieldDecl. There
+    // are currently cases where this does not happen and this is correctness
+    // fix since operations such as code generation will expect this to be so.
+    if (ImportedOrErr) {
+      FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From);
+      Decl *ImportedDecl = (Decl*)*ImportedOrErr;
+      FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl);
+      if (FieldFrom && FieldTo) {
+        const RecordType *RecordFrom = FieldFrom->getType()->getAs<RecordType>();
+        const RecordType *RecordTo = FieldTo->getType()->getAs<RecordType>();
+        if (RecordFrom && RecordTo) {
+          RecordDecl *FromRecordDecl = RecordFrom->getDecl();
+          RecordDecl *ToRecordDecl = RecordTo->getDecl();
+
+          if (FromRecordDecl->isCompleteDefinition() &&
+              !ToRecordDecl->isCompleteDefinition()) {
+            Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl);
+
+            if (Err)
+              return Err;
+            }
+        }
+      }
+    }
+
     if (!ImportedOrErr) {
       if (AccumulateChildErrors)
         ChildErrors =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to