Author: Ding Fei Date: 2024-04-20T10:11:02+08:00 New Revision: 0ccdd4c28fca72d1e1d518c6ed9715e92fb47edf
URL: https://github.com/llvm/llvm-project/commit/0ccdd4c28fca72d1e1d518c6ed9715e92fb47edf DIFF: https://github.com/llvm/llvm-project/commit/0ccdd4c28fca72d1e1d518c6ed9715e92fb47edf.diff LOG: [ASTImporter] Fix infinite recurse on return type declared inside body (#68775) Lambda without trailing auto could have return type declared inside the body too. Fixes #68775 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ASTImporter.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index aea8fda35bb29c..c44f238e33846b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -559,6 +559,9 @@ Bug Fixes to AST Handling Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed an infinite recursion in ASTImporter, on return type declared inside + body of C++11 lambda without trailing return (#GH68775). + Miscellaneous Clang Crashes Fixed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 6aaa34c55ce307..f8180047f68609 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -695,7 +695,7 @@ namespace clang { // Returns true if the given function has a placeholder return type and // that type is declared inside the body of the function. // E.g. auto f() { struct X{}; return X(); } - bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D); + bool hasReturnTypeDeclaredInside(FunctionDecl *D); }; template <typename InContainerTy> @@ -3647,15 +3647,28 @@ class IsTypeDeclaredInsideVisitor }; } // namespace -/// This function checks if the function has 'auto' return type that contains +/// This function checks if the given function has a return type that contains /// a reference (in any way) to a declaration inside the same function. -bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { +bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs<FunctionProtoType>(); assert(FromFPT && "Must be called on FunctionProtoType"); + auto IsCXX11LambdaWithouTrailingReturn = [&]() { + if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later + return false; + + if (FromFPT->hasTrailingReturn()) + return false; + + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) + return cast<CXXRecordDecl>(MD->getDeclContext())->isLambda(); + + return false; + }; + QualType RetT = FromFPT->getReturnType(); - if (isa<AutoType>(RetT.getTypePtr())) { + if (isa<AutoType>(RetT.getTypePtr()) || IsCXX11LambdaWithouTrailingReturn()) { FunctionDecl *Def = D->getDefinition(); IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D); return Visitor.CheckType(RetT); @@ -3811,7 +3824,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // E.g.: auto foo() { struct X{}; return X(); } // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified return type. - if (hasAutoReturnTypeDeclaredInside(D)) { + if (hasReturnTypeDeclaredInside(D)) { FromReturnTy = Importer.getFromContext().VoidTy; UsedDifferentProtoType = true; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index acc596fef87b76..4ee64de697d37a 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6721,6 +6721,23 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) { EXPECT_FALSE(FromL->isDependentLambda()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) { + Decl *From, *To; + std::tie(From, To) = getImportedDecl( + R"( + void foo() { + (void) []() { + struct X {}; + return X(); + }; + } + )", + Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only + auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(To, lambdaExpr()); + EXPECT_TRUE(ToLambda); +} + TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) { Decl *FromTU = getTuDecl( R"( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits