1
+ import cpp
2
+ import codingstandards.cpp.Macro
3
+ import codingstandards.cpp.MatchingParenthesis
4
+
5
+ string genericRegexp ( ) { result = ".*_Generic\\s*\\(\\s*(.+),.*" }
6
+
7
+ bindingset [ input]
8
+ string deparenthesize ( string input ) {
9
+ input = "(" + result + ")" and
10
+ result = input .substring ( 1 , input .length ( ) - 1 )
11
+ }
12
+
13
+
14
+ class GenericMacro extends Macro {
15
+ string ctrlExpr ;
16
+
17
+ GenericMacro ( ) { ctrlExpr = getBody ( ) .regexpCapture ( genericRegexp ( ) , 1 ) .trim ( ) }
18
+
19
+ string getAParameter ( ) { result = this .( FunctionLikeMacro ) .getAParameter ( ) }
20
+
21
+ string getControllingExprString ( ) {
22
+ if exists ( string s | s = deparenthesize ( ctrlExpr ) )
23
+ then result = deparenthesize ( ctrlExpr ) .trim ( )
24
+ else result = ctrlExpr
25
+ }
26
+
27
+ /**
28
+ * Whether the controlling expression of the `_Generic` expr in this macro's controlling
29
+ * expression refers to one of this macro's parameters.
30
+ */
31
+ predicate hasControllingExprFromMacroParameter ( ) {
32
+ getControllingExprString ( ) .matches ( getAParameter ( ) )
33
+ }
34
+ }
35
+
36
+ class GenericMacroString extends string {
37
+ GenericMacroString ( ) { this = any ( Macro m ) .getBody ( ) and this .matches ( "%_Generic%" ) }
38
+ }
39
+
40
+ import MatchingParenthesis< GenericMacroString >
41
+
42
+ class ParsedGenericMacro extends Macro {
43
+ ParsedRoot macroBody ;
44
+ Parsed genericBody ;
45
+ string beforeGenericBody ;
46
+ string afterGenericBody ;
47
+
48
+ ParsedGenericMacro ( ) {
49
+ macroBody .getInputString ( ) = this .getBody ( ) and
50
+ exists ( ParsedText genericText |
51
+ genericText .getText ( ) .matches ( "%_Generic%" ) and
52
+ genericBody = genericText .getParent ( ) .getChild ( genericText .getChildIdx ( ) + 1 ) and
53
+ genericBody .getRoot ( ) = macroBody
54
+ ) and
55
+ beforeGenericBody =
56
+ textFrom ( macroBody .getStartToken ( ) , genericBody .getStartToken ( ) .getPrevious ( ) ) and
57
+ (
58
+ if exists ( genericBody .getEndToken ( ) .getNext ( ) )
59
+ then afterGenericBody = textFrom ( genericBody .getEndToken ( ) .getNext ( ) , macroBody .getEndToken ( ) )
60
+ else afterGenericBody = ""
61
+ )
62
+ }
63
+
64
+ string getAParameter ( ) {
65
+ result = this .( FunctionLikeMacro ) .getAParameter ( )
66
+ }
67
+
68
+ int getAParsedGenericCommaSeparatorOffset ( ) {
69
+ exists ( ParsedText text |
70
+ text .getParent ( ) = genericBody and
71
+ result = text .getStartToken ( ) .getStartPos ( ) + text .getText ( ) .indexOf ( "," )
72
+ )
73
+ }
74
+
75
+ int getAParsedGenericColonSeparatorOffset ( ) {
76
+ exists ( ParsedText text |
77
+ text .getParent ( ) = genericBody and
78
+ result = text .getStartToken ( ) .getStartPos ( ) + text .getText ( ) .indexOf ( ":" )
79
+ )
80
+ }
81
+
82
+ int getParsedGenericCommaSeparatorOffset ( int i ) {
83
+ result = rank [ i ] ( int index | index = getAParsedGenericCommaSeparatorOffset ( ) )
84
+ }
85
+
86
+ bindingset [ start, end]
87
+ int getParsedGenericColon ( int start , int end ) {
88
+ result =
89
+ min ( int offset |
90
+ offset = getAParsedGenericColonSeparatorOffset ( ) and
91
+ offset >= start and
92
+ offset <= end
93
+ )
94
+ }
95
+
96
+ predicate hasParsedFullSelectionRange ( int idx , int start , int end ) {
97
+ idx = 1 and
98
+ start = genericBody .getStartToken ( ) .getEndPos ( ) and
99
+ end = getParsedGenericCommaSeparatorOffset ( idx )
100
+ or
101
+ not exists ( getParsedGenericCommaSeparatorOffset ( idx ) ) and
102
+ start = getParsedGenericCommaSeparatorOffset ( idx - 1 ) and
103
+ end = genericBody .getEndToken ( ) .getStartPos ( )
104
+ or
105
+ start = getParsedGenericCommaSeparatorOffset ( idx - 1 ) and
106
+ end = getParsedGenericCommaSeparatorOffset ( idx )
107
+ }
108
+
109
+ string getSelectionString ( int idx ) {
110
+ exists ( int start , int rawStart , int end |
111
+ hasParsedFullSelectionRange ( idx , rawStart , end ) and
112
+ (
113
+ if exists ( getParsedGenericColon ( rawStart , end ) )
114
+ then start = getParsedGenericColon ( rawStart , end )
115
+ else start = rawStart
116
+ ) and
117
+ result = genericBody .getInputString ( ) .substring ( start , end )
118
+ )
119
+ }
120
+
121
+ string getControllingExprString ( ) {
122
+ result = getSelectionString ( 1 )
123
+ }
124
+
125
+ bindingset [ str, word]
126
+ private int countWordInString ( string word , string str ) {
127
+ result =
128
+ max ( int occurrence |
129
+ exists ( str .regexpFind ( "\\b" + word + "\\b" , occurrence , _) ) or occurrence = - 1
130
+ |
131
+ occurrence + 1
132
+ )
133
+ }
134
+
135
+ int expansionsOutsideExpr ( string parameter ) {
136
+ parameter = getAParameter ( ) and
137
+ result =
138
+ countWordInString ( parameter , beforeGenericBody ) +
139
+ countWordInString ( parameter , afterGenericBody )
140
+ }
141
+
142
+ int expansionsInsideSelection ( string parameter , int idx ) {
143
+ parameter = getAParameter ( ) and
144
+ result = countWordInString ( parameter , getSelectionString ( idx ) )
145
+ }
146
+
147
+ int expansionsInsideControllingExpr ( string parameter ) {
148
+ result = expansionsInsideSelection ( parameter , 1 )
149
+ }
150
+
151
+ int expansionsInsideAssociation ( string parameter , int idx ) {
152
+ not idx = 0 and
153
+ result = expansionsInsideSelection ( parameter , idx + 1 )
154
+ }
155
+ }
0 commit comments