Search code examples
c++language-lawyerexternextern-c

Are extern extern "C", and extern "C" extern, allowed?


Is this code correct?

extern "C" extern int x;       // 1
extern extern "C" int y;       // 2
extern "C" extern "C" int z;   // 3

int main() { }

gcc rejects 1 and 2 as syntax errors and accepts 3. clang accepts all three but gives a duplicate-declaration-specifier warning about them all.

Maybe relevant is C++17 [dcl.stc]/5:

The extern specifier can be applied only to the names of variables and functions. The extern specifier cannot be used in the declaration of class members or function parameters. For the linkage of a name declared with an extern specifier, see 6.5. [Note: The extern keyword can also be used in explicit-instantiations and linkage-specifications, but it is not a storage-class-specifier in such contexts. —end note ]


Solution

  • extern extern "C" is not valid syntax, as extern "C" is not a specifier and thus cannot occur in a decl-specifier-seq. Instead extern "C" can only appear as part of a linkage-specification, for which the syntax is

    extern string-literal { declaration-seq(opt) }
    extern string-literal declaration

    Thus, extern "C" must occur first.

    Also, extern "C" extern is not valid either, according to [dcl.link]/7:

    A declaration directly contained in a linkage-specification is treated as if it contains the extern specifier (10.1.1) for the purpose of determining the linkage of the declared name and whether it is a definition. Such a declaration shall not specify a storage class.

    (extern is a storage class specifier.)

    It doesn't seem that there is any rule forbidding extern "C" extern "C", though.