3
votes

Consider the following example:

#include <iostream>

void foo(class B, B *b); 

B *c; //OK

int main(){ }

DEMO

The Standard N4296::3.3.2/7.1 [basic.scope.pdecl]

— for a declaration of the form

class-key attribute-specifier-seqopt identifier;

the identifier is declared to be a class-name in the scope that contains the declaration

, but according to N4296:3.3.4/1 [basic.scope.proto]

In a function declaration, or in any function declarator except the declarator of a function definition (8.4), names of parameters (if supplied) have function prototype scope, which terminates at the end of the nearest enclosing function declarator.

So, the class B should have been introduced in the function prototype scope. And the scope of B should have been up to the end of the foo's declarator. But the name is visible in the global scope. Why?

1
I don't know, but GCC 4.7 accepts this too. I'm really curious how you came up with this construction in the first place!John Zwinck
The first quote doesn't apply. There's no semicolon.T.C.

1 Answers

6
votes

You are quoting the wrong bullet in 3.3.2 [basic.scope.pdecl]/p7. The class B in the declaration of foo is not of the form class-key attribute-specifier-seq_opt identifier; - there is no semicolon.

Instead, the second bullet applies:

for an elaborated-type-specifier of the form

class-key identifier

if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration.

Hence, the elaborated-type-specifier class B in your example declares B as a class-name in the namespace containing the declaration of foo - i.e., the global namespace.