﻿# V2667\. MISRA\. The value of an expression and its persistent side effects must be the same under all permitted evaluation orders and must be independent from thread interleaving\.

This diagnostic rule is based on the [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) software development guidelines\.

This diagnostic rule is relevant only for C and C\+\+ until the C\+\+11 standard\.

The analyzer has detected unordered volatile operations on the same object\. The behavior of such operations is undefined, and they may lead to unexpected program behavior\.

The C and C\+\+ standards allows compiler to freely set the order of evaluation to achieve code optimization\. As a result, the intended sequence of operations should be defined manually\.

To avoid unexpected results or undefined behavior between two adjacent **sequence points**, the MISRA standard prohibits:

1. modify an object more than once;
1. modify and read an object, unless the read contributes to the evaluation of the object value;
1. modify more than one `volatile` or atomic object;
1. read more than one `volatile` object or the same `volatile` object more than once;
1. read the same atomic object more than once\.

**Note N1**\. The `volatile` object refers to a variable declared with the `volatile` qualifier or a structure data member declared with this qualifier\.

The example:

```cpp
volatile int a;
const volatile char b = 5;
volatile int* pointer;
_Atomic volatile int av;
  
struct TestStruct
{
  int x;
};
volatile TestStruct ts;
```

Both `ts` and `ts.x` are `volatile`\-objects\.

The atomic object is a variable declared with the `_Atomic(....)` specifier or the `_Atomic` qualifier, or the structure data member declared with such a specifier or qualifier\. 

The example:

```cpp
_Atomic int a;
_Atomic const float f = 1.0;
_Atomic(char) c;
atomic_long l;
_Atomic volatile int av;
  
struct TestStruct
{
  int x;
};
_Atomic TestStruct ts;
```

In this example, both `ts` and `ts.x` are atomicobjects\.

**Note N2**\. In imperative programming, a sequence point is a point in a program where it is guaranteed that all side effects of previous evaluations have already completed, and the side effects of subsequent computations have not completed yet\. In the C language, sequence points are described in [Annex C](https://open-std.org/JTC1/SC22/WG14/www/docs/n1570.pdf#page=521) of the standard\.

**Note N3**\. All expression subobjects are handled for determining read/write regardless of any known values\.

The example:

```cpp
int n = 1;
int m = n || n++ + n;
```

Even though the `n++ + n` expression is never executed in this context, the analyzer will still issue a warning\.

Look at examples for each rule requirement\.

**The example N1**\. It is prohibited to modify an object more than once between adjacent sequence points:

```cpp
int n, m;
n = n++;
n = ++n + n;
n = (n = 4);
m = n++ + ++n;
foo(n++, n++);
```

In each line, `n` is modified twice, which violates the requirement N1\.

The fixed code:

```cpp
n = m++;
n = m + m * 200;
n = 4 + (m = 2);
n = m = n + m;
foo(n++, m++);
```

**The example N2**\. It is prohibited to modify or read an object unless the read contributes to the evaluation of the object value:

```cpp
int n, m;
int m = n + (n = 2);
m = n++ + n;
m = foo(n, n++);
```

In each line, `n` is modified and read, which violates requirement N2\.

The fixed code: 

```cpp
n = n + 2;
n++;
m = n++;
```

Although `n` is modified and read in each line, the `n` variable is only read to evaluate the new `n` value\.

**The example N3**\. It is prohibited to modify more than one `volatile` or atomic object\.

```cpp
volatile int volat1, volat2;
_Atomic int atom1, atom2;
int n = atom1++ + atom2++;       // <= (A2)
n = (atom1 = 0) + (atom2 = 1);   // <= (A2)
n = atom1++ + volat1++;          // <= (A1V1)
n = (atom1 = 0) + (volat1 = 1);  // <= (A1V1)
n = volat1++ + volat2++;         // <= (V2)
n = (volat1 = 0) + (volat2 = 1); // <= (V2)
```

This example demonstrates:

* in the lines marked `A2`, two atomic objects are modified;
* in the lines marked `A1V1`, one atomic and one `volatile` object are modified;
* in the lines marked `V2`, two `volatile` objects are modified\.

All of these cases violate requirement N3\.

The fixed code:

```cpp
volat1++;
n = atom1++;
n = (volat1 = 0) + atom1;
n = (volat1 = 0, volat2 = 1);         // <= (SP)
m = (volat1 = n) || (volat2 = n + 1); // <= (SP)
```

In each line marked `SP`, modifications occur out of adjacent sequence points\.

**The example N4**\. It is prohibited to read more than one `volatile` object or the same `volatile` object more than once:

```cpp
volatile int volat1, volat2;
_Atomic int atom1, atom2;
int n = volat1 + volat1; // <= (V1)
n = volat1 + volat2;     // <= (V2)
foo(volat1, volat1);     // <= (V1)
foo(volat1, volat2);     // <= (V2)
```

In this example, `volatile` objects are read during addition operations and when passing arguments by copy to a function call\. 

This example demonstrates: 

* in the lines marked `V1`, the same `volatile` object is read more than once;
* in the lines marked `V2`, two `volatile` objects are read\.

All of these cases violate requirement N4\.

The fixed code:

```cpp
n = volat1;
volat1 = volat2;
volat1 = volat1 + 42;
foo(volat1, n);
```

**The example N5**\. It is prohibited to read the same atomic object more than once\.

```cpp
_Atomic int atom1, atom2;
int n = atom1 + atom1;
foo(atom1, atom1);
n = foo(atom1, 0) + atom1;
```

In this example, atomic objects are read during addition operations and when arguments are passed by value to a function call\. All of these cases violate the rule requirement N5\.

The fixed code:

```cpp
n = atom1 + atom2;
atom1 = atom1 + 42;
n = atom1 && atom1;       // <= (SP)
n = foo(atom1, 0), atom1; // <= (SP)
```

In each line marked `SP`, reading occurs out of adjacent sequence points\.