Premature macro expansion in preprocessor?

Hi,

In going through the preprocessor code in clang, I have noted a tendancy towards using Lex(Tok) over LexUnexpandedToken(Tok), for example in the built-in macro implementations.

This means, the following "works":

#define HB __has_builtin
#define LP (
#define BT __builtin_trap
#define RP )

HB LP BT RP // expands to 1

My question is, is this intentional, or an oversight? Is it worth my while going through and changing Lex(...) to LexUnexpandedToken(...) in these cases? Normally, preprocessor rules require an extra level of expansion, as in:

#define EXPAND(...) __VA_ARGS__
#define MACRO(A) String: #A

#define M MACRO
#define S test

M LP S RP // expands to MACRO ( test )
EXPAND(M LP S RP) // expands to String: "test"

Thoughts?

Andy

I consider this a bug. The __has_builtin/__has_feature/etc. code should be using LexUnexpandedToken.

  - Doug

Without commenting about the problem you observe in full generality, I
was talking to Doug about this the other day, and we both thought that
it was an oversight that macro expansion took place inside of many of
the __has_...() feature test constructs. Those should directly test
the token provided, so that people can use them without
__uglified__names__everywhere__ ;]

__has_feature and __has_extension should *definitely* work like this.

My inclination is make __has_attribute also work like this.

On the other hand, I think an argument can be made that
__has_builtin()s argument should be subject to macro expansion, as the
builtins themselves are.

The __has_include and other test macros that accept a string literal
clearly aren't applicable here.

Personally, I also find it distasteful that the feature tests are
treated as normal function-style-macros, as I don't think it is
reasonable to use your LP and RP macros above ... I wonder if it would
make more sense to define the feature tests as special tokens in the
preprocessor much like defined().

Personally, I also find it distasteful that the feature tests are
treated as normal function-style-macros, as I don't think it is
reasonable to use your LP and RP macros above ...

Yes, its only use, I think, is in some obfuscated coding contest!

I wonder if it would make more sense to define the feature tests
as special tokens in the preprocessor much like defined().

Actually, I differ in opinion here. I think it is useful that they
are implemented as function-style-macros because this means they
can be used in contexts outside of #if directives. defined() is
limited in its usefulness by this.

Cheers,
Andy

Ok, I'll have a look at it tomorrow then. (Too late in the night now!!)

Andy

FYI, I added "utils/ClangDataFormat.py" which can be used to display clang classes (initially just SourceLocation) in a more user-friendly format from inside lldb, for example:

(lldb) p Tok.Loc
(clang::SourceLocation) $0 = {
  (unsigned int) ID = 123582
}

becomes:

(lldb) p Tok.Loc
(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file)

This works both in command-line and inside Xcode. Note that it depends on r167629.
To enable it import this file in your ~/.lldbinit by adding this line:

command script import /path/to/ClangDataFormat.py

-Argyrios

I wasn't suggesting we have to give them exactly the same constraints,
more meaning that there is plenty of precedent for representing these
as something more constrained than function style macros.

I think the opposite. It is highly desirable that the __has_foo
builtins act exactly like function-style macros, so that this
(documented!) pattern can be used portably:

#ifndef __has_foo
#define __has_foo(x) 0
#endif

... Can I have my cake and eat it too? ;]

Anyways, fine, I suppose its better to live with the silliness of
function style macros if only to provide consistency for those who end
up needing function-style-macros...