Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -1221,6 +1221,10 @@ // If the field looks like this: // struct { ... } A; QualType FieldType = F->getType(); + // In case of nested structs. + while (const auto *ElabType = dyn_cast(FieldType)) { + FieldType = ElabType->getNamedType(); + } if (const auto *RecType = dyn_cast(FieldType)) { const RecordDecl *RecDecl = RecType->getDecl(); if (RecDecl->getDeclContext() == Owner && @@ -3030,9 +3034,8 @@ } if (RecordDecl *FoundRecord = dyn_cast(Found)) { - if (D->isAnonymousStructOrUnion() && - FoundRecord->isAnonymousStructOrUnion()) { - // If both anonymous structs/unions are in a record context, make sure + if (!SearchName) { + // If both unnamed structs/unions are in a record context, make sure // they occur in the same location in the context records. if (Optional Index1 = findUntaggedStructOrUnionIndex(D)) { @@ -3076,8 +3079,6 @@ AdoptDecl = FoundRecord; continue; - } else if (!SearchName) { - continue; } } Index: test/ASTMerge/struct/Inputs/struct1.c =================================================================== --- test/ASTMerge/struct/Inputs/struct1.c +++ test/ASTMerge/struct/Inputs/struct1.c @@ -61,3 +61,65 @@ Int i; float f; } x11; + +//Matches +struct Unnamed { + union { + struct { + int i; + } S; + struct { + float i; + } R; + } U; +} x12; + +//Matches +struct DeepUnnamed { + union { + union { + struct { + long i; + } S; + struct { + int i; + } R; + } U1; + union { + struct { + long i; + } S; + struct { + float i; + } T; + } U2; + } U; + struct { + long i; + } V; +} x13; + +// Mismatch due to unnamed struct used internally +struct DeepUnnamedError { + union { + union { + struct { + long i; + } S; + struct { + int i; + } R; + } U1; + union { + struct { + long i; + } S; + struct { + float i; + } T; + } U2; + } U; + struct { + long i; + } V; +} x14; \ No newline at end of file Index: test/ASTMerge/struct/Inputs/struct2.c =================================================================== --- test/ASTMerge/struct/Inputs/struct2.c +++ test/ASTMerge/struct/Inputs/struct2.c @@ -58,3 +58,65 @@ int i; float f; } x11; + +//Matches +struct Unnamed { + union { + struct { + int i; + } S; + struct { + float i; + } R; + } U; +} x12; + +//Matches +struct DeepUnnamed { + union { + union { + struct { + long i; + } S; + struct { + int i; + } R; + } U1; + union { + struct { + long i; + } S; + struct { + float i; + } T; + } U2; + } U; + struct { + long i; + } V; +} x13; + +// Mismatch due to unnamed struct used internally +struct DeepUnnamedError { + union { + union { + struct { + long i; + } S; + struct { + int i; + } R; + } U1; + union { + struct { + float i; + } S; + struct { + float i; + } T; + } U2; + } U; + struct { + long i; + } V; +} x14; Index: test/ASTMerge/struct/test.c =================================================================== --- test/ASTMerge/struct/test.c +++ test/ASTMerge/struct/test.c @@ -39,4 +39,12 @@ // CHECK: struct2.c:53:43: note: field 'Deeper' has type 'struct DeeperError *' here // CHECK: struct2.c:54:3: error: external variable 'xDeep' declared with incompatible types in different translation units ('struct DeepError' vs. 'struct DeepError') // CHECK: struct1.c:57:3: note: declared here with type 'struct DeepError' -// CHECK: 8 warnings and 7 errors generated +// CHECK: struct1.c:114:7: warning: type 'struct DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS:.+]]/struct1.c:114:7)' has incompatible definitions in different translation units +// CHECK: struct1.c:115:14: note: field 'i' has type 'long' here +// CHECK: struct2.c:112:15: note: field 'i' has type 'float' here +// CHECK: struct1.c:113:5: warning: type 'union DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS]]/struct1.c:113:5)' has incompatible definitions in different translation units +// CHECK: struct1.c:116:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]/struct1.c:114:7)' here +// CHECK: struct2.c:113:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]/struct2.c:111:7)' here +// CHECK: struct2.c:122:3: error: external variable 'x14' declared with incompatible types in different translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError') +// check: struct1.c:125:3: note: declared here with type 'struct DeepUnnamedError' +// CHECK: 10 warnings and 8 errors generated