Newer
Older
//===---------------------------------------------------------------------===//
// Random Notes
//===---------------------------------------------------------------------===//
//===---------------------------------------------------------------------===//
Extensions:
* "#define_target X Y"
This preprocessor directive works exactly the same was as #define, but it
notes that 'X' is a target-specific preprocessor directive. When used, a
diagnostic is emitted indicating that the translation unit is non-portable.
If a target-define is #undef'd before use, no diagnostic is emitted. If 'X'
were previously a normal #define macro, the macro is tainted. If 'X' is
subsequently #defined as a non-target-specific define, the taint bit is
cleared.
* "#define_other_target X"
The preprocessor directive takes a single identifier argument. It notes
that this identifier is a target-specific #define for some target other than
the current one. Use of this identifier will result in a diagnostic.
If 'X' is later #undef'd or #define'd, the taint bit is cleared. If 'X' is
already defined, X is marked as a target-specific define.
//===---------------------------------------------------------------------===//
To time GCC preprocessing speed without output, use:
This is similar to -Eonly.
//===---------------------------------------------------------------------===//
Interesting fact:
clang -Eonly INPUTS/carbon-header-C-E.c
wc -w INPUTS/carbon-header-C-E.c
!!
//===---------------------------------------------------------------------===//
The 'portability' model in clang is sufficient to catch translation units (or
their parts) that are not portable, but it doesn't help if the system headers
are non-portable and not fixed. An alternative model that would be easy to use
is a 'tainting' scheme. Consider:
int32_t
OSHostByteOrder(void) {
#if defined(__LITTLE_ENDIAN__)
return OSLittleEndian;
#elif defined(__BIG_ENDIAN__)
return OSBigEndian;
It would be trivial to mark 'OSHostByteOrder' as being non-portable (tainted)
instead of marking the entire translation unit. Then, if OSHostByteOrder is
never called/used by the current translation unit, the t-u wouldn't be marked
non-portable. However, there is no good way to handle stuff like:
extern int X, Y;
#ifndef __POWERPC__
#define X Y
#endif
int bar() { return X; }
When compiling for powerpc, the #define is skipped, so it doesn't know that bar
uses a #define that is set on some other target. In practice, limited cases
could be handled by scanning the skipped region of a #if, but the fully general
case cannot be implemented efficiently. In particular, code like this (from
OSByteOrder.h):
#if (defined(__ppc__) || defined(__ppc64__))
#include <libkern/ppc/OSByteOrder.h>
#elif (defined(__i386__) || defined(__x86_64__))
#include <libkern/i386/OSByteOrder.h>
#else
#include <libkern/machine/OSByteOrder.h>
#endif
... should be fixed by having an initial #ifdef __llvm__ that defines its
contents in terms of the llvm bswap intrinsics. Other things should be handled
on a case-by-case basis.
We probably have to do something smarter like this in the future. The C++ header
static const int digits10 = __LDBL_DIG__;
static const int min_exponent = __LDBL_MIN_EXP__;
static const int min_exponent10 = __LDBL_MIN_10_EXP__;
static const float_denorm_style has_denorm
= bool(__LDBL_DENORM_MIN__) ? denorm_present : denorm_absent;
... since this isn't being used in an #ifdef, it should be easy enough to taint
the decl for these ivars.
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/usr/include/sys/cdefs.h contains stuff like this:
#if defined(__ppc__)
# if defined(__LDBL_MANT_DIG__) && defined(__DBL_MANT_DIG__) && \
__LDBL_MANT_DIG__ > __DBL_MANT_DIG__
# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 < 1040
# define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBLStub")
# else
# define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBL128")
# endif
# define __DARWIN_LDBL_COMPAT2(x) __asm("_" __STRING(x) "$LDBL128")
# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0
# else
# define __DARWIN_LDBL_COMPAT(x) /* nothing */
# define __DARWIN_LDBL_COMPAT2(x) /* nothing */
# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 1
# endif
#elif defined(__i386__) || defined(__ppc64__) || defined(__x86_64__)
# define __DARWIN_LDBL_COMPAT(x) /* nothing */
# define __DARWIN_LDBL_COMPAT2(x) /* nothing */
# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0
#else
# error Unknown architecture
#endif
An ideal way to solve this issue is to mark __DARWIN_LDBL_COMPAT /
__DARWIN_LDBL_COMPAT2 / __DARWIN_LONG_DOUBLE_IS_DOUBLE as being non-portable
because they depend on non-portable macros.
//===---------------------------------------------------------------------===//