Clang error: non-templated function cannot have a requires clause (err_constrained_non_templated_function)

From emmtrix Wiki
Jump to navigation Jump to search
Text error: non-templated function cannot have a requires clause (since 15.0)
Type Error
Category Semantic Issue (since 15.0)
Internal Id err_constrained_non_templated_function (since 15.0)
Internal Message non-templated function cannot have a requires clause (since 15.0)
Regular Expression (?:error|fatal error)\: non\-templated function cannot have a requires clause
First Commit 2021-05-09 cb08f4aa4467 Support warn_unused_result on typedefs

Description

The error is issued by the Clang compiler when a function that is not a template has a requires clause associated with it. In C++20, the introduction of concepts and constraints allows for the specification of requirements that templates must satisfy for successful instantiation. A requires clause, which is part of this feature set, is used to specify such requirements. However, this mechanism is only applicable to templated entities, such as function templates, class templates, and templated member functions of class templates.

Non-templated functions, lacking the parameterization that templates provide, do not support the addition of a requires clause. Attempting to compile a non-templated function declaration that includes a requires clause results in this error. The error indicates a misunderstanding or incorrect use of the requires clause within the context of the C++20 standard.

The consequence of this error is that the compilation process identifies the specific function declaration as invalid due to the inappropriate use of a requires clause. This serves as a mechanism to enforce the correct usage of C++20 concepts and constraints, ensuring that requires clauses are only applied to templated entities which can meaningfully be constrained by such requirements.

This error helps maintain the semantic integrity of C++ programs by ensuring that the features introduced with C++20 are used in a manner consistent with the language's specification, particularly in the context of templating and the application of constraints to templated entities.

 
AI Generated

Example

In the following example, an attempt is made to define a function f with a requires clause. However, f is not a template function, but rather a plain function with no template parameters. The requires clause is intended to be used with templates to specify constraints that template arguments must satisfy. Since f is not a template, the inclusion of a requires clause is incorrect according to the C++20 standard. This misuse results in a compilation error as indicated by the Clang compiler, highlighting that a non-templated function cannot have a requires clause. The error message clearly states the issue, enforcing the rule that requires clauses are solely applicable to templated entities.  
AI Generated


Flags -xc++ -std=c++20

[Try out in Compiler Explorer]

Source
int f() requires true { return 0; }
// f has a requires clause but is not a template.
Compiler Output
<source>:1:18: error: non-templated function cannot have a requires clause


Clang Internals (17.0.6)

Git Commit Message

Support warn_unused_result on typedefs

While it's not as robust as using the attribute on enums/classes (the
type information may be lost through a function pointer, a declaration
or use of the underlying type without using the typedef, etc) but I
think there's still value in being able to attribute a typedef and have
all return types written with that typedef pick up the
warn_unused_result behavior.

Specifically I'd like to be able to annotate LLVMErrorRef (a wrapper for
llvm::Error used in the C API - the underlying type is a raw pointer, so
it can't be attributed itself) to reduce the chance of unhandled errors.

Differential Revision: https://reviews.llvm.org/D102122

Used in Clang Sources

This section lists all occurrences of the diagnostic within the Clang's codebase. For each occurrence, an auto-extracted snipped from the source code is listed including key elements like control structures, functions, or classes. It should illustrate the conditions under which the diagnostic is activated.

clang/lib/Sema/SemaDecl.cpp (line 11983)

/// Perform semantic checking of a new function declaration.
///
/// Performs semantic analysis of the new function declaration
/// NewFD. This routine performs all semantic checking that does not
/// require the actual declarator involved in the declaration, and is
/// used both for the declaration of functions as they are parsed
/// (called via ActOnDeclarator) and for the declaration of functions
/// that have been instantiated via C++ template instantiation (called
/// via InstantiateDecl).
///
/// \param IsMemberSpecialization whether this new function declaration is
/// a member specialization (that replaces any definition provided by the
/// previous declaration).
///
/// This sets NewFD->isInvalidDecl() to true if there was an error.
///
/// \returns true if the function declaration is a redeclaration.
bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsMemberSpecialization, bool DeclIsDefn) {
  // ...
  if (getLangOpts().CPlusPlus) {
    // ...
    // C++20: dcl.decl.general p4:
    // The optional requires-clause ([temp.pre]) in an init-declarator or
    // member-declarator shall be present only if the declarator declares a
    // templated function ([dcl.fct]).
    if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
      // ...
      if (!NewFD->getDescribedFunctionTemplate() && // -a template
        // ...
        Diag(TRC->getBeginLoc(), diag::err_constrained_non_templated_function);

clang/lib/Sema/SemaLambda.cpp (line 1414)

void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Declarator &ParamInfo, const DeclSpec &DS) {
  // ...
  // C++20: dcl.decl.general p4:
  // The optional requires-clause ([temp.pre]) in an init-declarator or
  // member-declarator shall be present only if the declarator declares a
  // templated function ([dcl.fct]).
  if (Expr *TRC = Method->getTrailingRequiresClause()) {
    // ...
    // Note: we only have to check if this is defined in a template entity, OR
    // if we are a template, since the rest don't apply. The requires clause
    // applies to the call operator, which we already know is a member function,
    // AND defined.
    if (!Method->getDescribedFunctionTemplate() && !Method->isTemplated()) {
      Diag(TRC->getBeginLoc(), diag::err_constrained_non_templated_function);

Triggered in Clang Tests

This section lists all internal Clang test cases that trigger the diagnostic.

clang/test/CXX/dcl/dcl.decl/p3.cpp

  • clang/test/CXX/dcl/dcl.decl/p3.cpp:11:34: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:12:42: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:13:53: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:15:35: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:16:31: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:18:30: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:20:23: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:23:17: error: non-templated function cannot have a requires clause
  • clang/test/CXX/dcl/dcl.decl/p3.cpp:23:35: error: non-templated function cannot have a requires clause