From f93dee10336a2361da528db0ff0f7188acba9627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <1.int32@gmail.com> Date: Fri, 10 Jun 2022 10:00:34 +0200 Subject: [PATCH] [clang][ASTImporter] Fix import of function with auto return type. Fix a case of importing a function with auto return type that is resolved with a type template argument that is declared inside the function. Fixes #55500 Reviewed By: martong Differential Revision: https://reviews.llvm.org/D127396 --- clang/lib/AST/ASTImporter.cpp | 35 ++++++++++------ clang/unittests/AST/ASTImporterTest.cpp | 55 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 21b9f21b8e6e..7fee8d21fa39 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3227,23 +3227,32 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { return false; } +static bool hasTypeDeclaredInsideFunction(QualType T, const FunctionDecl *FD) { + if (T.isNull()) + return false; + if (const auto *RecordT = T->getAs()) { + const RecordDecl *RD = RecordT->getDecl(); + assert(RD); + if (isAncestorDeclContextOf(FD, RD)) { + assert(RD->getLexicalDeclContext() == RD->getDeclContext()); + return true; + } + if (const auto *RDTempl = dyn_cast(RD)) + return llvm::count_if(RDTempl->getTemplateArgs().asArray(), + [FD](const TemplateArgument &Arg) { + return hasTypeDeclaredInsideFunction( + Arg.getAsType(), FD); + }); + } + return false; +} + bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs(); assert(FromFPT && "Must be called on FunctionProtoType"); - if (const AutoType *AutoT = - FromFPT->getReturnType()->getContainedAutoType()) { - QualType DeducedT = AutoT->getDeducedType(); - if (const auto *RecordT = - !DeducedT.isNull() ? DeducedT->getAs() : nullptr) { - const RecordDecl *RD = RecordT->getDecl(); - assert(RD); - if (isAncestorDeclContextOf(D, RD)) { - assert(RD->getLexicalDeclContext() == RD->getDeclContext()); - return true; - } - } - } + if (const AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) + return hasTypeDeclaredInsideFunction(AutoT->getDeducedType(), D); if (const auto *TypedefT = FromFPT->getReturnType()->getAs()) { const TypedefNameDecl *TD = TypedefT->getDecl(); assert(TD); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 4d37ac2ebb2e..607c049608e6 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6319,6 +6319,61 @@ TEST_P(ASTImporterOptionSpecificTestBase, struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {}; +TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) { + Decl *FromTU = getTuDecl( + R"( + template struct Tmpl {}; + auto foo() { + struct X {}; + return Tmpl(); + } + )", + Lang_CXX14, "input0.cc"); + FunctionDecl *From = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + FunctionDecl *To = Import(From, Lang_CXX14); + EXPECT_TRUE(To); + EXPECT_TRUE(isa(To->getReturnType())); +} + +TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) { + Decl *FromTU = getTuDecl( + R"( + template struct Tmpl {}; + auto foo() { + struct X {}; + return Tmpl>(); + } + )", + Lang_CXX14, "input0.cc"); + FunctionDecl *From = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + FunctionDecl *To = Import(From, Lang_CXX14); + EXPECT_TRUE(To); + EXPECT_TRUE(isa(To->getReturnType())); +} + +TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) { + Decl *FromTU = getTuDecl( + R"( + template struct Tmpl {}; + auto foo() { + struct X {}; + using x_type = X; + return Tmpl(); + } + )", + Lang_CXX14, "input0.cc"); + FunctionDecl *From = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("foo"))); + + FunctionDecl *To = Import(From, Lang_CXX14); + EXPECT_TRUE(To); + EXPECT_TRUE(isa(To->getReturnType())); +} + TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) { Decl *FromTU = getTuDecl( R"(