summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Horvath <xazax.hun@gmail.com>2017-04-03 11:57:11 +0000
committerGabor Horvath <xazax.hun@gmail.com>2017-04-03 11:57:11 +0000
commit3d2c10d941844e5abec6e5058de90ed132d4f145 (patch)
tree5a32277d30932d4ee5f07de17a27fc19daedcdbb
parent5558ba2d82d7e6c0d30a3a3c1a3de790ca6abac3 (diff)
downloadbcm5719-llvm-3d2c10d941844e5abec6e5058de90ed132d4f145.tar.gz
bcm5719-llvm-3d2c10d941844e5abec6e5058de90ed132d4f145.zip
[ASTImporter] Fix for importing unnamed structs
Patch by Peter Szecsi! Differential Revision: https://reviews.llvm.org/D30876 llvm-svn: 299355
-rw-r--r--clang/lib/AST/ASTImporter.cpp9
-rw-r--r--clang/test/ASTMerge/struct/Inputs/struct1.c62
-rw-r--r--clang/test/ASTMerge/struct/Inputs/struct2.c62
-rw-r--r--clang/test/ASTMerge/struct/test.c10
4 files changed, 139 insertions, 4 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 95492825eb9..74449a965f9 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1221,6 +1221,10 @@ static Optional<unsigned> 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<ElaboratedType>(FieldType)) {
+ FieldType = ElabType->getNamedType();
+ }
if (const auto *RecType = dyn_cast<RecordType>(FieldType)) {
const RecordDecl *RecDecl = RecType->getDecl();
if (RecDecl->getDeclContext() == Owner &&
@@ -3020,9 +3024,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(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<unsigned> Index1
= findUntaggedStructOrUnionIndex(D)) {
diff --git a/clang/test/ASTMerge/struct/Inputs/struct1.c b/clang/test/ASTMerge/struct/Inputs/struct1.c
index 0f3e8b9bc3e..a85aec70a84 100644
--- a/clang/test/ASTMerge/struct/Inputs/struct1.c
+++ b/clang/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/clang/test/ASTMerge/struct/Inputs/struct2.c b/clang/test/ASTMerge/struct/Inputs/struct2.c
index 7fe17a576b2..49fe36d823d 100644
--- a/clang/test/ASTMerge/struct/Inputs/struct2.c
+++ b/clang/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/clang/test/ASTMerge/struct/test.c b/clang/test/ASTMerge/struct/test.c
index ed7750f6bec..b7e24416d25 100644
--- a/clang/test/ASTMerge/struct/test.c
+++ b/clang/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
OpenPOWER on IntegriCloud