diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -496,6 +496,7 @@ ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D); ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D); ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D); + ExpectedDecl VisitBindingDecl(BindingDecl *D); ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D); ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D); ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); @@ -2291,6 +2292,35 @@ return ToD; } +ExpectedDecl ASTNodeImporter::VisitBindingDecl(BindingDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToND; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToND, Loc)) + return std::move(Err); + if (ToND) + return ToND; + + Error Err = Error::success(); + QualType ToType = importChecked(Err, D->getType()); + Expr *ToBinding = importChecked(Err, D->getBinding()); + ValueDecl *ToDecomposedDecl = importChecked(Err, D->getDecomposedDecl()); + if (Err) + return std::move(Err); + + BindingDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo())) + return ToD; + + ToD->setBinding(ToType, ToBinding); + ToD->setDecomposedDecl(ToDecomposedDecl); + addDeclToContexts(D, ToD); + + return ToD; +} + ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { ExpectedSLoc LocOrErr = import(D->getLocation()); if (!LocOrErr) diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -3679,6 +3679,52 @@ EXPECT_TRUE(ImportedD->getDefinition()); } +TEST_P(ImportVariables, ImportBindingDecl) { + Decl *From, *To; + std::tie(From, To) = getImportedDecl( + R"( + void declToImport() { + int a[2] = {1,2}; + auto [x1,y1] = a; + auto& [x2,y2] = a; + + struct S { + mutable int x1 : 2; + volatile double y1; + }; + S b; + const auto [x3, y3] = b; + }; + )", + Lang_CXX17, "", Lang_CXX17); + + TranslationUnitDecl *FromTU = From->getTranslationUnitDecl(); + auto *FromF = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("declToImport"))); + auto *ToF = Import(FromF, Lang_CXX17); + EXPECT_TRUE(ToF); + + auto VerifyImport = [&](llvm::StringRef BindName) { + auto *FromB = FirstDeclMatcher().match( + FromF, bindingDecl(hasName(BindName))); + ASSERT_TRUE(FromB); + auto *ToB = Import(FromB, Lang_CXX17); + EXPECT_TRUE(ToB); + EXPECT_EQ(FromB->getBinding() != nullptr, ToB->getBinding() != nullptr); + EXPECT_EQ(FromB->getDecomposedDecl() != nullptr, + ToB->getDecomposedDecl() != nullptr); + EXPECT_EQ(FromB->getHoldingVar() != nullptr, + ToB->getHoldingVar() != nullptr); + }; + + VerifyImport("x1"); + VerifyImport("y1"); + VerifyImport("x2"); + VerifyImport("y2"); + VerifyImport("x3"); + VerifyImport("y3"); +} + struct ImportClasses : ASTImporterOptionSpecificTestBase {}; TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {