spyffe created this revision.
spyffe added a reviewer: manmanren.
spyffe added a subscriber: cfe-commits.
spyffe set the repository for this revision to rL LLVM.

When importing classes and structs with anonymous structs, it is critical that 
distinct anonymous structs remain distinct despite having similar layout.
This is already ensured by distinguishing based on their placement in the 
parent struct, using the function `findAnonymousStructOrUnionIndex`.
The problem is that this function only handles 
```
class Foo { struct { int a; } }
```
and not
```
class Foo { struct { int a; } var; }
```
Both need to be handled, and this patch fixes that.  The test case ensures that 
this functionality doesn't regress.

Repository:
  rL LLVM

http://reviews.llvm.org/D22270

Files:
  lib/AST/ASTImporter.cpp
  test/ASTMerge/Inputs/anonymous-fields1.cpp
  test/ASTMerge/Inputs/anonymous-fields2.cpp
  test/ASTMerge/anonymous-fields.cpp

Index: test/ASTMerge/anonymous-fields.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/anonymous-fields.cpp
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/anonymous-fields1.cpp
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/anonymous-fields2.cpp
+// RUN: %clang_cc1 -emit-obj -o /dev/null -ast-merge %t.1.ast -ast-merge 
%t.2.ast %s
+// expected-no-diagnostics
Index: test/ASTMerge/Inputs/anonymous-fields2.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/Inputs/anonymous-fields2.cpp
@@ -0,0 +1,9 @@
+class A {
+public:
+  struct { int foo; } f;
+  struct { int foo; } g;
+};
+
+inline int useA(A &a) {
+  return (a.f.foo + a.g.foo);
+}
Index: test/ASTMerge/Inputs/anonymous-fields1.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/Inputs/anonymous-fields1.cpp
@@ -0,0 +1,5 @@
+class A {
+public:
+  struct { int foo; } f;
+  struct { int foo; } g;
+};
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -1040,11 +1040,27 @@
   unsigned Index = 0;
   for (const auto *D : Owner->noload_decls()) {
     const auto *F = dyn_cast<FieldDecl>(D);
-    if (!F || !F->isAnonymousStructOrUnion())
+    if (!F)
       continue;
-
-    if (Context.hasSameType(F->getType(), AnonTy))
-      break;
+  
+    if (F->isAnonymousStructOrUnion()) {
+      if (Context.hasSameType(F->getType(), AnonTy)) {
+        break;
+      }
+    } else {
+      // If the field looks like this:
+      // struct { ... } A;
+      QualType FieldType = F->getType();
+      if (const RecordType *RecType = dyn_cast<RecordType>(FieldType)) {
+        const RecordDecl *RecDecl = RecType->getDecl();
+        if (RecDecl->getDeclContext() == Owner &&
+            !RecDecl->getIdentifier()) {
+          if (Context.hasSameType(FieldType, AnonTy)) {
+            break;
+          }
+        }
+      }
+    }
 
     ++Index;
   }


Index: test/ASTMerge/anonymous-fields.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/anonymous-fields.cpp
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/anonymous-fields1.cpp
+// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/anonymous-fields2.cpp
+// RUN: %clang_cc1 -emit-obj -o /dev/null -ast-merge %t.1.ast -ast-merge %t.2.ast %s
+// expected-no-diagnostics
Index: test/ASTMerge/Inputs/anonymous-fields2.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/Inputs/anonymous-fields2.cpp
@@ -0,0 +1,9 @@
+class A {
+public:
+  struct { int foo; } f;
+  struct { int foo; } g;
+};
+
+inline int useA(A &a) {
+  return (a.f.foo + a.g.foo);
+}
Index: test/ASTMerge/Inputs/anonymous-fields1.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/Inputs/anonymous-fields1.cpp
@@ -0,0 +1,5 @@
+class A {
+public:
+  struct { int foo; } f;
+  struct { int foo; } g;
+};
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -1040,11 +1040,27 @@
   unsigned Index = 0;
   for (const auto *D : Owner->noload_decls()) {
     const auto *F = dyn_cast<FieldDecl>(D);
-    if (!F || !F->isAnonymousStructOrUnion())
+    if (!F)
       continue;
-
-    if (Context.hasSameType(F->getType(), AnonTy))
-      break;
+  
+    if (F->isAnonymousStructOrUnion()) {
+      if (Context.hasSameType(F->getType(), AnonTy)) {
+        break;
+      }
+    } else {
+      // If the field looks like this:
+      // struct { ... } A;
+      QualType FieldType = F->getType();
+      if (const RecordType *RecType = dyn_cast<RecordType>(FieldType)) {
+        const RecordDecl *RecDecl = RecType->getDecl();
+        if (RecDecl->getDeclContext() == Owner &&
+            !RecDecl->getIdentifier()) {
+          if (Context.hasSameType(FieldType, AnonTy)) {
+            break;
+          }
+        }
+      }
+    }
 
     ++Index;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to