Skip to main content

Conv

Struct Conv 

Source
pub struct Conv<'a> {
    pub tast: &'a mut Tast,
    pub types: &'a mut Types,
    pub target: &'a TargetInfo,
}
Expand description

Everything a conversion needs: the tree to write the node into and the table to ask.

Three references rather than a pass-wide context, because the conversions are the part of semantic analysis with no state of its own and nothing else here should be able to reach the scopes or the diagnostics through them.

Fields§

§tast: &'a mut Tast

The tree the nodes are written into.

§types: &'a mut Types

The types, which conversions extend.

§target: &'a TargetInfo

What the target’s integers are, which is what the promotions are decided by.

Implementations§

Source§

impl Conv<'_>

Source

pub fn value(&mut self, expr: ExprId) -> ExprId

The value of an expression: 6.3.2.1, with the decays that replace it.

An array becomes a pointer to its first element, a function becomes a pointer to itself, and everything else that is an lvalue is read. An expression that is already a value is its own answer, so this can be called on any operand without asking what it is first.

Source

pub fn promote(&mut self, expr: ExprId) -> ExprId

The value of an expression with the integer promotions applied, 6.3.1.1.

Anything narrower than int becomes int, or unsigned int where int cannot hold every value it had. A floating type, a pointer and a _BitInt are each their own answer, the last because C23 6.3.1.1p2 says so and because that is the point of the type: it is the one integer type in C that does what it says.

Source

pub fn promote_bits(&mut self, expr: ExprId, width: u32) -> ExprId

The value of a bit-field with the integer promotions applied to its width.

A bit-field is narrower than the type it was declared with, and it is the width that decides. The caller passes the width because the tree holds the field index and the width is a fact about the record, not about the expression.

Source

pub fn usual_arithmetic( &mut self, lhs: ExprId, rhs: ExprId, ) -> Option<(ExprId, ExprId)>

The usual arithmetic conversions, 6.3.1.8: both operands converted to one type.

None where either operand is not arithmetic, which is not a failure of this rule but a question it does not answer, since p + 1 is pointer arithmetic and never reaches it.

Source

pub fn to_bool(&mut self, expr: ExprId) -> ExprId

A scalar as a condition, which is a comparison against zero and not a truncation.

That is why it is Conversion::Bool rather than Conversion::Arithmetic: (bool) 256 is true and (char) 256 is zero, and a compiler that treats the two the same is wrong about one of them.

Source

pub fn to_void(&mut self, expr: ExprId) -> ExprId

A value discarded, which is what a cast to void does.

An expression statement does not write one of these, even though it discards a value too. The statement is what does the discarding, and a statement expression’s value is the last statement’s, so an expression statement that had thrown its type away would have nothing left to give.

Source

pub fn to_type(&mut self, expr: ExprId, ty: TypeId) -> ExprId

A value converted to a given type, with the kind of conversion worked out from the two.

This is what an assignment, an argument, a return and an initializer all do. It writes the conversion the pair calls for and does not judge whether the pair is allowed: the caller has the span and the wording, and a conversion that should have been diagnosed is a diagnostic the caller owes rather than a node this refuses to write.

Source

pub fn is_null_pointer_constant(&self, expr: ExprId) -> bool

Whether an expression is a null pointer constant, 6.3.2.3p3.

An integer constant expression with the value zero, or such an expression cast to void *. The casts and the conversions are looked through because (void *)0 is one and so is (long)0, and stopping at the first node would see a cast rather than a zero.

Trait Implementations§

Source§

impl<'a> Debug for Conv<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> !UnwindSafe for Conv<'a>

§

impl<'a> Freeze for Conv<'a>

§

impl<'a> RefUnwindSafe for Conv<'a>

§

impl<'a> Send for Conv<'a>

§

impl<'a> Sync for Conv<'a>

§

impl<'a> Unpin for Conv<'a>

§

impl<'a> UnsafeUnpin for Conv<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.