@@ -10440,6 +10440,60 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10440
10440
diag::ext_operator_new_delete_declared_inline)
10441
10441
<< NewFD->getDeclName();
10442
10442
10443
+ if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
10444
+ // C++20 [dcl.decl.general]p4:
10445
+ // The optional requires-clause in an init-declarator or
10446
+ // member-declarator shall be present only if the declarator declares a
10447
+ // templated function.
10448
+ //
10449
+ // C++20 [temp.pre]p8:
10450
+ // An entity is templated if it is
10451
+ // - a template,
10452
+ // - an entity defined or created in a templated entity,
10453
+ // - a member of a templated entity,
10454
+ // - an enumerator for an enumeration that is a templated entity, or
10455
+ // - the closure type of a lambda-expression appearing in the
10456
+ // declaration of a templated entity.
10457
+ //
10458
+ // [Note 6: A local class, a local or block variable, or a friend
10459
+ // function defined in a templated entity is a templated entity.
10460
+ // — end note]
10461
+ //
10462
+ // A templated function is a function template or a function that is
10463
+ // templated. A templated class is a class template or a class that is
10464
+ // templated. A templated variable is a variable template or a variable
10465
+ // that is templated.
10466
+ if (!FunctionTemplate) {
10467
+ if (isFunctionTemplateSpecialization || isMemberSpecialization) {
10468
+ // C++ [temp.expl.spec]p8 (proposed resolution for CWG2847):
10469
+ // An explicit specialization shall not have a trailing
10470
+ // requires-clause unless it declares a function template.
10471
+ //
10472
+ // Since a friend function template specialization cannot be
10473
+ // definition, and since a non-template friend declaration with a
10474
+ // trailing requires-clause must be a definition, we diagnose
10475
+ // friend function template specializations with trailing
10476
+ // requires-clauses on the same path as explicit specializations
10477
+ // even though they aren't necessarily prohibited by the same
10478
+ // language rule.
10479
+ Diag(TRC->getBeginLoc(), diag::err_non_temp_spec_requires_clause)
10480
+ << isFriend;
10481
+ } else if (isFriend && NewFD->isTemplated() &&
10482
+ !D.isFunctionDefinition()) {
10483
+ // C++ [temp.friend]p9:
10484
+ // A non-template friend declaration with a requires-clause shall be
10485
+ // a definition.
10486
+ Diag(NewFD->getBeginLoc(),
10487
+ diag::err_non_temp_friend_decl_with_requires_clause_must_be_def);
10488
+ NewFD->setInvalidDecl();
10489
+ } else if (!NewFD->isTemplated() ||
10490
+ !(isa<CXXMethodDecl>(NewFD) || D.isFunctionDefinition())) {
10491
+ Diag(TRC->getBeginLoc(),
10492
+ diag::err_constrained_non_templated_function);
10493
+ }
10494
+ }
10495
+ }
10496
+
10443
10497
// We do not add HD attributes to specializations here because
10444
10498
// they may have different constexpr-ness compared to their
10445
10499
// templates and, after maybeAddCUDAHostDeviceAttrs() is applied,
@@ -12063,55 +12117,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
12063
12117
checkThisInStaticMemberFunctionType(Method);
12064
12118
}
12065
12119
12066
- if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
12067
- // C++20: dcl.decl.general p4:
12068
- // The optional requires-clause ([temp.pre]) in an init-declarator or
12069
- // member-declarator shall be present only if the declarator declares a
12070
- // templated function ([dcl.fct]).
12071
- //
12072
- // [temp.pre]/8:
12073
- // An entity is templated if it is
12074
- // - a template,
12075
- // - an entity defined ([basic.def]) or created ([class.temporary]) in a
12076
- // templated entity,
12077
- // - a member of a templated entity,
12078
- // - an enumerator for an enumeration that is a templated entity, or
12079
- // - the closure type of a lambda-expression ([expr.prim.lambda.closure])
12080
- // appearing in the declaration of a templated entity. [Note 6: A local
12081
- // class, a local or block variable, or a friend function defined in a
12082
- // templated entity is a templated entity. — end note]
12083
- //
12084
- // A templated function is a function template or a function that is
12085
- // templated. A templated class is a class template or a class that is
12086
- // templated. A templated variable is a variable template or a variable
12087
- // that is templated.
12088
-
12089
- bool IsTemplate = NewFD->getDescribedFunctionTemplate();
12090
- bool IsFriend = NewFD->getFriendObjectKind();
12091
- if (!IsTemplate && // -a template
12092
- // defined... in a templated entity
12093
- !(DeclIsDefn && NewFD->isTemplated()) &&
12094
- // a member of a templated entity
12095
- !(isa<CXXMethodDecl>(NewFD) && NewFD->isTemplated()) &&
12096
- // Don't complain about instantiations, they've already had these
12097
- // rules + others enforced.
12098
- !NewFD->isTemplateInstantiation() &&
12099
- // If the function violates [temp.friend]p9 because it is missing
12100
- // a definition, and adding a definition would make it templated,
12101
- // then let that error take precedence.
12102
- !(!DeclIsDefn && IsFriend && NewFD->isTemplated())) {
12103
- Diag(TRC->getBeginLoc(), diag::err_constrained_non_templated_function);
12104
- } else if (!DeclIsDefn && !IsTemplate && IsFriend &&
12105
- !NewFD->isTemplateInstantiation()) {
12106
- // C++ [temp.friend]p9:
12107
- // A non-template friend declaration with a requires-clause shall be a
12108
- // definition.
12109
- Diag(NewFD->getBeginLoc(),
12110
- diag::err_non_temp_friend_decl_with_requires_clause_must_be_def);
12111
- NewFD->setInvalidDecl();
12112
- }
12113
- }
12114
-
12115
12120
if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
12116
12121
ActOnConversionDeclarator(Conversion);
12117
12122
0 commit comments