3

I expected the following program to emit a diagnostic in GCC or Clang:

#undef protected
#undef private

due to [macro.names]/2:

A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.

protected and private are both listed in Table 3. A quick find with "no diagnostic required" through N3337 didn't turn up anything. So are compilers required to complain in this case?

  • Doesn't that subclause fall under the blanket "behavior is undefined" in 17.6.4.3/2? – T.C. Dec 09 '14 at 11:11
  • There wouldn't be any point either way. Keywords aren't defined by the preprocessor. – user207421 Dec 09 '14 at 11:13
  • 1
    OTOH, sometimes it may be necessary. I have come across naughty code saying `#define private public`, so `#undef private` is the only way to get rid of that UB. – juanchopanza Dec 09 '14 at 11:17
  • 1
    @juanchopanza does that really "get rid" of the UB? I thought once there's UB in any code, the behavior of the entire afterlife of the program is undefined. Hence `#undef private` may not do what one might expect. Is this not the case? – The Paramagnetic Croissant Dec 09 '14 at 11:19
  • @TheParamagneticCroissant It's undefined behavior _if_ the program uses the standard library (or if the translation unit includes any standard header---I'm not sure which). Otherwise, it's well defined. As for @juanchopanza's suggestion, he's making a pragmatic suggestion; the code presumably already contains undefined behavior. (`#define private public` is a good way of violating the one definition rule, for example.) – James Kanze Dec 09 '14 at 11:22
  • @T.C. That's the section I quoted. More generally: violations of constraints in the library are almost always undefined behavior, since the compiler isn't required to know about them (and this is a library constraint, not a constraint on the program in general). – James Kanze Dec 09 '14 at 11:25

3 Answers3

7

[macro.names] is part of [reserved.names], which states that "If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined." So it is undefined behavior.

In practice, most compilers will not complain for two reasons: the first is because pre-processing normally takes place before the compiler evaluates whether a symbol is a keyword or not; it's an earlier phase of translation. And also because such declarations are only illegal if you actually use the standard library (although other libraries, like Posix or Windows, may and probably do impose similar rules).

EDIT:

Just a general comment: although there is no global statement to this effect in the standard, there is a general, underlying principle that violation of library constraints is undefined behavior; the intent is that the compiler not need to know anything about the library, and that an implementation can treat #include <vector> exactly like #include "MyHeader.hpp" (except perhaps for where it looks for the file). And the restrictions cited in the original posting are constraints on programs using the library, and only apply to such programs. Something like:

#define while if
int
main( int argc, char** argv )
{
    int retval = 0;
    while ( argc > 0 ) {
        ++ retval;
        -- argc;
    }
    return retval;
}

is a perfectly well defined and legal C++ (and C) program, guaranteed to return 1. (Of course, I'd not recommend anything like this.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • [macro.names] is different from all other subsections though in that it does not say "is reserved", it says "shall not". – Sebastian Redl Dec 09 '14 at 11:25
  • @SebastianRedl Maybe, but [reserved.names] clearly applies to [macro.names]. – James Kanze Dec 09 '14 at 11:29
  • @SebastianRedl The reason for the different wording is probably because keywords aren't reserved names in the general sense; they are a totally separate entity. – James Kanze Dec 09 '14 at 11:32
0

Yes, but in practice most don't. Clang very recently got a warning.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
0

It's surely not a good idea to use names reserved for keywords. However, most compiler won't warn you regarding that.

You can have a look at Keywords redefinition in C / C++.

It's on similar lines.

Community
  • 1
  • 1
ravi
  • 10,994
  • 1
  • 18
  • 36