rspec/rules/S6191/cfamily/rule.adoc

49 lines
2.2 KiB
Plaintext
Raw Normal View History

When a variable appears in a compound expression (for instance ``a{plus}{plus}`` or `a+=2`), the variable is accessed twice. This detail only matters for `volatile` variables. And it may not be obvious to all developers that two accesses happen while the variable is only named once. The standard was not explicit on this topic up until {cpp}23.
2021-04-28 16:49:39 +02:00
As a consequence, it is usually clearer to rewrite the code so that the variable appears twice, matching the accesses that will happen.
2021-04-28 16:49:39 +02:00
In C++, it usually does not matter how many times you access a variable, as long as the variable value is the right one. This is not the case when the variable is in a memory region that is mapped to external hardware. In that case, for instance, several successive reads can yield different values (if the memory is updated by the hardware in-between) and several writes of the same value may be significant (some hardware trigger events each time a memory location is written to).
2021-04-28 16:49:39 +02:00
To specify that every read and write has an impact outside of the abstract machine of the language, access to a variable may be qualified as `volatile`. In that case, the program must perform all reads and writes that are specified, without optimizing anything away.
Note: In {cpp}20, compound expressions on volatile variables were deprecated. This deprecation was removed in {cpp}23, and the number of accesses was made explicit. The reason for removing the deprecation is that such operations are commonly used in embedded code, especially to access specific bits of a variable. However, using a function with a dedicated name instead of direct bit manipulation usually leads to code that is easier to read.
2021-04-28 16:49:39 +02:00
== Noncompliant Code Example
2022-02-04 17:28:24 +01:00
[source,cpp]
2021-04-28 16:49:39 +02:00
----
void f1(int volatile* p) {
++(*p); // Noncompliant
}
void f2(volatile int& in) {
in += 2; // Noncompliant
}
void f3(volatile int& in) {
int i = in = 2; // Noncompliant
}
----
2021-04-28 16:49:39 +02:00
== Compliant Solution
2022-02-04 17:28:24 +01:00
[source,cpp]
2021-04-28 16:49:39 +02:00
----
void f1(int volatile* p) {
auto val = *p; // One access to read the register
*p = val + 1; // One access to write to it (and potentially overwrite another change)
}
void f2(volatile int& in) {
auto val = in;
in = val + 2;
}
void f3(volatile int& in) {
in = 2;
int i = in;
}
----