From 2844a309ef2c40f9e5d5961948e110a8a46d1533 Mon Sep 17 00:00:00 2001 From: Aleksei Sidorin Date: Thu, 5 Apr 2018 15:31:49 +0000 Subject: [PATCH] [ASTImporter] Fix for importing unnamed structs Patch by Peter Szecsi! Differential Revision: https://reviews.llvm.org/D30876 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@329301 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 5 +-- lib/AST/ASTStructuralEquivalence.cpp | 4 ++ test/ASTMerge/struct/Inputs/struct1.c | 62 +++++++++++++++++++++++++++ test/ASTMerge/struct/Inputs/struct2.c | 62 +++++++++++++++++++++++++++ test/ASTMerge/struct/test.c | 10 ++++- 5 files changed, 139 insertions(+), 4 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 6b9260d2d8..2d9e1c8883 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1923,9 +1923,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } 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 = StructuralEquivalenceContext::findUntaggedStructOrUnionIndex( diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index da0a26e40b..d74042c883 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -1256,6 +1256,10 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) { // 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 && !RecDecl->getIdentifier()) { diff --git a/test/ASTMerge/struct/Inputs/struct1.c b/test/ASTMerge/struct/Inputs/struct1.c index 0f3e8b9bc3..a85aec70a8 100644 --- a/test/ASTMerge/struct/Inputs/struct1.c +++ b/test/ASTMerge/struct/Inputs/struct1.c @@ -77,3 +77,65 @@ typedef struct { } S13; S13 x13; + +// Matches +struct Unnamed { + union { + struct { + int i; + } S; + struct { + float i; + } R; + } U; +} x14; + +// 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; +} x15; + +// Mismatch due to unnamed struct used internally +struct DeepUnnamedError { + union { + union { + struct { + long i; + } S; + struct { + int i; + } R; + } U1; + union { + struct { + long i; // Mismatch here. + } S; + struct { + float i; + } T; + } U2; + } U; + struct { + long i; + } V; +} x16; diff --git a/test/ASTMerge/struct/Inputs/struct2.c b/test/ASTMerge/struct/Inputs/struct2.c index 7fe17a576b..49fe36d823 100644 --- a/test/ASTMerge/struct/Inputs/struct2.c +++ b/test/ASTMerge/struct/Inputs/struct2.c @@ -74,3 +74,65 @@ typedef struct { } S13; S13 x13; + +// Matches +struct Unnamed { + union { + struct { + int i; + } S; + struct { + float i; + } R; + } U; +} x14; + +// 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; +} x15; + +// Mismatch due to unnamed struct used internally +struct DeepUnnamedError { + union { + union { + struct { + long i; + } S; + struct { + int i; + } R; + } U1; + union { + struct { + float i; // Mismatch here. + } S; + struct { + float i; + } T; + } U2; + } U; + struct { + long i; + } V; +} x16; diff --git a/test/ASTMerge/struct/test.c b/test/ASTMerge/struct/test.c index ed7750f6be..b7e24416d2 100644 --- a/test/ASTMerge/struct/test.c +++ b/test/ASTMerge/struct/test.c @@ -44,4 +44,12 @@ // CHECK: struct2.c:72:7: note: field 'i' has type 'int' here // CHECK: struct2.c:76:5: error: external variable 'x13' declared with incompatible types in different translation units ('S13' vs. 'S13') // CHECK: struct1.c:79:5: note: declared here with type 'S13' -// CHECK: 9 warnings and 8 errors generated +// CHECK: struct1.c:130:7: warning: type 'struct DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS:.+]]/struct1.c:130:7)' has incompatible definitions in different translation units +// CHECK: struct1.c:131:14: note: field 'i' has type 'long' here +// CHECK: struct2.c:128:15: note: field 'i' has type 'float' here +// CHECK: struct1.c:129:5: warning: type 'union DeepUnnamedError::(anonymous at [[PATH_TO_INPUTS]]/struct1.c:129:5)' has incompatible definitions in different translation units +// CHECK: struct1.c:132:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]/struct1.c:130:7)' here +// CHECK: struct2.c:129:9: note: field 'S' has type 'struct (anonymous struct at [[PATH_TO_INPUTS]]/struct2.c:127:7)' here +// CHECK: struct2.c:138:3: error: external variable 'x16' declared with incompatible types in different translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError') +// CHECK: struct1.c:141:3: note: declared here with type 'struct DeepUnnamedError' +// CHECK: 11 warnings and 9 errors generated -- 2.40.0