Conditional compilation inside asm and enum declarations

Walter Bright newshound1 at digitalmars.com
Tue Jul 14 17:56:17 PDT 2009


Bill Baxter wrote:
> On Tue, Jul 14, 2009 at 5:13 PM, Walter
> Bright<newshound1 at digitalmars.com> wrote:
>> Why do C and C++ (and D) make it difficult to do:
>>
>>   char *p;
>>   p |= 1;
>>
>> ? There's no implementation difficulty in accepting such and generating
>> correct code for it. It's purely a matter of making what is generally
>> considered to be bad practice harder to do. I've never heard anyone argue
>> that this was a bad decision.
> 
> I've never ever needed to do that, or been the slightest bit tempted
> to.  The operation doesn't make sense.  So I think the analogy is
> inappropos.

I beg to differ. My C++ compiler implementation of precompiled headers 
uses bit 0 to determine if a pointer needs to be adjusted based on where 
it is loaded into memory or not.

Using the bottom two bits as flags (because the pointers were aligned) 
is not all that uncommon. I've seen it done by major companies on some 
major, very successful projects.

Then there's the famous pointer "xor hack".


> In contrast, using the negation of a version makes plenty
> of sense.

As you wrote, we've hashed through that before. Over time, I've 
eliminated nearly all the negated conditionals from my code, and have 
been happier with the results. Half of them turned out to be bogus 
anyway, because I'd add a 3rd state and then latent undetected bugs 
would appear.

Here's one of my faves:

#ifndef _WIN32
     ... do something for Linux ...
#endif

Does this happen in reality? I grepped #ifndef's from the Hans Boehm gc:

version.h:#ifndef GC_NO_VERSION_VAR
allchblk.c:#ifndef USE_MUNMAP
alloc.c:#ifndef SMALL_CONFIG
AmigaOS.c:#ifndef GC_AMIGA_FASTALLOC
AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST
AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST
AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST
AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST
AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST
AmigaOS.c:#ifndef GC_AMIGA_FASTALLOC
AmigaOS.c:#ifndef GC_AMIGA_ONLYFAST
dbg_mlc.c:#ifndef SHORT_DBG_HDRS
dbg_mlc.c:#ifndef SHORT_DBG_HDRS
dbg_mlc.c:#ifndef SHORT_DBG_HDRS
dbg_mlc.c:#ifndef SHORT_DBG_HDRS
dyn_load.c:#ifndef _sigargs
finalize.c:#ifndef NO_DEBUGGING
finalize.c:#ifndef JAVA_FINALIZATION_NOT_NEEDED
irix_threads.c:#ifndef LINT
linux_threads.c:#ifndef __GNUC__
linux_threads.c:#ifndef SIG_THR_RESTART
mach_dep.c:#ifndef USE_GENERIC_PUSH_REGS
mach_dep.c:#ifndef SPARC
mark.c:#ifndef THREADS
mark.c:#ifndef UNALIGNED
mark.c:#ifndef SMALL_CONFIG
mark.c:#ifndef SMALL_CONFIG
misc.c:#ifndef _WIN32_WCE
misc.c:#ifndef PCR
new_hblk.c:#ifndef SMALL_CONFIG
os_dep.c:#ifndef HEAP_START
os_dep.c:#ifndef THREADS
solaris_pthreads.c:#ifndef LINT
solaris_threads.c:#ifndef MMAP_STACKS
solaris_threads.c:#ifndef LINT

The #ifndef NO_DEBUGGING is awful. The #ifndef __GNUC__ means compile 
for every unknown compiler ever, except gcc. Can't possibly be right.

Let's try grepping for !defined. We get:

allchblk.c:# if !defined(NO_DEBUGGING)
alloc.c:# if !defined(MACOS) && !defined(MSWINCE)
alloc.c:#   if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
alloc.c:# if !defined(NO_DEBUGGING)
alloc.c:#	    if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC)
AmigaOS.c:#if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && 
!defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM)
checksums.c:#   if !defined(MSWIN32) && !defined(MSWINCE)
dyn_load.c:#if !defined(MACOS) && !defined(_WIN32_WCE)
dyn_load.c:     && !defined(GC_USE_LD_WRAP)
dyn_load.c:    && !defined(PCR)
dyn_load.c:#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) 
&& \
dyn_load.c:    !defined(MSWIN32) && !defined(MSWINCE) && \
dyn_load.c:    !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
dyn_load.c:    !defined(RS6000) && !defined(SCO_ELF) && \
dyn_load.c:#if defined(SUNOS5DL) && !defined(USE_PROC_FOR_LIBRARIES)
dyn_load.c:#if defined(SUNOS4) && !defined(USE_PROC_FOR_LIBRARIES)
dyn_load.c:# if !defined(PCR) && !defined(SOLARIS_THREADS) && 
defined(THREADS)
dyn_load.c:#    if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
dyn_load.c:#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && 
!defined(LINUX))
dyn_load.c:#   if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
finalize.c:#		if !defined(THREADS) && !defined(DBG_HDRS_ALL)
gc_dlopen.c:# if defined(dlopen) && !defined(GC_USE_LD_WRAP)
linux_threads.c:# if defined(HPUX_THREADS) && 
!defined(USE_PTHREAD_SPECIFIC) \
linux_threads.c:     && !defined(USE_HPUX_TLS)
linux_threads.c:#   if !defined(USE_PTHREAD_SPECIFIC) && 
!defined(USE_HPUX_TLS)
linux_threads.c:# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
linux_threads.c:#	if defined(REDIRECT_MALLOC) && 
!defined(USE_PTHREAD_SPECIFIC) \
linux_threads.c:	   || !defined(__GNUC__)
linux_threads.c:#if !defined(HPUX_THREADS) && !defined(GC_OSF1_THREADS)
linux_threads.c:#   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
linux_threads.c:#   if defined(THREAD_LOCAL_ALLOC) && 
!defined(USE_PTHREAD_SPECIFIC) \
linux_threads.c:       && !defined(USE_HPUX_TLS) && !defined(DBG_HDRS_ALL)
linux_threads.c:#   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
linux_threads.c:#if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK)
mach_dep.c:#if defined(__MWERKS__) && !defined(POWERPC)
mach_dep.c:#       if defined(I386) &&!defined(OS2) &&!defined(SVR4) \
mach_dep.c:	&& (defined(__MINGW32__) || !defined(MSWIN32)) \
mach_dep.c:	&& !defined(SCO) && !defined(SCO_ELF) \
mach_dep.c:	&& !defined(DOS4GW)
mach_dep.c:#       if defined(I386) && defined(MSWIN32) && 
!defined(__MINGW32__) \
mach_dep.c:	   && !defined(USE_GENERIC)
mach_dep.c:#	if !defined(POWERPC) && !defined(UTS4)
mach_dep.c:#       if !defined(PJ) && !(defined(MIPS) && defined(LINUX))
mach_dep.c:#if defined(ASM_CLEAR_CODE) && !defined(THREADS)
MacOS.c:#     if !defined(SHARED_LIBRARY_BUILD)
MacOS.c:#       if !defined(SILENT) && !defined(SHARED_LIBRARY_BUILD)
mallocx.c:#if defined(THREADS) && !defined(SRC_M3)
mark.c:#     if !defined(IA64) && !defined(HP_PA)
mark.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
mark.c:#   if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
mark.c:#   if !defined(SMALL_CONFIG) && !defined(UNALIGNED) && \
mark.c:       !defined(USE_MARK_BYTES)
mark_rts.c: #	if !defined(MSWIN32) && !defined(MSWINCE)
mark_rts.c:# if !defined(NO_DEBUGGING)
mark_rts.c:#if !defined(MSWIN32) && !defined(MSWINCE)
mark_rts.c:#   if !defined(MSWIN32) && !defined(MSWINCE)
mark_rts.c:#   if !defined(MSWIN32) && !defined(MSWINCE)
mark_rts.c:#   if !defined(MSWIN32) && !defined(MSWINCE)
mark_rts.c:	   || defined(PCR)) && !defined(SRC_M3)
mark_rts.c:#   if !defined(USE_GENERIC_PUSH_REGS)
misc.c:		   || defined(LINUX_THREADS) && !defined(USE_SPIN_LOCK)
misc.c:#   if !defined(THREADS) && defined(GC_ASSERTIONS)
misc.c:#   if !defined(THREADS) || defined(SOLARIS_THREADS) || 
defined(WIN32_THREADS) \
misc.c:#     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
misc.c:#   if !defined(_AUX_SOURCE) || defined(__GNUC__)
misc.c:# if !defined(SMALL_CONFIG)
misc.c:#if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && 
!defined(MSWINCE)
misc.c:# if !defined(AMIGA)
misc.c:#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) && 
!defined(MACOS)
misc.c:#if defined(LINUX) && !defined(SMALL_CONFIG)
misc.c:#if !defined(NO_DEBUGGING)
os_dep.c:# if defined(LINUX) && !defined(POWERPC)
os_dep.c:# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && 
!defined(MACOS) \
os_dep.c:    && !defined(MSWINCE)
os_dep.c:#   if !defined(MSWIN32) && !defined(SUNOS4)
os_dep.c:# if !defined(THREADS) && !defined(STACKBOTTOM) && 
defined(HEURISTIC2)
os_dep.c:# if (defined(SUNOS4) && defined(DYNAMIC_LOADING)) && !defined(PCR)
os_dep.c:# if (defined(SVR4) || defined(AUX) || defined(DGUX)) && 
!defined(PCR)
os_dep.c:#if !defined(NO_EXECUTE_PERMISSION)
os_dep.c:# if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
os_dep.c:#  if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
os_dep.c:      && !defined(MSWINCE) \
os_dep.c:      && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW)
os_dep.c:#   if defined(sigmask) && !defined(UTS4)
os_dep.c:#if defined(PRINTSTATS) && !defined(THREADS)
os_dep.c:#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
os_dep.c:    && !defined(MSWINCE) && !defined(OS2)
os_dep.c:      || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
os_dep.c:#   if !defined(PCR) && !defined(SRC_M3) && !defined(NEXT) && 
!defined(MACOS) \
os_dep.c:       && !defined(MACOSX)
os_dep.c:#   if !defined(PCR) && (defined(NEXT) || defined(MACOSX))
os_dep.c:# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
os_dep.c:	&& !defined(MSWIN32) && !defined(MSWINCE) \
os_dep.c:	&& !defined(MACOS) && !defined(DOS4GW)
os_dep.c:#   if !defined(LINUX)
os_dep.c:#if !defined(MSWIN32) && !defined(MSWINCE)
os_dep.c:# if !defined(MSWIN32) && !defined(MSWINCE)
os_dep.c:#   if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || 
defined(ALPHA) || defined(IA64)
os_dep.c:#		if !defined(MSWIN32) && !defined(MSWINCE)
os_dep.c:#if !defined(MSWIN32) && !defined(MSWINCE) && 
!defined(LINUX_THREADS) \
os_dep.c:    && !defined(GC_USE_LD_WRAP)
os_dep.c:# if defined(__STDC__) && !defined(SUNOS4)
os_dep.c:    (!defined(SMALL_CONFIG) || defined(USE_PROC_FOR_LIBRARIES))
os_dep.c:#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
ptr_chck.c:                && !defined(SRC_M3)
reclaim.c:#if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES)
reclaim.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
reclaim.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
reclaim.c:#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
reclaim.c:#      if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
reclaim.c:#      if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
reclaim.c:#if !defined(NO_DEBUGGING)

stlport is not quite as bad:

src\c_locale_win32\c_locale_win32.c:#if !defined (LC_MAX)
stlport\stl\_algo.c:# if !defined (_STLP_INTERNAL_ALGO_H)
stlport\stl\_algobase.c:# if !defined (_STLP_INTERNAL_ALGOBASE_H)
stlport\stl\_limits.c:# if !defined (_STLP_LIMITS_C)
stlport\stl\_list.c:#if !defined (__WATCOMC__)
stlport\stl\_num_get.c:# if 
defined(_STLP_LONG_LONG)&&!defined(__MRC__)		//*ty 12/07/2001 - MrCpp 
can not cast from long long to void*
stlport\stl\_num_put.c:# if defined(_STLP_LONG_LONG) && 
!defined(__MRC__) //*ty 11/24/2001 - MrCpp can not cast from void* to 
long long
stlport\stl\_ostream.c:#if !defined (_STLP_INTERNAL_NUM_PUT_H)
stlport\stl\_rope.c:#if !defined (_STLP_USE_NO_IOSTREAMS)	
stlport\stl\_rope.c:#if defined(__MRC__)||(defined(__SC__) && 
!defined(__DMC__))		//*TY 05/23/2000 - added support for mpw compiler's 
trigger function approach to generate vtable
stlport\stl\_rope.c:#  if defined(__MRC__)||(defined(__SC__) && 
!defined(__DMC__))		//*TY 05/23/2000 - added support for mpw compiler's 
trigger function approach to generate vtable
stlport\stl\_rope.c:#  if defined(__MRC__)||(defined(__SC__) && 
!defined(__DMC__))		//*TY 05/23/2000 - added support for mpw compiler's 
trigger function approach to generate vtable
stlport\stl\_rope.c:# if !defined (_STLP_NO_METHOD_SPECIALIZATION)
stlport\stl\_rope.c:#endif /* if !defined (_STLP_USE_NO_IOSTREAMS) */
stlport\stl\_rope.c:#if !defined (_STLP_USE_NO_IOSTREAMS)
stlport\stl\_rope.c:#	if !defined(__GC) && defined(_STLP_USE_EXCEPTIONS)
stlport\stl\_streambuf.c:#  if !defined (_STLP_NO_WCHAR_T)
stlport\stl\_string.c:# if defined (_STLP_USE_OWN_NAMESPACE) || !defined 
(_STLP_USE_NATIVE_STRING)
stlport\stl\_string.c:# if !defined (_STLP_LINK_TIME_INSTANTIATION)
stlport\stl\_string_fwd.c:#if !defined ( _STLP_STRING_FWD_C) && ! 
defined (_STLP_OWN_IOSTREAMS)
stlport\stl\_threads.c:#  if !defined ( _STLP_ATOMIC_EXCHANGE ) && 
(defined (_STLP_PTHREADS) || defined (_STLP_UITHREADS) || defined 
(_STLP_OS2THREADS))
stlport\stl\_vector.c:# if !defined (_STLP_INTERNAL_VECTOR_H)
stlport\stl\debug\_debug.c:#  if !defined( _STLP_DEBUG_MESSAGE )
src\c_locale_win32\c_locale_win32.c:#ifndef _LEADBYTE

See all those !(NO_FEATURE) constructs? Not no-how, not no-way! And 
people say my use of goto is bad and should be taken away from me :-)

I tried it on the Microsoft Windows api headers. Many pages of very 
dubious use follow, no need to post it all here.

This stuff is marquee showcase code by professional well-paid corporate 
developers, not idiots or newbies. I slip into writing such crud, too.


> As does versioning out an entry in an enum that doesn't
> apply for some reason.

Can we discuss a real example of this? I think perhaps we can find a way 
to accommodate the desired result (if not the method) in a clean manner.



More information about the Digitalmars-d mailing list