Skip to content

Commit 0ccdd4c

Browse files
authored
[ASTImporter] Fix infinite recurse on return type declared inside body (llvm#68775)
Lambda without trailing auto could have return type declared inside the body too. Fixes llvm#68775
1 parent 30257dd commit 0ccdd4c

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@ Bug Fixes to AST Handling
559559
Miscellaneous Bug Fixes
560560
^^^^^^^^^^^^^^^^^^^^^^^
561561

562+
- Fixed an infinite recursion in ASTImporter, on return type declared inside
563+
body of C++11 lambda without trailing return (#GH68775).
564+
562565
Miscellaneous Clang Crashes Fixed
563566
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
564567

clang/lib/AST/ASTImporter.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ namespace clang {
695695
// Returns true if the given function has a placeholder return type and
696696
// that type is declared inside the body of the function.
697697
// E.g. auto f() { struct X{}; return X(); }
698-
bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D);
698+
bool hasReturnTypeDeclaredInside(FunctionDecl *D);
699699
};
700700

701701
template <typename InContainerTy>
@@ -3647,15 +3647,28 @@ class IsTypeDeclaredInsideVisitor
36473647
};
36483648
} // namespace
36493649

3650-
/// This function checks if the function has 'auto' return type that contains
3650+
/// This function checks if the given function has a return type that contains
36513651
/// a reference (in any way) to a declaration inside the same function.
3652-
bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) {
3652+
bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
36533653
QualType FromTy = D->getType();
36543654
const auto *FromFPT = FromTy->getAs<FunctionProtoType>();
36553655
assert(FromFPT && "Must be called on FunctionProtoType");
36563656

3657+
auto IsCXX11LambdaWithouTrailingReturn = [&]() {
3658+
if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later
3659+
return false;
3660+
3661+
if (FromFPT->hasTrailingReturn())
3662+
return false;
3663+
3664+
if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
3665+
return cast<CXXRecordDecl>(MD->getDeclContext())->isLambda();
3666+
3667+
return false;
3668+
};
3669+
36573670
QualType RetT = FromFPT->getReturnType();
3658-
if (isa<AutoType>(RetT.getTypePtr())) {
3671+
if (isa<AutoType>(RetT.getTypePtr()) || IsCXX11LambdaWithouTrailingReturn()) {
36593672
FunctionDecl *Def = D->getDefinition();
36603673
IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
36613674
return Visitor.CheckType(RetT);
@@ -3811,7 +3824,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
38113824
// E.g.: auto foo() { struct X{}; return X(); }
38123825
// To avoid an infinite recursion when importing, create the FunctionDecl
38133826
// with a simplified return type.
3814-
if (hasAutoReturnTypeDeclaredInside(D)) {
3827+
if (hasReturnTypeDeclaredInside(D)) {
38153828
FromReturnTy = Importer.getFromContext().VoidTy;
38163829
UsedDifferentProtoType = true;
38173830
}

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6721,6 +6721,23 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
67216721
EXPECT_FALSE(FromL->isDependentLambda());
67226722
}
67236723

6724+
TEST_P(ASTImporterOptionSpecificTestBase,
6725+
ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) {
6726+
Decl *From, *To;
6727+
std::tie(From, To) = getImportedDecl(
6728+
R"(
6729+
void foo() {
6730+
(void) []() {
6731+
struct X {};
6732+
return X();
6733+
};
6734+
}
6735+
)",
6736+
Lang_CXX11, "", Lang_CXX11, "foo"); // c++11 only
6737+
auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(To, lambdaExpr());
6738+
EXPECT_TRUE(ToLambda);
6739+
}
6740+
67246741
TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
67256742
Decl *FromTU = getTuDecl(
67266743
R"(

0 commit comments

Comments
 (0)