[cfe-dev] Preliminary reinterpret_cast Sema patch
akyrtzi at gmail.com
Sun Oct 19 06:22:41 PDT 2008
Sebastian Redl wrote:
> The thing is, compilers implement a curiously hybrid view of the
> 5.2.10/1 says that only the explicitly listed conversions are supported.
> 5.2.10/2 says that conversion to self is allowed, "subject to the
> restrictions in this section". But 5.2.10 contains only two
> restrictions: that of not casting away constness (/2) and that of only
> allowing explicitly listed conversions (/1).
> Let's look at the other paragraphs:
> /4 allows pointer->integral. Obviously, this can't allow conversion to
> /5 allows integral->pointer. Same thing.
> /6 allows pointer to function to pointer to function "of different
> type". This explicitly disallows conversion to self.
> /7 allows pointer to object to pointer to object "of different type".
> Again, conversion to self is explicitly disallowed.
> /9 allows pointer to member to pointer to member, if both sides are
> member function or member object types, no mixing. This does not
> explicitly disallow conversion to self, although it was probably
> intended, since it would be in keeping with the spirit of the other
> two paragraphs.
> This means that there are, in my opinion, three valid interpretations
> of the standard:
> 1) Conversion to self is allowed only for pointers to members. This is
> the most literal interpretation.
> 2) Conversion to self is not allowed at all. This assumes that /9 is
> in the spirit of /6 and /7.
> 3) Conversion to self is always allowed. This assumes the note in /2
> is actually normative and the only restriction it talks about is
> casting away constness.
> But compilers generally allow conversion to self if the involved types
> are both pointers, or the equivalent reference cast. GCC allows
> int*->int*, but not int->int.
> It's easy to follow general practice, of course, but I still think
> that the other compilers are wrong.
The justification is that integral->integral is not a "explicitly listed
conversion", so int->int should also be illegal.
>>> float *fp = reinterpret_cast<float*>(l);
>>> // Note: should fail on 64-bit, but LLVM is target-agnostic. Is it
>>> // to annotate the bytecode to make this fail in native codegen?
>>> int i = reinterpret_cast<int>(fp);
>> LLVM IR produced by C/C++ cannot be target-agnostic. See:
>> You can use TargetInfo to check whether the above conversion is legal.
> Sad, but makes sense. How do I get a TargetInfo from the Sema?
It's in ASTContext (Context.Target), but a better way is to use
ASTContext's getTypeSize(QualType T).
>>> fnptr2 fp2 = reinterpret_cast<fnptr2>(fp);
>>> // Should fail in C++03 without extensions, succeed with exts or
>>> in 0x mode.
>>> void *vp = reinterpret_cast<void*>(fp2);
>> All three compilers accept this; I think Clang should accept it too,
>> programmers will be unpleasantly surprised if they find this is not
> I accept it unless LangInfo.NoExtensions is set. I don't know any
> switch that actually enables this bit, though - I think -std=c++98
> should, but it doesn't. I can get rid of the NoExtensions check if you
> think it's better.
> In addition, I warn if -pedantic is set. This is consistent with GCC's
Ah never mind, I agree about keeping it consistent with GCC.
If you issue a diagnostic marked with EXTENSION it will have this
behavior without having to do any explicit checks yourself:
-will not be emitted by default
-will emit a warning at -pedantic
-will emit an error at -pedantic-errors.
And you are right, for C++0x it should probably be allowed without
More information about the cfe-dev