[cfe-dev] Standard conversion sequences and PerformImplicitConversion

Bevin Hansson via cfe-dev cfe-dev at lists.llvm.org
Mon Dec 9 02:01:18 PST 2019


Hi cfe-dev,

While looking at generalizing address space support in Clang, I've 
struck upon some oddities with the emission of standard conversion 
sequences in PerformImplicitConversion. The method claims to lower every 
step of the conversions contained in an SCS that are passed to it. 
However, in reality the method completely ignores the intermediate types 
of the individual conversions, resulting in certain conversion steps 
doing more than they should be. For example, if an SCS consists of a 
pointer conversion followed by a qualification conversion, the pointer 
conversion will actually perform both steps, and the qualification 
conversion will simply be a no-op.

The reason for this behavior is because PerformImplicitConversion never 
looks at the intermediate destination types of the conversions, only at 
the final type. This means that the code for, say, pointer conversion 
must be able to handle both pointer conversion and qualification 
conversion at the same time, even though they should be done in separate 
steps.

The reason I'm stumbling onto this is because there is (what seems to 
be?) a hack in IsQualificationConversion that prevents Clang from 
considering certain address space conversions as qualification 
conversions, even though they should be. Removing that causes Clang to 
create an ICS for "(__private void *)generic_char_ptr" of the form:

* Pointer conversion: "char *" -> "void *"
* Qualification conversion: "void *" -> "__private void *"

This sequence is correct. However, PerformImplicitConversion tries to 
have the pointer conversion handle the entire ICS, and this does not 
work as CheckPointerConversion cannot handle address space conversions. 
Adding the ability to emit address space conversions to it solves the 
problem, but it does not solve the case where the pointer conversion is 
a derived-to-base conversion instead, and that is less easy to solve.

Modifying PerformImplicitConversion to obey/verify the intermediate 
conversion types causes test failures, due to a bunch of different reasons:

* Many conversions of functions/function pointers omit the exception 
specifications in SCSes in interesting ways
* Some code (such as direct reference binding initialization) builds 
'identity' and derived-to-base SCSes with incorrect intermediate types
* Some manually built SCSes haven't actually set the intermediate types 
at all

There are probably a few more I've missed here.

Is it supposed to be this way? It feels like the method is taking 
shortcuts with the conversions and that the rest of the codebase has 
simply coded around this behavior.

For reference, the review with a comment about this is here: 
https://reviews.llvm.org/D62574#inline-636836

/ Bevin


More information about the cfe-dev mailing list