Disabling “cast from pointer to smaller type uint3

2020-06-16 05:58发布

问题:

I'm working on a school project that involves porting a large piece of C++ code on an experimental piece of hardware. Unfortunately, that hardware is 64-bit and the code contains many instances of pointer arithmetic that expects pointers to be 32-bit, i.e. it often does reinterpret_cast<uint32_t>(ptr).

Going through them one by one would be very tedious and since this is an experimental project anyway, I'm happy to settle for a "hackish" workaround. So instead I modified the implementation of malloc to ensure it never allocates memory above the 4GB limit. Technically, these casts should therefore be valid.

Question is, how do I explain this to Clang? The error I'm getting is: error: cast from pointer to smaller type 'uint32_t' (aka 'unsigned int') loses information. Is there a way to disable it?

Thanks, David

回答1:

I agree that you should bite the bullet and fix the code to use the correct integer type. But to answer your question: No, you can't disable it, though you can work around it.

Many errors come from warnings. A good thing in general, but if you want to disable the warning, just do it. Since the culprit is probably something like -Wall which enables many warnings you should keep on, you should selectively disable this single warning. The error message mentions the diagnostic responsible for error message, e.g. ... [-Wextra-tokens] (if it doesn't, remove the -fno-diagnostics-show-option flag). You can then disable this diagnostic completely by adding -Wno-extra-tokens (again, the "extra tokens" warning is an example), or turn it into a non-fatal warning by means of -Wno-error=extra-tokens.

However, this specific error is not due to a warning and I can't find any option to disable errors (makes sense, since most errors are fatal).

But to just truncate the integer value and not having to fix all the wrong uses of uint32_t just yet, you could use static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)). Needless to say, this will still be wrong.



回答2:

I was able to disable this with -fms-extensions after getting this from someone on the Cpplang Slack:

Looking at "DiagnosticSemaKinds.td" it shows up as err_bad_reinterpret_cast_small_int, https://github.com/llvm-mirror/clang/blob/release_50/include/clang/Basic/DiagnosticSemaKinds.td#L6193 There are two occurences in "SemaCast.cpp" -- one of which suggests it's sensitive to MS extensions, https://github.com/llvm-mirror/clang/blob/release_50/lib/Sema/SemaCast.cpp#L2112 One could try -fms-extensions (hopefully not -fms-compatibility), but that would bring all the shebang with it.



回答3:

how about using uintptr_t, most of your pointer arithmetic may still works.



回答4:

Save this piece of code as mycast.hpp and add -include mycast.hpp to your Makefile.

#include <cstdint>

template<typename U, typename T>
U Reinterpret_cast(T *x) {
    return (U)(uintptr_t)x;
}

template<typename U, typename T>
U Reinterpret_cast(T &x) {
    return *(U*)&x;
}

#define reinterpret_cast Reinterpret_cast

They should do their job unless your code is too tricky.

Your strategy will not work for stack-allocated objects, be careful!! You can insert some debugging/logging logic to Reinterpret_cast if necessary.



回答5:

I hit this same problem in a project without C++11, and worked around it like this:

inline int PtrToInt(void* ptr)
{
    void* clang[1];
    clang[0] = ptr;
    return *(int*)clang;
}