@@ -25,21 +25,9 @@ import codingstandards.cpp.alertreporting.HoldsForAllCopies
2525 * Holds if the function is in a template scope and should be excluded.
2626 */
2727predicate isInTemplateScope ( Function f ) {
28- // Function templates
2928 f .isFromTemplateInstantiation ( _)
3029 or
31- f instanceof TemplateFunction
32- or
33- // Functions declared within the scope of a template class
34- exists ( TemplateClass tc | f .getDeclaringType ( ) = tc )
35- or
36- f .getDeclaringType ( ) .isFromTemplateInstantiation ( _)
37- or
38- // Lambdas within template scope
39- exists ( LambdaExpression le |
40- le .getLambdaFunction ( ) = f and
41- isInTemplateScope ( le .getEnclosingFunction ( ) )
42- )
30+ f .isFromUninstantiatedTemplate ( _)
4331}
4432
4533/**
@@ -96,6 +84,9 @@ class PointerLikeType extends Type {
9684 predicate pointsToNonConst ( ) { not innerType .isConst ( ) }
9785}
9886
87+ /**
88+ * A `Parameter` whose type is a `PointerLikeType` such as a pointer or reference.
89+ */
9990class PointerLikeParam extends Parameter {
10091 PointerLikeType pointerLikeType ;
10192
@@ -107,6 +98,28 @@ class PointerLikeParam extends Parameter {
10798 not pointerLikeType .getInnerType ( ) instanceof VoidType
10899 }
109100
101+ /**
102+ * Get the pointer like type of this parameter.
103+ */
104+ PointerLikeType getPointerLikeType ( ) { result = pointerLikeType }
105+
106+ /**
107+ * Get usages of this parameter that maintain pointer-like semantics -- typically this means
108+ * either a normal access, or switching between pointers and reference semantics.
109+ *
110+ * Examples of accesses with pointer-like semantics include:
111+ * - `ref` in `int &x = ref`, or `&ref` in `int *x = &ref`;
112+ * - `ptr` in `int *x = ptr`, or `*ptr` in `int &x = *ptr`;
113+ *
114+ * In the above examples, we can still access the value pointed to by `ref` or `ptr` through the
115+ * expression.
116+ *
117+ * Examples of non-pointer-like semantics include:
118+ * - `ref` in `int x = ref` and `*ptr` in `int x = *ptr`;
119+ *
120+ * In the above examples, the value pointed to by `ref` or `ptr` is copied and the expression
121+ * refers to a new/different object.
122+ */
110123 Expr getAPointerLikeAccess ( ) {
111124 result = this .getAnAccess ( )
112125 or
@@ -121,17 +134,40 @@ class PointerLikeParam extends Parameter {
121134 }
122135}
123136
124- query predicate test (
125- PointerLikeParam param , Expr ptrLikeAccess , Type argtype , Type innerType , string explain
126- ) {
127- ptrLikeAccess = param .getAPointerLikeAccess ( ) and
128- exists ( FunctionCall fc |
129- fc .getArgument ( 0 ) = ptrLikeAccess and
130- argtype = fc .getTarget ( ) .getParameter ( 0 ) .getType ( ) and
131- argtype .( PointerLikeType ) .pointsToNonConst ( ) and
132- innerType = argtype .( PointerLikeType ) .getInnerType ( )
133- ) and
134- explain = argtype .explain ( )
137+ /**
138+ * A `VariableEffect` whose target variable is a `PointerLikeParam`.
139+ *
140+ * Examples of pointer-like effects on a pointer-like parameter `p` would include `p = ...`, `++p`,
141+ * `*p = ...`, and `++*p`, etc.
142+ */
143+ class PointerLikeEffect extends VariableEffect {
144+ PointerLikeParam param ;
145+
146+ PointerLikeEffect ( ) { param = this .getTarget ( ) }
147+
148+ /**
149+ * Holds if this effect modifies the pointed-to or referred-to object.
150+ *
151+ * For example, `*p = 0` modifies the inner type if `p` is a pointer, and `p = 0` affects the
152+ * inner type if `p` is a reference.
153+ */
154+ predicate affectsInnerType ( ) {
155+ if param .getPointerLikeType ( ) instanceof ReferenceType
156+ then affectsOuterType ( )
157+ else not affectsOuterType ( )
158+ }
159+
160+ /**
161+ * Holds if this effect modifies the pointer or reference itself.
162+ *
163+ * For example, `p = ...` and `++p` modify the outer type, whether that type is a pointer or
164+ * reference, while `*p = 0` does not modify the outer type.
165+ */
166+ predicate affectsOuterType ( ) {
167+ this .( Assignment ) .getLValue ( ) = param .getAnAccess ( )
168+ or
169+ this .( CrementOperation ) .getOperand ( ) = param .getAnAccess ( )
170+ }
135171}
136172
137173/**
@@ -158,17 +194,10 @@ class NonConstParam extends PointerLikeParam {
158194 not this .getFunction ( ) .hasGlobalName ( "main" ) and
159195 // Exclude deleted functions
160196 not this .getFunction ( ) .isDeleted ( ) and
161- // Exclude any parameter whose underlying data is modified (VariableEffect)
162- not exists ( VariableEffect effect |
197+ // Exclude any parameter whose underlying data is modified
198+ not exists ( PointerLikeEffect effect |
163199 effect .getTarget ( ) = this and
164- (
165- // For reference types, any effect is a target modification
166- pointerLikeType .getOuterType ( ) instanceof ReferenceType
167- or
168- // For pointer types, exclude effects that only modify the pointer itself
169- not effect .( AssignExpr ) .getLValue ( ) = this .getAnAccess ( ) and
170- not effect .( CrementOperation ) .getOperand ( ) = this .getAnAccess ( )
171- )
200+ effect .affectsInnerType ( )
172201 ) and
173202 // Exclude parameters passed as arguments to functions taking non-const pointer/ref params
174203 not exists ( FunctionCall fc , int i |
@@ -183,19 +212,30 @@ class NonConstParam extends PointerLikeParam {
183212 ) and
184213 // Exclude parameters assigned to a non-const pointer/reference alias
185214 not exists ( Variable v |
186- v .getAnAssignedValue ( ) = this .getAnAccess ( ) and
215+ v .getAnAssignedValue ( ) = this .getAPointerLikeAccess ( ) and
187216 v .getType ( ) .( PointerLikeType ) .pointsToNonConst ( )
188217 ) and
189218 // Exclude parameters returned as non-const pointer/reference
190219 not exists ( ReturnStmt ret |
191- ret .getExpr ( ) = this .getAnAccess ( ) and
220+ ret .getExpr ( ) = this .getAPointerLikeAccess ( ) and
192221 ret .getEnclosingFunction ( ) .getType ( ) .( PointerLikeType ) .pointsToNonConst ( )
222+ ) and
223+ not exists ( FieldAccess fa |
224+ fa .getQualifier ( ) = [ this .getAPointerLikeAccess ( ) , this .getAnAccess ( ) ] and
225+ fa .isLValueCategory ( )
226+ ) and
227+ not exists ( AddressOfExpr addrOf |
228+ // exclude pointer to pointer and reference to pointer cases.
229+ addrOf .getOperand ( ) = this .getAPointerLikeAccess ( ) and
230+ addrOf .getType ( ) .( PointerLikeType ) .getInnerType ( ) instanceof PointerLikeType
193231 )
194232 }
195233}
196234
197- from NonConstParam param
198- where not isExcluded ( param , Declarations3Package:: pointerOrRefParamNotConstQuery ( ) )
235+ from NonConstParam param , Type innerType
236+ where
237+ not isExcluded ( param , Declarations3Package:: pointerOrRefParamNotConstQuery ( ) ) and
238+ innerType = param .getPointerLikeType ( ) .getInnerType ( )
199239select param ,
200- "Parameter '" + param .getName ( ) +
201- "' points/refers to a non-const-qualified type but does not modify the target object."
240+ "Parameter '" + param .getName ( ) + "' points/refers to a non-const type '" + innerType . toString ( ) +
241+ "' but does not modify the target object."
0 commit comments