P2615R0: Meaningful exports (original) (raw)
Audience: CWG
S. Davis Herring <>
July 1, 2022
Introduction
This paper addresses CWG2443 by forbidding applying export directly to certain meaningless declarations. Conversely, it also allows all kinds to appear with export {}. For consistency extern "C" is given the same restrictions when used directly.
Approach
The expansion of permissions here was originally proposed in P1766, which SG2 considered in Cologne but which has never been seen by EWG (perhaps because the rest of it was considered “accepted”). EWG did see the corresponding NB comment, but the vote was too close to progress it. The only apparent new information on the subject is that the wording does not specify a coherent set of restrictions (as opposed to finding the issues that some imagined might surface with the general direction). As such, this wording does make the change (largely by separating the relevant candidates in the declaration grammar); EWG approved the design change (while it had the form of core issue drafting).
Wording
Relative to N4910.
#[basic]
#[basic.pre]
Change paragraph 5:
Every name is introduced by a declaration, which is a
- name-declaration,
- block-name-declaration, or
[…]
#[basic.def]
Change bullet (2.20):
it is an explicit specialization ([temp.expl.spec]) whose name-declaration is not a definition.
#[basic.lookup.unqual]
Change paragraph 1:
[…]
[Note: A using-directive is exported if and only if it appears in a header unit. — _end note_]
#[stmt.dcl]
Change the grammar in paragraph 1:
declaration-statement:
block-name-declaration
block-special-declaration
#[dcl.dcl]
#[dcl.pre]
Change the grammar in paragraph 1:
[…]
declaration:
name-declaration
special-declarationname-declaration:
block-name-declaration
nodeclspec-function-declaration
function-definition
template-declaration
linkage-specification
namespace-definitionspecial-declaration:
block-special-declaration
deduction-guide
explicit-instantiation
explicit-specialization
export-declarationlinkage-specificationnamespace-definition
empty-declaration
attribute-declaration
module-import-declarationblock-name-declaration:
simple-declaration
asm-declaration
namespace-alias-definition
using-declaration
using-enum-declaration
using-directivestatic_assert-declaration
alias-declaration
opaque-enum-declarationblock-special-declaration:
asm-declaration
static_assert-declaration[…]
#[dcl.meaning.general]
Change paragraph 1:
A declarator contains exactly one declarator-id; it names the entity that is declared. If the unqualified-id occurring in a declarator-id is a template-id, the declarator shall appear in the name-declaration of a template-declaration ([temp.decls]), explicit-specialization ([temp.expl.spec]), or explicit-instantiation ([temp.explicit]).
[…]
#[dcl.link]
Change the grammar in paragraph 2:
linkage-specification:
externstring-literal{declaration-seq opt}externstring-literal name-declaration
Change paragraph 4:
A module-import-declaration shall not be directly contained in a linkage-specification.A module-import-declaration appearing in a linkage specification with other than C++ language linkage is conditionally-supported with implementation-defined semantics.
#[module.interface]
Change the grammar before paragraph 1:
export-declaration:
exportname-declarationexport{declaration-seq opt}
export-keyword module-import-declaration
Change paragraph 1:
An export-declaration shall inhabit a namespace scope and appear in the purview of a module interface unit. An export-declaration shall not appear directly or indirectly within an unnamed namespace or a private-module-fragment. An export-declaration has the declarative effects of its name-declaration, declaration-seq (if any), or module-import-declaration. The name-declaration of an export-declaration shall not declare a partial specialization ([temp.decls.general]). The
declaration ordeclaration-seq of an export-declaration shall not contain an export-declaration or module-import-declaration.[Note: An export-declaration does not establish a scope. — _end note_]
Change paragraph 3:
An exported declaration that is not a module-import-declaration shall declare at least one name.Ifthean exported declaration is not within a header unit, it shall not declare a name with internal linkage.
Change paragraph 4:
[…]
export module M; export namespace {} // error:
does not introduce any namesnamespace has internal linkageexport namespace {int a1; // error: export of name with internal linkage}namespace { export int a2; // error: export of name with internal linkage } export static int b; // error: b explicitly declared static export int f(); // OK export namespace N { } // OK export using namespace N; //error: does not declare a nameOK[…]
#[temp]
#[temp.explicit]
Change the grammar in paragraph 2:
explicit-instantiation:
externopttemplatename-declaration
Change paragraph 4:
If the explicit instantiation is for a class or member class, the elaborated-type-specifier in the name-declaration shall include a simple-template-id; otherwise, the name-declaration shall be a simple-declaration whose init-declarator-list comprises a single init-declarator that does not have an initializer. If the explicit instantiation is for a variable template specialization, the unqualified-id in the declarator shall be a simple-template-id. [Example:
[…]
— _end example_]
Change paragraph 5:
[…] If the name-declaration of the explicit instantiation names an implicitly-declared special member function ([special]), the program is ill-formed.
Change paragraph 6:
The name-declaration in an explicit-instantiation and the declaration produced by the corresponding substitution into the templated function, variable, or class are two declarations of the same entity.
[Note: […] — _end note_]
Despite its syntactic form, the name-declaration in an explicit-instantiation for a variable is not itself a definition and does not conflict with the definition instantiated by an explicit instantiation definition for that variable.
#[temp.expl.spec]
Change paragraph 2:
The declaration in an explicit-specialization shall not be an export-declaration. An explicit specialization shall not use a storage-class-specifier ([dcl.stc]) other than
thread_local.