Skip to content

Commit d0ca048

Browse files
authored
Merge pull request #116 from lcartey/a5-2-2/issue-32/c-style-casts-from-macros
A5-2-2: Exclude c-style casts generated from library macros, and improve message
2 parents 504d5f8 + 13df5e3 commit d0ca048

File tree

6 files changed

+86
-7
lines changed

6 files changed

+86
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- `A5-2-2` - `TraditionalCStyleCastsUsed.ql`
2+
- Reduced false positives by excluding casts generated by library macros (i.e. macros defined outside the source location)
3+
- Improved the message to cite the macro which generated the c-style cast, if any.
4+
- Improved the message to cite the type being casted to, to aid with identification and remediation.

cpp/autosar/src/rules/A5-2-2/TraditionalCStyleCastsUsed.ql

+49-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,55 @@
1616
import cpp
1717
import codingstandards.cpp.autosar
1818

19-
from CStyleCast c
19+
/**
20+
* Gets the macro (if any) that generated the given `CStyleCast`.
21+
*
22+
* If there are nested macro invocations, we identify the most specific macro that generated the
23+
* cast.
24+
*/
25+
Macro getGeneratedFrom(CStyleCast c) {
26+
exists(MacroInvocation mi |
27+
mi = result.getAnInvocation() and
28+
mi.getAGeneratedElement() = c and
29+
mi.getLocation().getStartColumn() = c.getLocation().getStartColumn() and
30+
not exists(MacroInvocation child |
31+
child.getParentInvocation() = mi and
32+
child.getAGeneratedElement() = c
33+
)
34+
)
35+
}
36+
37+
/** A macro within the source location of this project. */
38+
class UserProvidedMacro extends Macro {
39+
UserProvidedMacro() { exists(this.getFile().getRelativePath()) }
40+
}
41+
42+
/** A macro defined within a library used by this project. */
43+
class LibraryMacro extends Macro {
44+
LibraryMacro() { not this instanceof UserProvidedMacro }
45+
}
46+
47+
from CStyleCast c, string extraMessage, Locatable l, string supplementary
2048
where
2149
not isExcluded(c, BannedSyntaxPackage::traditionalCStyleCastsUsedQuery()) and
2250
not c.isImplicit() and
23-
not c.getType() instanceof UnknownType
24-
select c, "Use of explicit C-style Cast"
51+
not c.getType() instanceof UnknownType and
52+
// Exclude casts created from macro invocations of macros defined by third parties
53+
not getGeneratedFrom(c) instanceof LibraryMacro and
54+
// If the cast was generated from a user-provided macro, then report the macro that generated the
55+
// cast, as the macro itself may have generated the cast
56+
if getGeneratedFrom(c) instanceof UserProvidedMacro
57+
then
58+
extraMessage = " generated from macro $@" and
59+
// Add macro as explanatory link
60+
l = getGeneratedFrom(c) and
61+
supplementary = getGeneratedFrom(c).getName()
62+
else (
63+
// No extra message required
64+
extraMessage = "" and
65+
// No explanatory link required, but we still need to set these to valid values
66+
l = c and
67+
supplementary = ""
68+
)
69+
select c, "Use of explicit c-style cast to " + c.getType().getName() + extraMessage + ".", l,
70+
supplementary
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
| test.cpp:8:22:8:37 | (uint32_t)... | Use of explicit C-style Cast |
2-
| test.cpp:9:22:9:32 | (unsigned int)... | Use of explicit C-style Cast |
3-
| test.cpp:15:3:15:13 | (void)... | Use of explicit C-style Cast |
1+
| test.cpp:8:22:8:37 | (uint32_t)... | Use of explicit c-style cast to uint32_t. | test.cpp:8:22:8:37 | (uint32_t)... | |
2+
| test.cpp:9:22:9:32 | (unsigned int)... | Use of explicit c-style cast to unsigned int. | test.cpp:9:22:9:32 | (unsigned int)... | |
3+
| test.cpp:15:3:15:13 | (void)... | Use of explicit c-style cast to void. | test.cpp:15:3:15:13 | (void)... | |
4+
| test.cpp:77:3:77:11 | (int)... | Use of explicit c-style cast to int generated from macro $@. | test.cpp:70:1:70:31 | #define ADD_ONE(x) ((int)x) + 1 | ADD_ONE |
5+
| test.cpp:79:3:79:18 | (int)... | Use of explicit c-style cast to int generated from macro $@. | test.cpp:71:1:71:36 | #define NESTED_ADD_ONE(x) ADD_ONE(x) | NESTED_ADD_ONE |
6+
| test.cpp:85:19:85:26 | (int)... | Use of explicit c-style cast to int. | test.cpp:85:19:85:26 | (int)... | |
7+
| test.cpp:86:27:86:34 | (int)... | Use of explicit c-style cast to int. | test.cpp:86:27:86:34 | (int)... | |

cpp/autosar/test/rules/A5-2-2/test.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,25 @@ class A5_2_2 final {
6565
void a5_2_2_test() {
6666
A5_2_2 a;
6767
a.f("");
68+
}
69+
70+
#define ADD_ONE(x) ((int)x) + 1
71+
#define NESTED_ADD_ONE(x) ADD_ONE(x)
72+
#define NO_CAST_ADD_ONE(x) x + 1
73+
74+
#include "macro_c_style_casts.h"
75+
76+
void test_macro_cast() {
77+
ADD_ONE(1); // NON_COMPLIANT - expansion of user-defined macro creates
78+
// c-style cast
79+
NESTED_ADD_ONE(1); // NON_COMPLIANT - expansion of user-defined macro creates
80+
// c-style cast
81+
LIBRARY_ADD_TWO(1); // COMPLIANT - macro generating the cast is defined in a
82+
// library, and is not modifiable by the user
83+
LIBRARY_NESTED_ADD_TWO(1); // COMPLIANT - macro generating the cast is defined
84+
// in a library, and is not modifiable by the user
85+
NO_CAST_ADD_ONE((int)1.0); // NON_COMPLIANT - cast in argument to macro
86+
LIBRARY_NO_CAST_ADD_TWO((int)1.0); // NON_COMPLIANT - library macro with
87+
// c-style cast in argument, written by
88+
// user so should be reported
6889
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Macros used in test for A5-2-2
2+
#define LIBRARY_ADD_TWO(x) ((int)x) + 2
3+
#define LIBRARY_NESTED_ADD_TWO(x) LIBRARY_ADD_TWO(x)
4+
#define LIBRARY_NO_CAST_ADD_TWO(x) x + 1

cpp/options

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
semmle-extractor-options:--clang -std=c++14 -nostdinc++ -I../../../../common/test/includes/standard-library
1+
semmle-extractor-options:--clang -std=c++14 -nostdinc++ -I../../../../common/test/includes/standard-library -I../../../../common/test/includes/custom-library

0 commit comments

Comments
 (0)