Files
2025-10-25 03:02:53 +03:00

22 KiB
Raw Permalink Blame History

[basic.link]

6 Basics [basic]

1

#

A program consists of one or more translation units linked together.

A translation unit consists of a sequence of declarations.

translation-unit:
declaration-seqopt
global-module-fragmentopt module-declaration declaration-seqopt private-module-fragmentopt

2

#

A name hasexternal linkage,module linkage,internal linkage, orno linkage, as determined by the rules below.

[Note 1:

All declarations of an entity with a name with internal linkage appear in the same translation unit.

All declarations of an entity with module linkage are attached to the same module.

— end note]

3

#

The name of an entity that belongs to a namespace scope has internal linkage if it is the name of

a variable, variable template, function, or function template that is explicitly declared static; or

a non-template variable of non-volatile const-qualified type, unless

it is declared in the purview of a module interface unit (outside the private-module-fragment, if any) or module partition, or

it is explicitly declared extern, or

it is inline, or

it was previously declared and the prior declaration did not have internal linkage; or

a data member of an anonymous union.

[Note 2:

An instantiated variable template that has const-qualified type can have external or module linkage, even if not declared extern.

— end note]

4

#

An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage.

All other namespaces have external linkage.

The name of an entity that belongs to a namespace scope, that has not been given internal linkage above, and that is the name of

a variable; or

a function; or

a named class ([class.pre]), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes ([dcl.typedef]); or

a named enumeration, or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes ([dcl.typedef]); or

an unnamed enumeration that has an enumerator as a name for linkage purposes ([dcl.enum]); or

a template

has its linkage determined as follows:

if the entity is a function or function template first declared in a friend declaration and that declaration is a definition and the enclosing class is defined within an export-declaration, the name has the same linkage, if any, as the name of the enclosing class ([class.friend]);

otherwise,if the entity is a function or function template declared in a friend declaration and a corresponding non-friend declaration is reachable, the name has the linkage determined from that prior declaration,

otherwise, if the enclosing namespace has internal linkage, the name has internal linkage;

otherwise, if the declaration of the name is attached to a named module ([module.unit]) and is not exported ([module.interface]), the name has module linkage;

otherwise, the name has external linkage.

5

#

In addition, a member function, a static data member, a named class or enumeration that inhabits a class scope, or an unnamed class or enumeration defined in a typedef declaration that inhabits a class scope such that the class or enumeration has the typedef name for linkage purposes ([dcl.typedef]), has the same linkage, if any, as the name of the class of which it is a member.

6

#

[Example 1: static void f();extern "C" void h();static int i = 0; // #1void q() {extern void f(); // internal linkageextern void g(); // ::g, external linkageextern void h(); // C language linkageint i; // #2: i has no linkage{extern void f(); // internal linkageextern int i; // #3: internal linkage}}

Even though the declaration at line #2 hides the declaration at line #1, the declaration at line #3 still redeclares #1 and receives internal linkage.

— end example]

7

#

Names not covered by these rules have no linkage.

Moreover, except as noted, a name declared at block scope has no linkage.

8

#

Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]), they correspond ([basic.scope.scope]), have the same target scope that is not a function or template parameter scope, neither is a name-independent declaration, and either

they appear in the same translation unit, or

they both declare type aliases or namespace aliases that have the same underlying entity, or

they both declare names with module linkage and are attached to the same module, or

they both declare names with external linkage.

[Note 3:

There are other circumstances in which declarations declare the same entity ([dcl.link], [temp.type], [temp.spec.partial]).

— end note]

9

#

If a declaration H that declares a name with internal linkage precedes a declaration D in another translation unit U and would declare the same entity as D if it appeared in U, the program is ill-formed.

[Note 4:

Such an H can appear only in a header unit.

— end note]

10

#

If two declarations of an entity are attached to different modules, the program is ill-formed; no diagnostic is required if neither is reachable from the other.

[Example 2:

"decls.h":int f(); // #1, attached to the global moduleint g(); // #2, attached to the global module

Module interface of M:module;#include "decls.h"export module M;export using ::f; // OK, does not declare an entity, exports #1int g(); // error: matches #2, but attached to Mexport int h(); // #3export int k(); // #4

Other translation unit:import M;static int h(); // error: matches #3int k(); // error: matches #4 — end example]

As a consequence of these rules, all declarations of an entity are attached to the same module; the entity is said to be attached to that module.

11

#

For any two declarations of an entity E:

  • (11.1)

    If one declares E to be a variable or function, the other shall declare E as one of the same type.

  • (11.2)

    If one declares E to be an enumerator, the other shall do so.

  • (11.3)

    If one declares E to be a namespace, the other shall do so.

  • (11.4)

    If one declares E to be a type, the other shall declare E to be a type of the same kind ([dcl.type.elab]).

  • (11.5)

    If one declares E to be a class template, the other shall do so with the same kind and an equivalent template-head ([temp.over.link]). [Note 5: The declarations can supply different default template arguments. — end note]

  • (11.6)

    If one declares E to be a function template or a (partial specialization of a) variable template, the other shall declare E to be one with an equivalent template-head and type.

  • (11.7)

    If one declares E to be an alias template, the other shall declare E to be one with an equivalent template-head and defining-type-id.

  • (11.8)

    If one declares E to be a concept, the other shall do so.

Types are compared after all adjustments of types (during which typedefs ([dcl.typedef]) are replaced by their definitions); declarations for an array object can specify array types that differ by the presence or absence of a major array bound ([dcl.array]).

No diagnostic is required if neither declaration is reachable from the other.

[Example 3: int f(int x, int x); // error: different entities for xvoid g(); // #1void g(int); // OK, different entity from #1int g(); // error: same entity as #1 with different typevoid h(); // #2namespace h {} // error: same entity as #2, but not a function — end example]

12

#

[Note 6:

Linkage to non-C++ declarations can be achieved using alinkage-specification ([dcl.link]).

— end note]

13

#

A declaration D names an entity E if

D contains a lambda-expression whose closure type is E,

D contains a reflect-expression or a splice-specifier that, respectively, represents or designates E,

D is an injected declaration ([expr.const]) whose characteristic sequence contains a reflection that represents a data member description (T, N, A, W, NUA) ([class.mem.general]) for which T is E,

E is not a function or function template and D contains anid-expression,type-specifier,nested-name-specifier,template-name, orconcept-name denoting E, or

E is a function or function template andD contains an expression that names E ([basic.def.odr]) or an id-expression that refers to a set of overloads that contains E. [Note 7: Non-dependent names in an instantiated declaration do not refer to a set of overloads ([temp.res]). — end note]

14

#

A declaration is an exposure if it either names a TU-local entity (defined below), ignoring

the function-body for a non-inline function or function template (but not the deduced return type for a (possibly instantiated) definition of a function with a declared return type that uses a placeholder type ([dcl.spec.auto])),

the initializer for a variable or variable template (but not the variable's type),

friend declarations in a class definition, and

any reference to a non-volatile const object or reference with internal or no linkage initialized with a constant expression that is not an odr-use ([basic.def.odr]),

or defines a constexpr variable initialized to a TU-local value (defined below).

[Note 8:

An inline function template can be an exposure even though certain explicit specializations of it would be usable in other translation units.

— end note]

15

#

An entity is TU-local if it is

a type, type alias, namespace, namespace alias, function, variable, or template that

has a name with internal linkage, or

does not have a name with linkage and is declared, or introduced by a lambda-expression, within the definition of a TU-local entity,

a type with no name that is defined outside aclass-specifier, function body, orinitializer or is introduced by a defining-type-specifier that is used to declare only TU-local entities,

a specialization of a TU-local template,

a specialization of a template with any TU-local template argument, or

a specialization of a template whose (possibly instantiated) declaration is an exposure. [Note 9: A specialization can be produced by implicit or explicit instantiation. — end note]

16

#

A value or object is TU-local if either

it is of TU-local type,

it is, or is a pointer to, a TU-local function or the object associated with a TU-local variable,

it is an object of class or array type and any of its subobjects or any of the objects or functions to which its non-static data members of reference type refer is TU-local and is usable in constant expressions, or

it is a reflection value ([basic.fundamental]) that represents

an entity, value, or object that is TU-local,

a direct base class relationship (D, B) ([class.derived.general]) for which either D or B is TU-local, or

a data member description (T, N, A, W, NUA) ([class.mem.general]) for which T is TU-local.

17

#

If a (possibly instantiated) declaration of, or a deduction guide for, a non-TU-local entity in a module interface unit (outside the private-module-fragment, if any) or module partition ([module.unit]) is an exposure, the program is ill-formed.

Such a declaration in any other context is deprecated ([depr.local]).

18

#

If a declaration that appears in one translation unit names a TU-local entity declared in another translation unit that is not a header unit, the program is ill-formed.

A declaration instantiated for a template specialization ([temp.spec]) appears at the point of instantiation of the specialization ([temp.point]).

19

#

[Example 4:

Translation unit #1:export module A;static void f() {}inline void it() { f(); } // error: is an exposure of fstatic inline void its() { f(); } // OKtemplate void g() { its(); } // OKtemplate void g<0>();

decltype(f) *fp; // error: f (though not its type) is TU-localauto &fr = f; // OKconstexpr auto &fr2 = fr; // error: is an exposure of fconstexpr static auto fp2 = fr; // OKstruct S { void (&ref)(); } s{f}; // OK, value is TU-localconstexpr extern struct W { S &s; } wrap{s}; // OK, value is not TU-localstatic auto x = []{f();}; // OKauto x2 = x; // error: the closure type is TU-localint y = ([]{f();}(),0); // error: the closure type is not TU-localint y2 = (x,0); // OKnamespace N {struct A {}; void adl(A); static void adl(int);}void adl(double);

inline void h(auto x) { adl(x); } // OK, but certain specializations are exposuresconstexpr std::meta::info r1 = ^^g<0>; // OKnamespace N2 {static constexpr std::meta::info r2 = ^^g<1>; // OK, r2 is TU-local}constexpr std::meta::info r3 = ^^f; // error: r3 is an exposure of fconstexpr auto ctx = std::meta::access_context::current();constexpr std::meta::info r4 = std::meta::members_of(^^N2, ctx)[0]; // error: r4 is an exposure of N2::r2

Translation unit #2:module A;void other() { g<0>(); // OK, specialization is explicitly instantiated g<1>(); // error: instantiation uses TU-local its h(N::A{}); // error: overload set contains TU-local N::adl(int) h(0); // OK, calls adl(double) adl(N::A{}); // OK; N::adl(int) not found, calls N::adl(N::A) fr(); // OK, calls fconstexpr auto ptr = fr; // error: fr is not usable in constant expressions here} — end example]