Skip to content

Commit 69ee88e

Browse files
committed
Add documentation
1 parent 1e21c8d commit 69ee88e

2 files changed

Lines changed: 195 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# duplicateExpressionTernary
2+
3+
**Message**: Same expression in both branches of ternary operator<br/>
4+
**Category**: Logic<br/>
5+
**Severity**: Style<br/>
6+
**Language**: C/C++
7+
8+
## Description
9+
10+
This checker detects when syntactically identical expressions appear in both the true and false branches of a ternary operator (`condition ? true_expr : false_expr`). When this occurs, the result of the ternary operator is always the same regardless of the condition, which is usually a logic error or copy-paste mistake.
11+
12+
The key difference from `duplicateValueTernary` is:
13+
- `duplicateExpressionTernary`: Triggered when expressions are syntactically **identical** (e.g., `x` and `x`, or `(int)1` and `(int)1`)
14+
- `duplicateValueTernary`: Triggered when expressions have the same **value** but different syntax (e.g., `1` and `(int)1`)
15+
16+
The warning is triggered when:
17+
- The second and third operands of a ternary operator are syntactically identical expressions
18+
- This includes cases where variables are referenced through aliases that resolve to the same expression
19+
20+
However, no warning is generated when:
21+
- The expressions have different values on different platforms (e.g., `sizeof(uint32_t)` vs `sizeof(unsigned int)` which may differ across platforms)
22+
- The expressions involve platform-dependent behavior
23+
24+
## Examples
25+
26+
### Problematic code
27+
28+
```cpp
29+
// Same expression in both branches
30+
int result = condition ? x : x; // Warning: duplicateExpressionTernary
31+
32+
// Same variable referenced through alias
33+
const int c = a;
34+
int result = condition ? a : c; // Warning: duplicateExpressionTernary
35+
36+
// Identical expressions with same syntax
37+
int result = condition ? 1 : 1; // Warning: duplicateExpressionTernary
38+
int result = condition ? (int)1 : (int)1; // Warning: duplicateExpressionTernary
39+
```
40+
41+
### Code that triggers duplicateValueTernary instead
42+
43+
```cpp
44+
// Different syntax, same value (triggers duplicateValueTernary, not duplicateExpressionTernary)
45+
int result = condition ? 1 : (int)1; // Warning: duplicateValueTernary
46+
int result = condition ? (int)42 : 42; // Warning: duplicateValueTernary
47+
```
48+
49+
### Fixed code
50+
51+
```cpp
52+
// Different expressions in branches
53+
int result = condition ? x : y; // OK
54+
55+
// Platform-dependent sizes are allowed
56+
int size = is_32bit ? sizeof(uint32_t) : sizeof(unsigned int); // OK - may differ on platforms
57+
```
58+
59+
### Exception: Platform-dependent expressions
60+
61+
```cpp
62+
// This does NOT generate a warning because sizeof may differ across platforms
63+
typedef float _Complex complex_f32;
64+
typedef struct {
65+
uint16_t real;
66+
uint16_t imag;
67+
} packed_complex;
68+
69+
int size = condition ? sizeof(packed_complex) : sizeof(complex_f32); // OK
70+
```
71+
72+
## How to fix
73+
74+
1. **Check for copy-paste errors**: Verify that both branches are supposed to have the same expression
75+
2. **Use different expressions**: If the branches should differ, update one of them
76+
3. **Simplify the code**: If both branches are intentionally the same, remove the ternary operator entirely
77+
78+
Before:
79+
```cpp
80+
int getValue(bool flag) {
81+
return flag ? computeValue() : computeValue(); // Same computation in both branches
82+
}
83+
```
84+
85+
After:
86+
```cpp
87+
int getValue(bool flag) {
88+
return computeValue(); // Simplified - condition doesn't matter
89+
}
90+
```
91+
92+
Or if the branches should differ:
93+
```cpp
94+
int getValue(bool flag) {
95+
return flag ? computeValue() : computeAlternativeValue(); // Different computations
96+
}
97+
```
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# duplicateValueTernary
2+
3+
**Message**: Same value in both branches of ternary operator<br/>
4+
**Category**: Logic<br/>
5+
**Severity**: Style<br/>
6+
**Language**: C/C++
7+
8+
## Description
9+
10+
This checker detects when both branches of a ternary operator (`condition ? true_expr : false_expr`) evaluate to the same value, even though the expressions themselves may be syntactically different. This usually indicates a logic error where the condition serves no purpose since the result is always the same.
11+
12+
The key difference from `duplicateExpressionTernary` is:
13+
- `duplicateValueTernary`: Triggered when expressions have the same **value** (e.g., `1` and `(int)1`)
14+
- `duplicateExpressionTernary`: Triggered when expressions are syntactically **identical** (e.g., `x` and `x`)
15+
16+
The warning is triggered when:
17+
- The second and third operands of a ternary operator evaluate to the same constant value
18+
- The expressions are constant statements that don't change during evaluation
19+
- The expressions have different syntax but equivalent values
20+
21+
However, no warning is generated when:
22+
- The expressions have different values on different platforms
23+
- Variables are modified between evaluations
24+
- The expressions involve non-constant computations
25+
26+
## Examples
27+
28+
### Problematic code
29+
30+
```cpp
31+
// Different expressions, same value
32+
int result = condition ? (int)1 : 1; // Warning: duplicateValueTernary
33+
34+
// Different cast syntax, same value
35+
int result = condition ? 1 : (int)1; // Warning: duplicateValueTernary
36+
37+
// Same constant value with different representations
38+
int result = condition ? (int)1 : 1; // Warning: duplicateValueTernary
39+
```
40+
41+
### Code that correctly triggers duplicateExpressionTernary instead
42+
43+
```cpp
44+
// Identical expressions (not just values)
45+
int result = condition ? 1 : 1; // Warning: duplicateExpressionTernary
46+
int result = condition ? (int)1 : (int)1; // Warning: duplicateExpressionTernary
47+
```
48+
49+
### Fixed code
50+
51+
```cpp
52+
// Different values in branches
53+
int result = condition ? 1 : 2; // OK
54+
55+
// Simplified - condition doesn't matter
56+
int result = 1; // OK - removed unnecessary ternary
57+
58+
// Platform-dependent values are allowed
59+
int size = is_64bit ? sizeof(long) : sizeof(int); // OK - may differ on platforms
60+
```
61+
62+
### Exception: Platform-dependent values
63+
64+
```cpp
65+
// This may NOT generate a warning if values differ across platforms
66+
int size = condition ? sizeof(long) : sizeof(int); // OK on some platforms
67+
68+
// Special case: +0.0 vs -0.0 are considered different
69+
double result = condition ? 0.0 : -0.0; // OK - different floating-point values
70+
```
71+
72+
## How to fix
73+
74+
1. **Check for logic errors**: Verify if both branches should actually have the same value
75+
2. **Simplify the code**: If both branches always have the same value, remove the ternary operator
76+
3. **Use different values**: If the branches should differ, update one of them
77+
4. **Remove unnecessary casts**: If the difference is only in casting, consider if the cast is needed
78+
79+
Before:
80+
```cpp
81+
int getValue(bool flag) {
82+
return flag ? (int)42 : 42; // Same value, different expressions
83+
}
84+
```
85+
86+
After (simplified):
87+
```cpp
88+
int getValue(bool flag) {
89+
return 42; // Simplified - condition doesn't affect result
90+
}
91+
```
92+
93+
Or (if branches should differ):
94+
```cpp
95+
int getValue(bool flag) {
96+
return flag ? 42 : 0; // Different values for different conditions
97+
}
98+
```

0 commit comments

Comments
 (0)