12

GCC, clang and VS2013 compile the snippet below:

namespace A{}
int main()
{
    int A;
}

However [namespace.alias]/4 says the following:

A namespace-name or namespace-alias shall not be declared as the name of any other entity in the same declarative region.

and

[basic.scope.declarative]/1 says:

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.

That is, I have the impression that the int variable in main() cannot have the same name as the namespace A. Observe that the example in [basic.scope.declarative]/2 seems to corroborate this when it says

The declarative region of the first j includes the entire example.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
Leon
  • 868
  • 4
  • 12
  • I don't think they are in the same declarative region. See http://stackoverflow.com/questions/23630201/whats-the-difference-between-declarative-region-and-scope and http://stackoverflow.com/questions/17376399/c11-3-3-1p4-declarations-in-same-declarative-region – dwcanillas Apr 21 '15 at 14:29
  • 1
    `j` is outside main in that example. Try putting your `int A;` at global scope to compare. – Mat Apr 21 '15 at 14:29
  • For what it's worth, **[namespace.alias]/4** paragraph no longer exists in C++14. – Igor Tandetnik Apr 21 '15 at 14:30
  • @IgorTandetnik N4140 has it. – Leon Apr 21 '15 at 14:37
  • See also "**[basic.lookup.udir]/1** In a *using-directive* or *namespace-alias-definition*, during the lookup for a *namespace-name* or for a name in a *nested-name-specifier* only namespace names are considered." If namespace names could never be hidden, this paragraph (which is already present in C++03) would be pointless. – Igor Tandetnik Apr 21 '15 at 14:39
  • `N4140 has it` but N4296 doesn't. – Igor Tandetnik Apr 21 '15 at 14:40
  • @IgorTandetnik I was under the impression N4296 was post-C++14 – Angew is no longer proud of SO Apr 21 '15 at 14:41
  • @IgorTandetnik N4296 is not C++14. See this: http://stackoverflow.com/a/29115882/1042389 – Leon Apr 21 '15 at 14:43
  • This could be. In any case, that paragraph appears to be in error and was subsequently removed. It doesn't make much sense to carve a special exception in name lookup rules for namespace names. There's also "**[basic.lookup]/1** The name lookup rules apply uniformly to all names (including ... *namespace-names*...)" – Igor Tandetnik Apr 21 '15 at 14:46
  • @IgorTandetnik see [dr 1795](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1795) – Shafik Yaghmour Apr 21 '15 at 14:46
  • @Angew the wording was a defect and that is why it was removed, see y answer below – Shafik Yaghmour Apr 21 '15 at 15:09

4 Answers4

6

From [basic.scope.declarative], the definition of a "declarative region" is:

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.

The restriction is, emphasis mine:

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name
— they shall all refer to the same entity, or all refer to functions and function templates

Going back to your example. If we annotate the two declarative regions, we have:

namespace A{}    + region #1
                 |
int main()       |           +
{                |           |
    int A;       |           | region #2               
                 |           |
}                +           +

The declarative regions for namespace A (#1) and int A (#2) are different (the second is a strict subset of the first, but that doesn't matter). Since they are different, the restriction on having a single name doesn't apply. There is one single A in #2 and one single A in #1.

If we, however, moved int A to be in the same declarative region:

namespace A {}     +   the only declarative region. even though the
int A;             |   potential scope of "int A" does not include
                   |   "namespace A", the declarative region does.
int main() {       |   The intent of this is expressed in the example
                   |   in [basic.scope.declarative]/2:
                   |        int main() {
                   |            int i = j, j;
                   |            j = 42;
                   |        }
                   |
                   |   "The declarative region of the [j] includes all 
                   |    the text between { and }, but its potential scope
}                  +    excludes the declaration of i."

That would violate [basic.scope.declarative]/4, and both gcc and clang correctly reject the code with:

error: redefinition of 'A' as different kind of symbol

Note that as Vaughn Cato points out, there is an active defect report about the wording for declarative region.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Wouldn't a strict reading of this imply that even the second example is valid, since the region for which int A is valid is one line less than the region for which namespace A is valid? – Vaughn Cato Apr 21 '15 at 15:10
  • 1
    @VaughnCato The scope is one line less, but the declarative region is the same. I believe that's the intended meaning, at the least. – Angew is no longer proud of SO Apr 21 '15 at 15:11
  • @VaughnCato The example indicates that the intent is the declarative region is the same: "The declarative region of the second declaration of `j` (the `j` immediately before the semicolon) includes all the text between `{` and `}`, but its potential scope excludes the declaration of i". The declarative region includes the declaration of `i`, even though its scope does not. – Barry Apr 21 '15 at 15:13
  • @Barry `Since they are different, the restriction on having a single name doesn't apply` I can't see how this could be inferred from the **largest part** you highlighted above. – Leon Apr 21 '15 at 15:20
  • @Angew: I agree the examples indicate that is the intent, but it seems to be inconsistent with the definition, or perhaps the definition of "valid" is not what I would expect. It seems like if the definition of "declarative region" is correct, it would imply that the local j is valid before the name appears within the braces. – Vaughn Cato Apr 21 '15 at 15:21
  • @LeonTrotski Yeah makes more sense to emphasis **single declarative region**. Changed that. – Barry Apr 21 '15 at 15:23
  • @Barry `[ Note: A namespace name or a class template name must be unique in its declarative region (7.3.2, Clause 14).—end note ]` in [basic.scope.declarative]/4. – Leon Apr 21 '15 at 15:25
  • @LeonTrotski Yes is exactly the same as [basic.scope.declarative]/4... except what I quoted isn't a note. `namespace A` and `int A` are in separate declarative regions, so uniqueness isn't violated. – Barry Apr 21 '15 at 15:30
  • Turns out there's already a defect report on the definition of "declarative region" being inconsistent: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#554. It's been there since 2006, but just has never been fixed. – Vaughn Cato Apr 21 '15 at 15:53
2

The first quote you mention [namespace.alias]/4 was actually there to cover extension namespaces and is the subject of a defect report and was subsequently removed and replaced with more specific wording. We can see from DR 1795 which says:

According to 7.3.1 [namespace.def] paragraph 2,

The identifier in an original-namespace-definition shall not have been previously defined in the declarative region in which the original-namespace-definition appears.

Apparently the intent of this requirement is to say that, given the declarations

namespace N { }
namespace N { }

the second declaration is to be taken as an extension-namespace-definition and not an original-namespace-definition, since the general rules in 3.3.1 [basic.scope.declarative] cover the case in which the identifier has been previously declared as something other than a namespace.

and tells us that 3.3.1 [basic.scope.declarative] covers the case you are referring to, which it does in paragraph 1:

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. In general, each particular name is valid only within some possibly discontiguous portion of program text called its scope. To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative region is excluded from the scope of the declaration in the outer (containing) declarative region.

and 3:

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,

  • they shall all refer to the same entity, or all refer to functions and function templates;
M.M
  • 138,810
  • 21
  • 208
  • 365
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Having this question brought to my attention by M.M's edit, I did not believe the accepted answer, until I read the citations in yours. Top marks. The point that declarative region rules are "aware" of "overrides" of names in more inner scopes is the key point, and nobody else proved that. – Lightness Races in Orbit Mar 07 '19 at 00:33
  • Actually on further reading Nathan did but yours is still clearer ;) – Lightness Races in Orbit Mar 07 '19 at 00:35
0

If you look at the example 3.3.1(2) just below 3.3.1(1)

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

It is noted as

the identifier j is declared twice as a name (and used twice). The declarative region of the first j includes the entire example. The potential scope of the first j begins immediately after that j and extends to the end of the program, but its (actual) scope excludes the text between the , and the }. The declarative region of the second declaration of j (the j immediately before the semicolon) includes all the text between { and }, but its potential scope excludes the declaration of i. The scope of the second declaration of j is the same as its potential scope.

Pay attention to what it say the scope of the name is. Emphasis mine.

So in the global space of the program you have a name A that is your namespace. Then you enter the scope of main() and the namespace A is still a valid name until in the declaration of the int A has been seen. Once that happens in the scope of main the namespace A will be hidden and any unqualified calls to A will be to the int that was declared.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 1
    Note, notes and examples are not normative and the question is tagged language lawyer, so I would expect at least some normative text in your answer. – Shafik Yaghmour Apr 21 '15 at 14:34
0

The largest scope that your int A is valid is the entire scope of main, so its declarative region is main. The namespace is valid at global scope and as such is not in the same declarative scope. Note that while the scopes overlap, they are not the same scope. The code looks valid to me given your quotes from the standard.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • Why not? Isn't `using namespace A;` valid inside main()? Then the block enclosed by main() is part of the declarative region containing the definition of namespace A. – Leon Apr 21 '15 at 14:52
  • [namespace.alias]/4 doesn't say anything about scopes, but about declarative regions. – Leon Apr 21 '15 at 14:57