Challenge 2 – Unused assignments and conditions predetermined
This code defines a function Cruise.Control which computes a mode for automatically controlling a car speed, given the information provided by sensors on the position and speed of surrounding vehicles. The mode distinguishes various levels of breaking and speeding.
Have a look at the following code and see if you can spot the errors. Once you think you’ve got them all, click on the “Go CodePeer” button to see how well you matched up to CodePeer’s comprehensive and rapid analysis of the same code.
Error line 84: “condition predetermined because (Time_Collision_Rear = +0) is always false”
Here’s how CodePeer helps you coming to this conclusion: CodePeer detects that Time_Collision_Rear cannot be non-negative when Time_Collision_Front is non-negative. (A short-circuit boolean operator is used.) Since they are initialized to -1.0 on lines 70 and 71, they can only be both non-negative if the tests on lines 73 and 77 succeed. CodePeer’s warning indicates that this is not possible. Looking more closely at the variables involved in these tests, we realize that Rear_Speed is wrongly initialized to ST.Speeds (Front) on line 68!
Error line 87: “dead code because (Time_Collision_Front >= 0.0 and then Time_Collision_Rear >= +0) = false”
Here’s how CodePeer helps you coming to this conclusion: Since Time_Collision_Rear and Time_Collision_Front cannot both be non-negative, as seen in the previous warning, the test on line 84 always fails, which makes the block of code starting on line 87 dead.
Error line 111: “unused assignment into Front_Speed”
Here’s how CodePeer helps you coming to this conclusion: Front_Speed is assigned on line 102 but is never used. Looking at where the algorithm is expected to use it, this reveals a bug on line 111 where Front_Speed should be used in place of Rear_Speed.
Error line 121: “condition predetermined because (Rear_Distance < Sec_Dist_Rear) is always false”
Here’s how CodePeer helps you coming to this conclusion: CodePeer detects that Rear_Distance cannot be less than Sec_Dist_Rear on line 121. Indeed, the same test used on line 116 prevents executions where this inequality holds to reach line 121. This is because the ‘or else’ boolean operator on line 115 should be an ‘and then’.
package Cruise is
type Mode is (Hard_Braking, Braking, Steady, Speeding, Hard_Speeding);
subtype Speeding_Mode is Mode range Speeding .. Hard_Speeding;
subtype Braking_Mode is Mode range Hard_Braking .. Braking;
subtype Soft_Mode is Mode range Braking .. Speeding;
type Vehicle is (Self, Front, Rear);
subtype Other_Vehicle is Vehicle range Front .. Rear;
type Speed is new Natural range 0 .. 200; -- Speed in km/h
type Distance is new Natural range 0 .. 200; -- Distance in m
type Vehicle_Speeds is array (Vehicle) of Speed;
type Other_Vehicle_Distances is array (Other_Vehicle) of Distance;
-- Sensors are polled every 100ms to compute the following information
-- about the position and speed of the vehicle w.r.t. the preceding (Front)
-- vehicle and the following (Rear) vehicle
type State is record
Speeds : Vehicle_Speeds;
Distances : Other_Vehicle_Distances;
Front_Braking : Boolean;
end record;
-- Depending on the respective positions and speeds of the vehicles (self,
-- preceding and following ones), decide on proper action to take
function Control (ST : State) return Mode;
end Cruise;
package body Cruise is
-- Return the distance (in m) covered in 2s at speed S (in km/h)
function Security_Distance (S : Speed) return Distance is
begin
return Distance (S * 5 / 9);
end Security_Distance;
-- Prevent collision with preceding vehicle by braking appropriately
function Control_Braking (Front_Braking : Boolean) return Braking_Mode is
begin
if Front_Braking then
return Hard_Braking;
else
return Braking;
end if;
end Control_Braking;
-- Prevent collision with following vehicle by speeding appropriately
function Control_Speeding
(Self_Speed : Speed;
Front_Distance : Distance) return Speeding_Mode is
begin
if Front_Distance < Security_Distance (Self_Speed) then
return Speeding;
else
return Hard_Speeding;
end if;
end Control_Speeding;
-- Optimize position of vehicle w.r.t. preceding and following vehicles
-- to balance the risks of collision with both vehicles
function Control_Position (ST : State) return Soft_Mode is
Front_Speed : Speed := ST.Speeds (Front);
Front_Distance : Distance := ST.Distances (Front);
Self_Speed : Speed := ST.Speeds (Self);
Rear_Speed : Speed := ST.Speeds (Front);
Rear_Distance : Distance := ST.Distances (Rear);
Time_Collision_Front : Float := -1.0;
Time_Collision_Rear : Float := -1.0;
begin
if Front_Speed < Self_Speed then
Time_Collision_Front :=
Float (Front_Distance) / Float (Self_Speed - Front_Speed);
end if;
if Self_Speed < Rear_Speed then
Time_Collision_Rear :=
Float (Rear_Distance) / Float (Rear_Speed - Self_Speed);
end if;
if Time_Collision_Front < 0.0 and then Time_Collision_Rear < 0.0 then
-- No risk of collision
return Steady;
elsif Time_Collision_Front >= 0.0 and then Time_Collision_Rear >= 0.0
then
-- Risk of collision with both preceding and following vehicles
if Time_Collision_Front < Time_Collision_Rear then
return Braking;
else
return Speeding;
end if;
elsif Time_Collision_Front < 0.0 then
-- Risk of collision with following vehicle only
return Speeding;
else
-- Risk of collision with preceding vehicle only
return Braking;
end if;
end Control_Position;
function Control (ST : State) return Mode is
Front_Speed : Speed := ST.Speeds (Front);
Front_Distance : Distance := ST.Distances (Front);
Front_Braking : Boolean := ST.Front_Braking;
Self_Speed : Speed := ST.Speeds (Self);
Rear_Speed : Speed := ST.Speeds (Rear);
Rear_Distance : Distance := ST.Distances (Rear);
Sec_Dist_Front : Distance := Security_Distance (Self_Speed);
Sec_Dist_Rear : Distance := Security_Distance (Rear_Speed);
begin
if Rear_Speed < Self_Speed and then
Front_Distance < Sec_Dist_Front then
-- Brake if preceding vehicle is close and we are approaching it
return Control_Braking (Front_Braking => Front_Braking);
elsif Self_Speed < Rear_Speed or else
Rear_Distance < Sec_Dist_Rear then
-- Speed-up if following vehicle is close and approaching us
return Control_Speeding (Self_Speed => Self_Speed,
Front_Distance => Front_Distance);
elsif Front_Distance < Sec_Dist_Front or else
Rear_Distance < Sec_Dist_Rear then
-- Maintain equivalent time-to-impact with preceding and following
-- vehicles if both are close
return Control_Position (ST);
else
return Steady;
end if;
end Control;
end Cruise;