|
| 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