Code Prover Assumptions About Volatile Variables
A Polyspace® analysis assumes that values of volatile variables can change without explicit write operations.
Global Volatile Variables
For global volatile variables:
Polyspace assumes that the variable has a full range of values allowed by its type.
You can constrain the range externally. See Constrain Global Variable Range for Polyspace Analysis.
Even if you do not explicitly initialize the variable, when you read the variable, Polyspace produces a green Non-initialized variable check.
Local Volatile Variables
For local volatile variables:
Polyspace assumes that the variable has a full range of values allowed by its type.
Unless you explicitly initialize the variable, when you read the variable, Polyspace produces an orange Non-initialized local variable check.
In this example, Polyspace assumes that val1
is potentially noninitialized but val2
is initialized. Polyspace considers that the +
operation can cause an overflow because it assumes both variables to have all possible values allowed by their data types.
int func (void) { volatile int val1, val2=0; return( val1 + val2); }
If the root cause of an orange check is a local volatile variable, you cannot override the default assumptions and constrain the values of the volatile variables. Try one of the following:
If the volatile variable represents hardware-supplied data, see if you can use a function call to model this data retrieval. For example, replace
volatile int port_A
withint port_A = read_location()
. You do not have to define the function. Polyspace stubs the undefined functions. You can then specify constraints on the function return values using the optionConstraint setup (-data-range-specifications)
.See if you can copy the contents of the volatile variable to a global nonvolatile variable. You can then constrain the global variable values throughout your code. See Constrain Global Variable Range for Polyspace Analysis.
Replace the volatile variable with a stubbed function, but only for verification. Before verification, specify constraints on the stubbed functions.
Write a Perl script that replaces each volatile variable declaration with a nonvolatile declaration where you obtain the variable value from a function call.
For example, if your code contains the line
volatile s8 PORT_A
, your Perl script can contain this substitution:$line=~ s/^\s*volatile\s*s8\s*PORT_A;/s8 PORT_A = random_s8();/g;
Specify the location of this Perl script for the analysis option
Command/script to apply to preprocessed files (-post-preprocessing-command)
.In an include file, provide the function declaration. For example, for a function
random_s8
, the include file can contain the following declaration:#ifndef POLYSPACE_H #define POLYSPACE_H signed char random_s8(void); #endif
Insert a
#include
directive for your include file in the relevant source filesInstead of a manual insertion, specify the location of your include file for the analysis option
Include (-include)
.
Volatile Parameters
A volatile
qualifier on a pass-by-copy function parameter is ignored because the copied parameters cannot be memory-mapped to I/O registers and are not likely to change their values without explicit write operations in the code. The volatile
qualifier continues to apply on pass-by-reference parameters.
In this example, the argument x
is passed by copy and y
by reference. The analysis does not apply the volatile
assumption of full-range values to the first parameter but continues to apply them to the variable that the second parameter points
to.
void foo(volatile int x, volatile int *y_ptr) { x = 1; assert(x==1); *y_ptr = 1; assert(*y_ptr==1); } void foo_caller(void) { volatile int x; volatile int y; x = 1; assert(x==1); y = 1; assert(y==1); foo(x, &y); }