[cfe-commits] Greatly improved static_cast error messages

Sebastian Redl sebastian.redl at getdesigned.at
Fri Nov 7 13:38:22 PST 2008

Douglas Gregor wrote:
> On Nov 6, 2008, at 3:53 PM, Sebastian Redl wrote:
>> Attached patch brings a great improvement in the error messages for 
>> invalid static_casts. It's not quite trivial, though, so I'm asking 
>> for a review first.
> These *are* greatly improved error messages. Nice!
Thank you!
> Of course, you caught my eye with this one:
> +  // This may not be entirely in line with the standard. Take for 
> example:
> +  // struct A {};
> +  // struct B : virtual A {
> +  //   B(A&);
> +  // };
> +  //
> +  // void f()
> +  // {
> +  //   (void)static_cast<const B&>(*((A*)0));
> +  // }
> +  // As far as the standard is concerned, p5 does not apply (A is 
> virtual), so
> +  // p2 should be used instead - "const B& t(*((A*)0));" is perfectly 
> valid.
> +  // However, both GCC and Comeau reject this example, and there's no 
> reason
> +  // to go to absurdly great lengths just to support pathological 
> examples.
> I'm trying to determine what these "absurdly great lengths" actually 
> would be. As far as I can tell, it means silently rejecting the A->B 
> downcast and then trying conversion by constructor later on (which 
> will happen anyway). That makes it harder to give a nice error message 
> in the common case, right?
> The reason for supporting this example, of course, is that it's what 
> the standard says, and we can smugly add this to our list of things 
> that we do right when others get them wrong. I'm okay with this patch 
> going in as-is, despite being non-compliant in this area, but I'd 
> rather that the comment reflect that this is a problem we're going to 
> fix, but it isn't a very high priority, e.g., make it a FIXME and drop 
> from "there's no reason..." to the end.
> I guess TryStaticDowncast could have some kind of interface that 
> allows it to say, "I might have more to complain about later" and, if 
> that flag gets set and later conversions fail, we can go back through 
> with a flag that says, "we failed; complain away."
Yes, but then the later conversion also needs a flag that says, "an 
earlier check may have had a better reason to complain than you, so 
don't", and a return value that says, "I would have complained, but you 
told me not to".
Or perhaps that can actually be solved nicely. I'll add the fixme and 
reinvestigate at a later date.
> In TryStaticImplicitCast:
> +  if (DestType->isRecordType()) {
> +    // FIXME: Use an implementation of C++ [over.match.ctor] for this.
> +    return TSC_NotApplicable;
> +  }
> Have you seen PerformInitializationByConstructor?
Yes, but I haven't had the time to examine it more closely yet. Since 
the old version didn't handle this case, I didn't add the case now either.
> It's a relatively new addition that, as it says, performs 
> initialization of a class type by constructor. It should do what you 
> need, although I guess we might need to split it into 
> Perform/TryInitializationByConstructor.
> +  // FIXME: To get a proper error from invalid conversions here, we 
> need to
> +  // reimplement more of this.
> +  ImplicitConversionSequence ICS = TryImplicitConversion(SrcExpr, 
> DestType);
> +  return ICS.ConversionKind == 
> ImplicitConversionSequence::BadConversion ?
> +    TSC_NotApplicable : TSC_Success;
> I assume that the problem here is that we don't get good error 
> messages out of TryImplicitConversion? That's definitely true, and it 
> has some of the same issues that you've been tackling with static_cast.
Yep, that's it.

Thanks for the review.

More information about the cfe-commits mailing list