@@ -10119,23 +10119,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10119
10119
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
10120
10120
}
10121
10121
10122
- if (getLangOpts().CPlusPlus14 &&
10123
- (NewFD->isDependentContext() ||
10124
- (isFriend && CurContext->isDependentContext())) &&
10125
- NewFD->getReturnType()->isUndeducedType()) {
10126
- // If the function template is referenced directly (for instance, as a
10127
- // member of the current instantiation), pretend it has a dependent type.
10128
- // This is not really justified by the standard, but is the only sane
10129
- // thing to do.
10130
- // FIXME: For a friend function, we have not marked the function as being
10131
- // a friend yet, so 'isDependentContext' on the FD doesn't work.
10132
- const FunctionProtoType *FPT =
10133
- NewFD->getType()->castAs<FunctionProtoType>();
10134
- QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
10135
- NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
10136
- FPT->getExtProtoInfo()));
10137
- }
10138
-
10139
10122
// C++ [dcl.fct.spec]p3:
10140
10123
// The inline specifier shall not appear on a block scope function
10141
10124
// declaration.
@@ -12107,6 +12090,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
12107
12090
12108
12091
CheckConstPureAttributesUsage(*this, NewFD);
12109
12092
12093
+ // C++23 [dcl.spec.auto.general]p12:
12094
+ // Return type deduction for a templated function with a placeholder in its
12095
+ // declared type occurs when the definition is instantiated even if the
12096
+ // function body contains a return statement with a non-type-dependent
12097
+ // operand.
12098
+ //
12099
+ // C++23 [temp.dep.expr]p3:
12100
+ // An id-expression is type-dependent if it is a template-id that is not a
12101
+ // concept-id and is dependent; or if its terminal name is:
12102
+ // - [...]
12103
+ // - associated by name lookup with one or more declarations of member
12104
+ // functions of a class that is the current instantiation declared with a
12105
+ // return type that contains a placeholder type,
12106
+ // - [...]
12107
+ //
12108
+ // If this is a templated function with a placeholder in its return type,
12109
+ // make the placeholder type dependent since it won't be deduced until the
12110
+ // definition is instantiated. We do this here because it needs to happen
12111
+ // for implicitly instantiated member functions/member function templates.
12112
+ if (getLangOpts().CPlusPlus14 &&
12113
+ (NewFD->isDependentContext() &&
12114
+ NewFD->getReturnType()->isUndeducedType())) {
12115
+ const FunctionProtoType *FPT =
12116
+ NewFD->getType()->castAs<FunctionProtoType>();
12117
+ QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType());
12118
+ NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(),
12119
+ FPT->getExtProtoInfo()));
12120
+ }
12121
+
12110
12122
// C++11 [dcl.constexpr]p8:
12111
12123
// A constexpr specifier for a non-static member function that is not
12112
12124
// a constructor declares that member function to be const.
0 commit comments