Main Content

Invalid shift operations

Shift operations are invalid

Description

This check on shift operations on a variable var determines:

  • Whether the shift amount is larger than the range allowed by the type of var.

  • If the shift is a left shift, whether var is negative.

Examples

expand all

#include <stdlib.h>
#define shiftAmount 32
enum shiftType {
 SIGNED_LEFT,
 SIGNED_RIGHT,
 UNSIGNED_LEFT,
 UNSIGNED_RIGHT
};

enum shiftType getShiftType();

void main() {
  enum shiftType myShiftType = getShiftType();
  int signedInteger = 1;
  unsigned int unsignedInteger = 1;
  switch(myShiftType) {
  case SIGNED_LEFT: 
    signedInteger = signedInteger << shiftAmount;
    break;
  case SIGNED_RIGHT: 
    signedInteger = signedInteger >> shiftAmount;
    break;
  case UNSIGNED_LEFT: 
    unsignedInteger = unsignedInteger << shiftAmount;
    break;
  case UNSIGNED_RIGHT: 
    unsignedInteger = unsignedInteger >> shiftAmount;
    break;
  }
}

In this example, the shift amount shiftAmount is outside the allowed range for both signed and unsigned int. Therefore the Invalid shift operations check produces a red error.

Correction — Keep shift amount within bounds

One possible correction is to keep the shift amount in the range 0..31 for unsigned integers and 0...30 for signed integers. This correction works if the size of int is 32 on the target processor.

#include <stdlib.h>
#define shiftAmountSigned 30
#define shiftAmount 31
enum shiftType {
 SIGNED_LEFT,
 SIGNED_RIGHT,
 UNSIGNED_LEFT,
 UNSIGNED_RIGHT
};

enum shiftType getShiftType();

void main() {
  enum shiftType myShiftType = getShiftType();
  int signedInteger = 1;
  unsigned int unsignedInteger = 1;
  switch(myShiftType) {
  case SIGNED_LEFT: 
    signedInteger = signedInteger << shiftAmountSigned;
  
    break;
  case SIGNED_RIGHT: 
    signedInteger = signedInteger >> shiftAmountSigned;
  
    break;
  case UNSIGNED_LEFT: 
    unsignedInteger = unsignedInteger << shiftAmount;
  
     break;
  case UNSIGNED_RIGHT: 
    unsignedInteger = unsignedInteger >> shiftAmount;
  
    break;
  }
}
void main(void) {
  int x = -200;
  int y;
  y = x << 1; 
}

In this example, the left operand of the left shift operation is negative.

Correction — Use Polyspace analysis option

You can use left shifts on negative numbers and not produce a red Invalid shift operations error. To allow such left shifts, on the Configuration pane, under Check Behavior, select Allow negative operand for left shifts.

void main(void) {
  int x = -200;
  int y;
  y = x << 1; 
}
short getVal();

int foo(void) {
  long lvar;
  short svar1, svar2;

  lvar = 0;
  svar1 = getVal();
  svar2 = getVal();

  lvar =  (svar1 - svar2) << 10;
  if (svar1 < svar2)  {
    return 1;
  } else {
    return 0;
  }
}

int main(void) {
  return foo();
}

In this example, if svar1 < svar2, the left operand of << can be negative. Therefore the Shift operations check on << is orange. Following an orange check, execution paths containing the error get truncated. Therefore, following the orange Invalid shift operations check, Polyspace® assumes that svar1 >= svar2. The branch of the statement, if(svar1 < svar2), is unreachable.

Check Information

Group: Numerical
Language: C | C++
Acronym: SHF