@@ -744,8 +744,13 @@ namespace clang {
744744 Error ImportOverriddenMethods (CXXMethodDecl *ToMethod,
745745 CXXMethodDecl *FromMethod);
746746
747- Expected<FunctionDecl *>
748- FindFunctionTemplateSpecialization (FunctionDecl *FromFD);
747+ Expected<FunctionDecl *> FindFunctionTemplateSpecialization (
748+ FunctionDecl *FromFD);
749+
750+ // Returns true if the given function has a placeholder return type and
751+ // that type is declared inside the body of the function.
752+ // E.g. auto f() { struct X{}; return X(); }
753+ bool hasReturnTypeDeclaredInside (FunctionDecl *D);
749754 };
750755
751756template <typename InContainerTy>
@@ -3897,6 +3902,30 @@ class IsTypeDeclaredInsideVisitor
38973902};
38983903} // namespace
38993904
3905+ // / This function checks if the given function has a return type that contains
3906+ // / a reference (in any way) to a declaration inside the same function.
3907+ bool ASTNodeImporter::hasReturnTypeDeclaredInside (FunctionDecl *D) {
3908+ QualType FromTy = D->getType ();
3909+ const auto *FromFPT = FromTy->getAs <FunctionProtoType>();
3910+ assert (FromFPT && " Must be called on FunctionProtoType" );
3911+
3912+ auto IsCXX11Lambda = [&]() {
3913+ if (Importer.FromContext .getLangOpts ().CPlusPlus14 ) // C++14 or later
3914+ return false ;
3915+
3916+ return isLambdaMethod (D);
3917+ };
3918+
3919+ QualType RetT = FromFPT->getReturnType ();
3920+ if (isa<AutoType>(RetT.getTypePtr ()) || IsCXX11Lambda ()) {
3921+ FunctionDecl *Def = D->getDefinition ();
3922+ IsTypeDeclaredInsideVisitor Visitor (Def ? Def : D);
3923+ return Visitor.CheckType (RetT);
3924+ }
3925+
3926+ return false ;
3927+ }
3928+
39003929ExplicitSpecifier
39013930ASTNodeImporter::importExplicitSpecifier (Error &Err, ExplicitSpecifier ESpec) {
39023931 Expr *ExplicitExpr = ESpec.getExpr ();
@@ -4045,8 +4074,9 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
40454074 // To avoid an infinite recursion when importing, create the FunctionDecl
40464075 // with a simplified return type.
40474076 // Reuse this approach for auto return types declared as typenames from
4048- // template params, tracked in FunctionReturnTypeCycleDetector.
4049- if (Importer.FunctionReturnTypeCycleDetector ->isCycle (D)) {
4077+ // template pamams, tracked in FunctionReturnTypeCycleDetector.
4078+ if (hasReturnTypeDeclaredInside (D) ||
4079+ Importer.FunctionReturnTypeCycleDetector ->isCycle (D)) {
40504080 FromReturnTy = Importer.getFromContext ().VoidTy ;
40514081 UsedDifferentProtoType = true ;
40524082 }
0 commit comments