This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


554. Definition of “declarative region” and “scope”

Section: 6.4  [basic.scope]     Status: CD6     Submitter: Gabriel Dos Reis     Date: 29 December 2005

[Accepted at the November, 2020 meeting as part of paper P1787R6 and moved to DR at the February, 2021 meeting.]

The various uses of the term “declarative region” throughout the Standard indicate that the term is intended to refer to the entire block, class, or namespace that contains a given declaration. For example, 6.4 [basic.scope] paragraph 2 says, in part:

[Example: in

    int j = 24;
    int main()
    {
        int i = j, j;
        j = 42;
    }

The declarative region of the first j includes the entire example... The declarative region of the second declaration of j (the j immediately before the semicolon) includes all the text between { and }...

However, the actual definition given for “declarative region” in 6.4 [basic.scope] paragraph 1 does not match this usage:

Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.

Because (except in class scope) a name cannot be used before it is declared, this definition contradicts the statement in the example and many other uses of the term throughout the Standard. As it stands, this definition is identical to that of the scope of a name.

The term “scope” is also misused. The scope of a declaration is defined in 6.4 [basic.scope] paragraph 1 as the region in which the name being declared is valid. However, there is frequent use of the phrase “the scope of a class,” not referring to the region in which the class's name is valid but to the declarative region of the class body, and similarly for namespaces, functions, exception handlers, etc. There is even a mention of looking up a name “in the scope of the complete postfix-expression” (_N4868_.6.5.6 [basic.lookup.classref] paragraph 3), which is the exact inverse of the scope of a declaration.

This terminology needs a thorough review to make it logically consistent. (Perhaps a discussion of the scope of template parameters could also be added to section 6.4 [basic.scope] at the same time, as all other kinds of scopes are described there.)

Proposed resolution (November, 2006):

  1. Change 6.4 [basic.scope] paragraph 1 as follows:

  2. Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity a statement, block, function declarator, function-definition, class, handler, template-declaration, template-parameter-list of a template template-parameter, or namespace. In general, each particular name is valid may be used as an unqualified name to refer to the entity of its declaration or to the label only within some possibly discontiguous portion of program text called its scope. To determine the scope of a declaration...
  3. Change 6.4 [basic.scope] paragraph 3 as follows:

  4. The names declared by a declaration are introduced into the scope in which the declaration occurs declarative region that directly encloses the declaration, except that declaration-statements, function parameter names in the declarator of a function-definition, exception-declarations (6.4.3 [basic.scope.block]), the presence of a friend specifier (11.8.4 [class.friend]), certain uses of the elaborated-type-specifier (9.2.9.4 [dcl.type.elab]), and using-directives (9.8.4 [namespace.udir]) alter this general behavior.
  5. Change 6.4.3 [basic.scope.block] paragraphs 1-3 and add a new paragraph 4 before the existing paragraph 4 as follows:

  6. A name declared in a block (8.4 [stmt.block]) is local to that block. Its potential scope begins at its point of declaration (6.4.2 [basic.scope.pdecl]) and ends at the end of its declarative region. The declarative region of a name declared in a declaration-statement is the directly enclosing block (8.4 [stmt.block]). Such a name is local to the block.

    The potential scope declarative region of a function parameter name (including one appearing in the declarator of a function-definition or in a lambda-parameter-declaration-clause) or of a function-local predefined variable in a function definition (9.5 [dcl.fct.def]) begins at its point of declaration. If the function has a function-try-block the potential scope of a parameter or of a function-local predefined variable ends at the end of the last associated handler, otherwise it ends at the end of the outermost block of the function definition. A parameter name is the entire function definition or lambda-expression. Such a name is local to the function definition and shall not be redeclared in the any outermost block of the function definition nor in the outermost block of any handler associated with a function-try-block function-body (including handlers of a function-try-block) or lambda-expression.

    The name in a catch exception-declaration The declarative region of a name declared in an exception-declaration is its entire handler. Such a name is local to the handler and shall not be redeclared in the outermost block of the handler.

    The potential scope of any local name begins at its point of declaration (6.4.2 [basic.scope.pdecl]) and ends at the end of its declarative region.

  7. Change _N4868_.6.4.5 [basic.funscope] as indicated:

  8. Labels (8.2 [stmt.label]) have function scope and may be used anywhere in the function in which they are declared except in members of local classes (11.6 [class.local]) of that function. Only labels have function scope.
  9. Change 8.8 [stmt.dcl] paragraph 1 as follows:

  10. A declaration statement introduces one or more new identifiers names into a block; it has the form

    [Note: If an identifier a name introduced by a declaration was previously declared in an outer block, the outer declaration is hidden for the remainder of the block, after which it resumes its force (_N4868_.6.4.10 [basic.scope.hiding]). end note]

[Drafting notes: This resolution deals almost exclusively with the unclear definition of “declarative region.” I've left the ambiguous use of “scope” alone for now. However sections 3.3.x all have headings reading “xxx scope,” but they don't mean the scope of a declaration but the different kinds of declarative regions and their effects on the scope of declarations contained therein. To me, it looks like most of 3.4 should refer to “declarative region” and not to “scope.”

The change to 6.7 fixes an “identifier” misuse (e.g., extern T operator+(T,T); at block scope introduces a name but not an identifier) and removes normative redundancy.]

Notes from the October, 2015 meeting:

This issue has been returned to "drafting" status to be reconciled with changes to the underlying existing text.