Search code examples
clanguage-lawyerdeclarationdefinition

Understanding declarations in the same scope


This is a language-lawyer question about ISO C.

I'm trying to understand how declaration is defined in the Standard. I use N1570. Consider the following cases:

Case 1.

int a;
extern int a; //compatible types, external linkage, well-defined behavior

Case 2.

extern int a;
int a; //well-defined behavior, external linkage, well-defined behavior

Case 3.

int a;
static int a; //6.2.2/6.9.2UB, linkage-disagreement

Case 4.

static int a;
extern int a; //6̶.̶2̶.̶2̶/̶6̶.̶9̶.̶2̶ ̶U̶B̶,̶ ̶l̶i̶n̶k̶a̶g̶e̶-̶d̶i̶s̶a̶g̶r̶e̶e̶m̶e̶n̶t̶
              //as @EricPostpischil mentioned in the comment
              //it is well-defined in 6.2.2

Case 5.

int a;
long a; //6.7.2 UB incompatible types

Case 6.

int a;
const int a; //6.7.2/6.7.3 incompatible types, different qualifiers

Case 7.

enum{
    a
};

enum{
    a //UB, why?
};

Case 8.

 enum {
     a
 };

 const unsigned char a; //UB, why?

Case 1-4

The explanation is clear and well-defined in the Standard.

6.2.2(p7):

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

Case 5

It is explained in the sections 6.2.7(p1):

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

and 6.7(p4):

All declarations in the same scope that refer to the same object or function shall specify compatible types.

Case 6

It is explained by 6.7.3(p10):

For two qualified types to be compatible, both shall have the identically qualified version of a compatible type

Case 7-8.

Unclear. I did not find any formal references in the Standard related to them. 6.2.7(p1) states:

For two enumerations, corresponding members shall have the same values.

case 7 satisfies that requirements.

so I don't see any problems.

I did not find anything related to case 8 explicitly so as if it is not defined in the Standard it should be UB.

Can you help to find an explanation in the Standard of the Case 7 and Case 8?


Solution

  • Case 7

    It is explained by 6.7.2.3 paragraph 1, 4 and 5 (page 137) (emphasis is mine)

    1 A specific type shall have its content defined at most once.

    4 All declarations of structure, union, or enumerated types that have the same scope and use the same tag declare the same type. Irrespective of whether there is a tag or what other declarations of the type are in the same translation unit, the type is incomplete [footnote 129)] until immediately after the closing brace of the list defining the content, and complete thereafter.

    5 Two declarations of structure, union, or enumerated types which are in different scopes or use different tags declare distinct types. Each declaration of a structure, union, or enumerated type which does not include a tag declares a distinct type.

    So an example of identical types of enums [if not for paragraph 1] would be like

    enum TagNameA
    {
        a
    };
    enum TagNameA
    {
       a
    };
    

    Case 8 It is explained by 6.7.2.2 paragraph 3 (page 136) (emphasis is mine)

    The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted [footnote: 127)]

    ...

    [footnote 127)] Thus, the identifiers of enumeration constants declared in the same scope shall all be distinct from each other and from other identifiers declared in ordinary declarators.

    where in Case 8

    const unsigned char a;
    

    is an ordinary declarator for a that is not distinct from the enumeration constant identifier a.