CTSRD-CHERI / clang

DO NOT USE. Use llvm-project instead
Other
9 stars 8 forks source link

pointer types don't work in switch statements #106

Closed brooksdavis closed 7 years ago

brooksdavis commented 7 years ago

There's a lovely bit of code in ntp split between contrib/ntp/sntp/libopts/enum.c and contrib/ntp/sntp/libopts/autoopts/options.h which uses enums (though ints have the same issue) cast to pointers and then to uintptr_t in a switch statement. It fails to compile with an error like:

/home/bed22/git/llvm-cheri/Build/bin/clang -g -integrated-as --target=cheri-unknown-freebsd  -msoft-float --sysroot=/home/bed22/obj/mips.mips64/home/bed22/git/cheribsd/tmp -mabi=sandbox -c ../../enum-weirdness.c
../../enum-weirdness.c:21:7: error: expression is not an integer constant expression
        case (__uintcap_t)OPTPROC_EMIT_USAGE:
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../enum-weirdness.c:21:7: note: cast that performs the conversions of a reinterpret_cast is not
      allowed in a constant expression
1 error generated

The sample code is:

#define use_switch

typedef struct options  tOptions;

#ifdef use_enum
typedef enum {
    OP_VAL_EMIT_USAGE       = 1,  ///< request for usage
} opt_proc_vals_t;

#define OPTPROC_EMIT_USAGE      ((tOptions *)OP_VAL_EMIT_USAGE)
#else
#define OPTPROC_EMIT_USAGE      ((tOptions *)1)
#endif

int
optionEnumerationVal(tOptions * pOpts)
{

#ifdef use_switch
        switch ((__uintcap_t)pOpts) {
        case (__uintcap_t)OPTPROC_EMIT_USAGE:
                return 1;
        default:
                return 0;
        }
#else
        if (pOpts == OPTPROC_EMIT_USAGE)
                return 1;
        else
                return 0;
#endif
}

If recast as an if, else if, else, chain the compiler is able to handle this. I'm not sure that it's sensible to make this code work.

davidchisnall commented 7 years ago

This is probably quite difficult to fix. The integer constant expression code has a few ugly cases for handling intptr_t, but making it to work with pointers is probably going to require some invasive changes. We'll need to track the fact that the pointer is a cast from an integer, which I think the existing infrastructure doesn't know how to handle.