LHS of a << operand being implicitly cast to int

i have the following sample code:

short unsigned int port = 0x005aU;
unsigned char portchar = 0x005aU;
short unsigned int resultshort;

resultshort = port << 4U;
resultshort = portchar << 4U;

resultshort = port << 4U;
resultshort = portchar << 4U;
resultshort = (unsigned short int)(portchar << 4U);

Here's the AST dump for the last three lines:
-BinaryOperator 0x557ff78 <line:337:3, col:25> 'unsigned short' '='

  > >-DeclRefExpr 0x557fe98 <col:3> 'unsigned short' lvalue Var

0x557fbb8 'resultshort' 'unsigned short'

  > `-ImplicitCastExpr 0x557ff60 <col:17, col:25> 'unsigned short'

<IntegralCast>

  > `-BinaryOperator 0x557ff38 <col:17, col:25> 'int' '<<'
  > >-ImplicitCastExpr 0x557ff20 <col:17> 'int' <IntegralCast>
  > > `-ImplicitCastExpr 0x557ff08 <col:17> 'unsigned short'

<LValueToRValue>

  > > `-DeclRefExpr 0x557fec0 <col:17> 'unsigned short' lvalue

Var 0x557fa28 'port' 'unsigned short'

  > `-IntegerLiteral 0x557fee8 <col:25> 'unsigned int' 4

-BinaryOperator 0x5580080 <line:338:3, col:29> 'unsigned short' '='
  > >-DeclRefExpr 0x557ffa0 <col:3> 'unsigned short' lvalue Var

0x557fbb8 'resultshort' 'unsigned short'

  > `-ImplicitCastExpr 0x5580068 <col:17, col:29> 'unsigned short'

<IntegralCast>

  > `-BinaryOperator 0x5580040 <col:17, col:29> 'int' '<<'
  > >-ImplicitCastExpr 0x5580028 <col:17> 'int' <IntegralCast>
  > > `-ImplicitCastExpr 0x5580010 <col:17> 'unsigned char'

<LValueToRValue>

  > > `-DeclRefExpr 0x557ffc8 <col:17> 'unsigned char' lvalue

Var 0x557faf0 'portchar' 'unsigned char'

  > `-IntegerLiteral 0x557fff0 <col:29> 'unsigned int' 4

-BinaryOperator 0x5580620 <line:339:3, col:52> 'unsigned short' '='
  > >-DeclRefExpr 0x55800a8 <col:3> 'unsigned short' lvalue Var

0x557fbb8 'resultshort' 'unsigned short'

  > `-CStyleCastExpr 0x55805f8 <col:17, col:52> 'unsigned short'

<IntegralCast>

  > `-ParenExpr 0x55805d8 <col:37, col:52> 'int'
  > `-BinaryOperator 0x5580148 <col:38, col:50> 'int' '<<'
  > >-ImplicitCastExpr 0x5580130 <col:38> 'int' <IntegralCast>
  > > `-ImplicitCastExpr 0x5580118 <col:38> 'unsigned char'

<LValueToRValue>

  > > `-DeclRefExpr 0x55800d0 <col:38> 'unsigned char'

lvalue Var 0x557faf0 'portchar' 'unsigned char'

  > `-IntegerLiteral 0x55800f8 <col:50> 'unsigned int' 4

switching "4U" with "const unsinged char constuchar=4U;" will still
result in the same thing, the RHS and LHS of a "<<" operator being
implicitly cast to int(signed and wider than the original type).
It appears to be a conscious choice on Clang's part given the possible
benefits. Am i correct in assuming that?
if yes, then is this target-dependent?
and is there a pass to disable this?

integer promotion rules says that char/short operands are promoted to int in calculations. please see the specification or other document for details.

..................................................................................................................
Daniel Marjamäki Senior Engineer
Evidente ES East AB Warfvinges väg 34 SE-112 51 Stockholm Sweden

Mobile: +46 (0)709 12 42 62
E-mail: Daniel.Marjamaki@evidente.se

www.evidente.se

I understand. thank you.