Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVM build fails with "error: invalid conversion from const void* to void*" #145

Closed
CodingMarkus opened this issue Feb 2, 2018 · 7 comments

Comments

@CodingMarkus
Copy link

When I try to build on Linux following the instructions given in the main README, it won't even compile.

../retdec/build/external/src/llvm-project/lib/Support/DynamicLibrary.cpp:141:42 error: invalid conversion from `const void*` to `void*` [-fpermissive]
    if (!strcmp(symbolName, #SYM)) return &SYM

GCC/G++ version 6.4

@s3rvac s3rvac changed the title Code doesn't build, invalid conversion... LLVM build fails with "error: invalid conversion from const void* to void*" Feb 2, 2018
@s3rvac
Copy link
Member

s3rvac commented Feb 2, 2018

Thank you for the report. Which Linux distribution do you use? So we can try to reproduce this.

@s3rvac
Copy link
Member

s3rvac commented Feb 2, 2018

Do you use Alpine Linux? If so, then I believe we will have to apply this or this patch to our LLVM version to get the build working. The reason is that Alpine Linux is based on musl libc instead of GNU libc, and the LLVM version that we use does not contain the patches needed to compile on musl libc (details).

@CodingMarkus
Copy link
Author

The first patch actually doesn't change anything at all. It just causes the compiler to take the ELSE case but the ELSE case contains exactly the same macros as the IF case, except that it verifies first that no macro of that name exist (which isn't the case and which had nothing to do with the reported problem). So I have no idea what the first patch is supposed to fix.

The 2nd one will of course work and is the same thing I already added by hand. If this is caused by musl, then I'll take the issue there. I just checked the standards again. The C standard says that "stdX" is a pointer to a FILE object, it doesn't say anything about being a const pointer. And the POSIX standard explicitly provides FILE * stdout as sample, so there is no const either. Whether it may be a good idea if these are/were const or not, if that breaks standard conformance, it's a horrible idea.

Now it fails at a different location because of duplicate symbols.

@ghost
Copy link

ghost commented Feb 3, 2018

glibc follows the gcc stanards though, and stdout is a #define in their library. #defines are const propagated by the language standard and wouldn't display the behavior of a pointer. I messed around with what the return type of that EXPLICIT_FUNCTION macro should be in ToT and came up with.

ptrs.cpp:12:18: warning: address of stack memory associated with local variable 'stdNonsense' returned
with a type of (void*)&* which is a warning in this context because it's taking the address of the deref of a stack local and converting it to a pointer.

The C++11 and 17 standards both agree that const void* -> void* conversions and other const conversions of the sort violate the purpose of the keyword and technically doing is also breaking the standard, as is taking a reference to a const pointer in general since all of those things allow modification where there should be any. C++17 allows it under the situation where the converted value is a temporary and can't be modified, but otherwise there's a reason const_cast<> exists.

So GCC doesn't allow this, Clang hasn't since it supported C++11, and Visual Studio's CL doesn't accept it.

**Z:\Code>cl ptrs.cpp /c
Microsoft (R) C/C++ Optimizing Compiler Version 19.12.25834 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.
ptrs.cpp(9): error C2440: 'initializing': cannot convert from 'const void *' to 'void *'
ptrs.cpp(9): note: Conversion loses qualifiers**

**Z:\Code>clang++ -std=c++17 ptrs.cpp
ptrs.cpp:9:8: error: cannot initialize a variable of type 'void *' with an lvalue of type 'const void *'
        void* x = y;
              ^   ~
1 error generated.

Z:\Code>clang++ -std=c++11 ptrs.cpp
ptrs.cpp:9:8: error: cannot initialize a variable of type 'void *' with an lvalue of type 'const void *'
        void* x = y;
              ^   ~
1 error generated.**

I'd take that as a sign that the library needs to be updated rather than the compiler, but that's just me. I'm not sure how integral muscl libc is to Alpine since I've never seen it mentioned until this thread, but I thought I'd run some tests for you. Did you try -fpermissive to disable the error?

@s3rvac
Copy link
Member

s3rvac commented Feb 17, 2018

@CodingMarkus What Linux distribution do you use? I would like to reproduce the issue before trying to fix it.

s3rvac added a commit that referenced this issue Mar 5, 2018

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
This commit includes a fix for #145.
@s3rvac s3rvac added the bug label Mar 5, 2018
@s3rvac
Copy link
Member

s3rvac commented Mar 5, 2018

Since we have not received an answer from you and we are unable to reproduce the issue, I have decided to apply both upstream patches (1, 2) to our LLVM fork (see avast/llvm@753e703). RetDec now uses LLVM with this commit for build (a0994e7).

If there are more issues with the build, please submit a separate issue. I am closing this one as fixed as it deals with a specific error.

@s3rvac s3rvac closed this as completed Mar 5, 2018
@s3rvac s3rvac self-assigned this Mar 5, 2018
@CodingMarkus
Copy link
Author

It was no Linux distribution at all, it was a special Docker Container that is based upon Alpine Linux and I reported that issue to the musl dev team and they said LLVM's code operates outside the POSIX standard as well as outside the C11 standard and that's why it won't compile as musl is "brutally" optimized for size using any trick that is allowed without violating these two standards. And according to these standards STDIN/SDTOUT/STDERR are "expressions whose result is the stream" and they are not the streams themselves, thus no standard would guarantee &STDIN to work. But LLVM recognized that issue themselves and have fixed it already a while ago, so as soon as you base your code on a later release of LLVM, the issue will go away on its own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants