diff options
| author | Balazs Keri <1.int32@gmail.com> | 2018-08-08 09:40:57 +0000 |
|---|---|---|
| committer | Balazs Keri <1.int32@gmail.com> | 2018-08-08 09:40:57 +0000 |
| commit | 2544b4b00ac05cf2e80cd4c7a75277dd930ec80d (patch) | |
| tree | 293582c97c10b3a24c6221b40d02457f0870f77f | |
| parent | 4107b31df25af1d5ff65607e83686ec4188b7349 (diff) | |
| download | bcm5719-llvm-2544b4b00ac05cf2e80cd4c7a75277dd930ec80d.tar.gz bcm5719-llvm-2544b4b00ac05cf2e80cd4c7a75277dd930ec80d.zip | |
[ASTImporter] Load external Decls when getting field index.
Summary:
At equality check of fields without name the index of fields is compared.
At determining the index of a field all fields of the parent context
should be loaded from external source to find the field at all.
Reviewers: a.sidorin, a_sidorin, r.stahl
Reviewed By: a.sidorin
Subscribers: martong, cfe-commits
Differential Revision: https://reviews.llvm.org/D49796
llvm-svn: 339226
| -rw-r--r-- | clang/include/clang/AST/ASTImporter.h | 7 | ||||
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 47 | ||||
| -rw-r--r-- | clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp | 3 | ||||
| -rw-r--r-- | clang/test/ASTMerge/unnamed_fields/test.cpp | 3 | ||||
| -rw-r--r-- | clang/unittests/AST/ASTImporterTest.cpp | 34 |
5 files changed, 75 insertions, 19 deletions
diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 2e9a8775a8a..311d64e7cbf 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -333,6 +333,13 @@ class Attr; /// equivalent. bool IsStructurallyEquivalent(QualType From, QualType To, bool Complain = true); + + /// Determine the index of a field in its parent record. + /// F should be a field (or indirect field) declaration. + /// \returns The index of the field in its parent context, starting from 1. + /// 0 is returned on error (parent context is non-record). + static unsigned getFieldIndex(Decl *F); + }; } // namespace clang diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 38ad4e28931..791dcc747cc 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -71,6 +71,28 @@ namespace clang { + unsigned ASTImporter::getFieldIndex(Decl *F) { + assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) && + "Try to get field index for non-field."); + + auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); + if (!Owner) + return 0; + + unsigned Index = 1; + for (const auto *D : Owner->decls()) { + if (D == F) + return Index; + + if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) + ++Index; + } + + llvm_unreachable("Field was not found in its parent context."); + + return 0; + } + template <class T> SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Redeclarable<T>* D) { @@ -2829,23 +2851,6 @@ Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } -static unsigned getFieldIndex(Decl *F) { - auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); - if (!Owner) - return 0; - - unsigned Index = 1; - for (const auto *D : Owner->noload_decls()) { - if (D == F) - return Index; - - if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) - ++Index; - } - - return Index; -} - Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; @@ -2863,7 +2868,9 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { for (auto *FoundDecl : FoundDecls) { if (auto *FoundField = dyn_cast<FieldDecl>(FoundDecl)) { // For anonymous fields, match up by index. - if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) + if (!Name && + ASTImporter::getFieldIndex(D) != + ASTImporter::getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), @@ -2928,7 +2935,9 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { // For anonymous indirect fields, match up by index. - if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) + if (!Name && + ASTImporter::getFieldIndex(D) != + ASTImporter::getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), diff --git a/clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp b/clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp new file mode 100644 index 00000000000..1bb0f358dcf --- /dev/null +++ b/clang/test/ASTMerge/unnamed_fields/Inputs/il.cpp @@ -0,0 +1,3 @@ +void f(int X, int Y, bool Z) { + auto x = [X, Y, Z] { (void)Z; }; +} diff --git a/clang/test/ASTMerge/unnamed_fields/test.cpp b/clang/test/ASTMerge/unnamed_fields/test.cpp new file mode 100644 index 00000000000..6ae3176df4f --- /dev/null +++ b/clang/test/ASTMerge/unnamed_fields/test.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp +// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s +// CHECK-NOT: warning: field '' declared with incompatible types in different translation units ('bool' vs. 'int') diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 04006a0bea3..2690f4e5f1f 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -2641,6 +2641,40 @@ TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) { R1, recordDecl(has(fieldDecl(hasName("next")))))); } +TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) { + Decl *FromTU = getTuDecl( + R"( + void f(int X, int Y, bool Z) { + (void)[X, Y, Z] { (void)Z; }; + } + )", + Lang_CXX11, "input0.cc"); + auto *FromF = FirstDeclMatcher<FunctionDecl>().match( + FromTU, functionDecl(hasName("f"))); + auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11)); + EXPECT_TRUE(ToF); + + CXXRecordDecl *FromLambda = + cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>( + FromF->getBody())->body_front())->getSubExpr())->getLambdaClass(); + + auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11)); + EXPECT_TRUE(ToLambda); + + // Check if the fields of the lambda class are imported in correct order. + unsigned FromIndex = 0u; + for (auto *FromField : FromLambda->fields()) { + ASSERT_FALSE(FromField->getDeclName()); + auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11)); + EXPECT_TRUE(ToField); + unsigned ToIndex = ASTImporter::getFieldIndex(ToField); + EXPECT_EQ(ToIndex, FromIndex + 1); + ++FromIndex; + } + + EXPECT_EQ(FromIndex, 3u); +} + struct DeclContextTest : ASTImporterTestBase {}; TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { |

