@@ -1287,6 +1287,44 @@ bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(TypedefNameDecl *Found,
12871287
12881288using namespace clang ;
12891289
1290+ class ASTImporter ::FunctionReturnTypeDeclCycleDetector {
1291+ public:
1292+ class ScopedReturnTypeImport {
1293+ public:
1294+ // Do not track cycles on D == nullptr.
1295+ ScopedReturnTypeImport (FunctionReturnTypeDeclCycleDetector &owner,
1296+ const Decl *D)
1297+ : CycleDetector(owner), D(D) {
1298+ if (D)
1299+ CycleDetector.FunctionReturnTypeDeclCycles .insert (D);
1300+ }
1301+ ~ScopedReturnTypeImport () {
1302+ if (D)
1303+ CycleDetector.FunctionReturnTypeDeclCycles .erase (D);
1304+ }
1305+ ScopedReturnTypeImport (const ScopedReturnTypeImport &) = delete ;
1306+ ScopedReturnTypeImport &operator =(const ScopedReturnTypeImport &) = delete ;
1307+
1308+ private:
1309+ FunctionReturnTypeDeclCycleDetector &CycleDetector;
1310+ const Decl *D;
1311+ };
1312+
1313+ ScopedReturnTypeImport DetectImportCycles (const Decl *D) {
1314+ if (!IsCycle (D))
1315+ return ScopedReturnTypeImport (*this , D);
1316+ return ScopedReturnTypeImport (*this , nullptr );
1317+ }
1318+
1319+ bool IsCycle (const Decl *D) const {
1320+ return FunctionReturnTypeDeclCycles.find (D) !=
1321+ FunctionReturnTypeDeclCycles.end ();
1322+ }
1323+
1324+ private:
1325+ llvm::DenseSet<const Decl *> FunctionReturnTypeDeclCycles;
1326+ };
1327+
12901328ExpectedType ASTNodeImporter::VisitType (const Type *T) {
12911329 Importer.FromDiag (SourceLocation (), diag::err_unsupported_ast_node)
12921330 << T->getTypeClassName ();
@@ -4035,8 +4073,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
40354073 // E.g.: auto foo() { struct X{}; return X(); }
40364074 // To avoid an infinite recursion when importing, create the FunctionDecl
40374075 // with a simplified return type.
4076+ // Reuse this approach for auto return types declared as typenames from
4077+ // template pamams, tracked in FunctionReturnTypeCycleDetector.
40384078 if (hasReturnTypeDeclaredInside (D) ||
4039- Importer.DeclTypeCycles . find (D) != Importer. DeclTypeCycles . end ( )) {
4079+ Importer.FunctionReturnTypeCycleDetector -> IsCycle (D )) {
40404080 FromReturnTy = Importer.getFromContext ().VoidTy ;
40414081 UsedDifferentProtoType = true ;
40424082 }
@@ -4059,11 +4099,9 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
40594099 }
40604100
40614101 Error Err = Error::success ();
4062- if (!UsedDifferentProtoType)
4063- Importer.DeclTypeCycles . insert (D);
4102+ auto ScopedReturnTypeDeclCycleDetector =
4103+ Importer.FunctionReturnTypeCycleDetector -> DetectImportCycles (D);
40644104 auto T = importChecked (Err, FromTy);
4065- if (!UsedDifferentProtoType)
4066- Importer.DeclTypeCycles .erase (D);
40674105 auto TInfo = importChecked (Err, FromTSI);
40684106 auto ToInnerLocStart = importChecked (Err, D->getInnerLocStart ());
40694107 auto ToEndLoc = importChecked (Err, D->getEndLoc ());
@@ -9299,7 +9337,9 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
92999337 std::shared_ptr<ASTImporterSharedState> SharedState)
93009338 : SharedState(SharedState), ToContext(ToContext), FromContext(FromContext),
93019339 ToFileManager (ToFileManager), FromFileManager(FromFileManager),
9302- Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative) {
9340+ Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative),
9341+ FunctionReturnTypeCycleDetector(
9342+ std::make_unique<FunctionReturnTypeDeclCycleDetector>()) {
93039343
93049344 // Create a default state without the lookup table: LLDB case.
93059345 if (!SharedState) {
0 commit comments