summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/ASTImporter.cpp34
-rw-r--r--clang/test/ASTMerge/Inputs/anonymous-fields1.cpp5
-rw-r--r--clang/test/ASTMerge/Inputs/anonymous-fields2.cpp9
-rw-r--r--clang/test/ASTMerge/anonymous-fields.cpp4
4 files changed, 43 insertions, 9 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 2be4b9e938a..bc1f9f96a06 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1029,7 +1029,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
/// including the next assigned index (if none of them match). Returns an
/// empty option if the context is not a record, i.e.. if the anonymous
/// struct/union is at namespace or block scope.
-static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) {
+static Optional<unsigned> findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
ASTContext &Context = Anon->getASTContext();
QualType AnonTy = Context.getRecordType(Anon);
@@ -1040,13 +1040,29 @@ static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) {
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;
+ ++Index;
+ continue;
+ }
- ++Index;
+ // If the field looks like this:
+ // struct { ... } A;
+ QualType FieldType = F->getType();
+ if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
+ const RecordDecl *RecDecl = RecType->getDecl();
+ if (RecDecl->getDeclContext() == Owner &&
+ !RecDecl->getIdentifier()) {
+ if (Context.hasSameType(FieldType, AnonTy))
+ break;
+ ++Index;
+ continue;
+ }
+ }
}
return Index;
@@ -1068,8 +1084,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) {
// If both anonymous structs/unions are in a record context, make sure
// they occur in the same location in the context records.
- if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D1)) {
- if (Optional<unsigned> Index2 = findAnonymousStructOrUnionIndex(D2)) {
+ if (Optional<unsigned> Index1 = findUntaggedStructOrUnionIndex(D1)) {
+ if (Optional<unsigned> Index2 = findUntaggedStructOrUnionIndex(D2)) {
if (*Index1 != *Index2)
return false;
}
@@ -2749,9 +2765,9 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
// If both anonymous structs/unions are in a record context, make sure
// they occur in the same location in the context records.
if (Optional<unsigned> Index1
- = findAnonymousStructOrUnionIndex(D)) {
+ = findUntaggedStructOrUnionIndex(D)) {
if (Optional<unsigned> Index2 =
- findAnonymousStructOrUnionIndex(FoundRecord)) {
+ findUntaggedStructOrUnionIndex(FoundRecord)) {
if (*Index1 != *Index2)
continue;
}
diff --git a/clang/test/ASTMerge/Inputs/anonymous-fields1.cpp b/clang/test/ASTMerge/Inputs/anonymous-fields1.cpp
new file mode 100644
index 00000000000..829bc0edd30
--- /dev/null
+++ b/clang/test/ASTMerge/Inputs/anonymous-fields1.cpp
@@ -0,0 +1,5 @@
+class A {
+public:
+ struct { int foo; } f;
+ struct { int foo; } g;
+};
diff --git a/clang/test/ASTMerge/Inputs/anonymous-fields2.cpp b/clang/test/ASTMerge/Inputs/anonymous-fields2.cpp
new file mode 100644
index 00000000000..28ea46d9871
--- /dev/null
+++ b/clang/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);
+}
diff --git a/clang/test/ASTMerge/anonymous-fields.cpp b/clang/test/ASTMerge/anonymous-fields.cpp
new file mode 100644
index 00000000000..67afc29d07e
--- /dev/null
+++ b/clang/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
OpenPOWER on IntegriCloud