Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 380417f

Browse files
authoredMay 8, 2024··
Merge pull request #546 from knewbury01/knewbury01/fix-118
A2-10-1: add functions and types to identifier consideration
2 parents c6fb3af + 80432d8 commit 380417f

File tree

9 files changed

+352
-137
lines changed

9 files changed

+352
-137
lines changed
 
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
| test.c:4:7:4:9 | id1 | Variable is hiding variable $@. | test.c:1:5:1:7 | id1 | id1 |
2-
| test.c:7:13:7:15 | id1 | Variable is hiding variable $@. | test.c:1:5:1:7 | id1 | id1 |
3-
| test.c:10:12:10:14 | id1 | Variable is hiding variable $@. | test.c:1:5:1:7 | id1 | id1 |
4-
| test.c:11:14:11:16 | id1 | Variable is hiding variable $@. | test.c:10:12:10:14 | id1 | id1 |
5-
| test.c:24:24:24:26 | id2 | Variable is hiding variable $@. | test.c:22:5:22:7 | id2 | id2 |
1+
| test.c:4:7:4:9 | id1 | Declaration is hiding declaration $@. | test.c:1:5:1:7 | id1 | id1 |
2+
| test.c:7:13:7:15 | id1 | Declaration is hiding declaration $@. | test.c:1:5:1:7 | id1 | id1 |
3+
| test.c:10:12:10:14 | id1 | Declaration is hiding declaration $@. | test.c:1:5:1:7 | id1 | id1 |
4+
| test.c:11:14:11:16 | id1 | Declaration is hiding declaration $@. | test.c:10:12:10:14 | id1 | id1 |
5+
| test.c:24:24:24:26 | id2 | Declaration is hiding declaration $@. | test.c:22:5:22:7 | id2 | id2 |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `A2-10-1`, `RULE-5-3` - `IdentifierHiding.ql`, `IdentifierHidingC.ql`:
2+
- Address FN reported in #118. Rule was missing detection of functions. Additionally omitted class template instantiations.
3+
- Fix FP for identifiers in nested namespaces.

‎cpp/autosar/src/rules/A7-1-2/VariableMissingConstexpr.ql

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import codingstandards.cpp.autosar
1818
import codingstandards.cpp.TrivialType
1919
import codingstandards.cpp.SideEffect
2020
import semmle.code.cpp.controlflow.SSA
21+
import codingstandards.cpp.Expr
2122

2223
predicate isZeroInitializable(Variable v) {
2324
not exists(v.getInitializer().getExpr()) and
@@ -34,78 +35,6 @@ predicate isTypeZeroInitializable(Type t) {
3435
t.getUnderlyingType() instanceof ArrayType
3536
}
3637

37-
/**
38-
* An optimized set of expressions used to determine the flow through constexpr variables.
39-
*/
40-
class VariableAccessOrCallOrLiteral extends Expr {
41-
VariableAccessOrCallOrLiteral() {
42-
this instanceof VariableAccess or
43-
this instanceof Call or
44-
this instanceof Literal
45-
}
46-
}
47-
48-
/**
49-
* Holds if the value of source flows through compile time evaluated variables to target.
50-
*/
51-
predicate flowsThroughConstExprVariables(
52-
VariableAccessOrCallOrLiteral source, VariableAccessOrCallOrLiteral target
53-
) {
54-
(
55-
source = target
56-
or
57-
source != target and
58-
exists(SsaDefinition intermediateDef, StackVariable intermediate |
59-
intermediateDef.getAVariable().getFunction() = source.getEnclosingFunction() and
60-
intermediateDef.getAVariable().getFunction() = target.getEnclosingFunction() and
61-
intermediateDef.getAVariable() = intermediate and
62-
intermediate.isConstexpr()
63-
|
64-
DataFlow::localExprFlow(source, intermediateDef.getDefiningValue(intermediate)) and
65-
flowsThroughConstExprVariables(intermediateDef.getAUse(intermediate), target)
66-
)
67-
)
68-
}
69-
70-
/*
71-
* Returns true if the given call may be evaluated at compile time and is compile time evaluated because
72-
* all its arguments are compile time evaluated and its default values are compile time evaluated.
73-
*/
74-
75-
predicate isCompileTimeEvaluated(Call call) {
76-
// 1. The call may be evaluated at compile time, because it is constexpr, and
77-
call.getTarget().isConstexpr() and
78-
// 2. all its arguments are compile time evaluated, and
79-
forall(DataFlow::Node ultimateArgSource, DataFlow::Node argSource |
80-
argSource = DataFlow::exprNode(call.getAnArgument()) and
81-
DataFlow::localFlow(ultimateArgSource, argSource) and
82-
not DataFlow::localFlowStep(_, ultimateArgSource)
83-
|
84-
(
85-
ultimateArgSource.asExpr() instanceof Literal
86-
or
87-
any(Call c | isCompileTimeEvaluated(c)) = ultimateArgSource.asExpr()
88-
) and
89-
// If the ultimate argument source is not the same as the argument source, then it must flow through
90-
// constexpr variables.
91-
(
92-
ultimateArgSource != argSource
93-
implies
94-
flowsThroughConstExprVariables(ultimateArgSource.asExpr(), argSource.asExpr())
95-
)
96-
) and
97-
// 3. all the default values used are compile time evaluated.
98-
forall(Expr defaultValue, Parameter parameterUsingDefaultValue, int idx |
99-
parameterUsingDefaultValue = call.getTarget().getParameter(idx) and
100-
not exists(call.getArgument(idx)) and
101-
parameterUsingDefaultValue.getAnAssignedValue() = defaultValue
102-
|
103-
defaultValue instanceof Literal
104-
or
105-
any(Call c | isCompileTimeEvaluated(c)) = defaultValue
106-
)
107-
}
108-
10938
from Variable v
11039
where
11140
not isExcluded(v, ConstPackage::variableMissingConstexprQuery()) and
@@ -119,7 +48,7 @@ where
11948
(
12049
v.getInitializer().getExpr().isConstant()
12150
or
122-
any(Call call | isCompileTimeEvaluated(call)) = v.getInitializer().getExpr()
51+
any(Call call | isCompileTimeEvaluatedCall(call)) = v.getInitializer().getExpr()
12352
or
12453
isZeroInitializable(v)
12554
or

‎cpp/common/src/codingstandards/cpp/Expr.qll

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,89 @@ module MisraExpr {
191191
}
192192

193193
/**
194+
* An optimized set of expressions used to determine the flow through constexpr variables.
195+
*/
196+
class VariableAccessOrCallOrLiteral extends Expr {
197+
VariableAccessOrCallOrLiteral() {
198+
this instanceof VariableAccess and this.(VariableAccess).getTarget().isConstexpr()
199+
or
200+
this instanceof Call
201+
or
202+
this instanceof Literal
203+
}
204+
}
205+
206+
/**
207+
* Holds if the value of source flows through compile time evaluated variables to target.
208+
*/
209+
predicate flowsThroughConstExprVariables(
210+
VariableAccessOrCallOrLiteral source, VariableAccessOrCallOrLiteral target
211+
) {
212+
(
213+
source = target
214+
or
215+
source != target and
216+
exists(SsaDefinition intermediateDef, StackVariable intermediate |
217+
intermediateDef.getAVariable().getFunction() = source.getEnclosingFunction() and
218+
intermediateDef.getAVariable().getFunction() = target.getEnclosingFunction() and
219+
intermediateDef.getAVariable() = intermediate and
220+
intermediate.isConstexpr()
221+
|
222+
DataFlow::localExprFlow(source, intermediateDef.getDefiningValue(intermediate)) and
223+
flowsThroughConstExprVariables(intermediateDef.getAUse(intermediate), target)
224+
)
225+
)
226+
}
227+
228+
predicate isCompileTimeEvaluatedExpression(Expr expression) {
229+
forall(DataFlow::Node ultimateSource, DataFlow::Node source |
230+
source = DataFlow::exprNode(expression) and
231+
DataFlow::localFlow(ultimateSource, source) and
232+
not DataFlow::localFlowStep(_, ultimateSource)
233+
|
234+
isDirectCompileTimeEvaluatedExpression(ultimateSource.asExpr()) and
235+
// If the ultimate source is not the same as the source, then it must flow through
236+
// constexpr variables.
237+
(
238+
ultimateSource != source
239+
implies
240+
flowsThroughConstExprVariables(ultimateSource.asExpr(), source.asExpr())
241+
)
242+
)
243+
}
244+
245+
predicate isDirectCompileTimeEvaluatedExpression(Expr expression) {
246+
expression instanceof Literal
247+
or
248+
any(Call c | isCompileTimeEvaluatedCall(c)) = expression
249+
}
250+
251+
/*
252+
* Returns true if the given call may be evaluated at compile time and is compile time evaluated because
253+
* all its arguments are compile time evaluated and its default values are compile time evaluated.
254+
*/
255+
256+
predicate isCompileTimeEvaluatedCall(Call call) {
257+
// 1. The call may be evaluated at compile time, because it is constexpr, and
258+
call.getTarget().isConstexpr() and
259+
// 2. all its arguments are compile time evaluated, and
260+
forall(Expr argSource | argSource = call.getAnArgument() |
261+
isCompileTimeEvaluatedExpression(argSource)
262+
) and
263+
// 3. all the default values used are compile time evaluated.
264+
forall(Expr defaultValue, Parameter parameterUsingDefaultValue, int idx |
265+
parameterUsingDefaultValue = call.getTarget().getParameter(idx) and
266+
not exists(call.getArgument(idx)) and
267+
parameterUsingDefaultValue.getAnAssignedValue() = defaultValue
268+
|
269+
isDirectCompileTimeEvaluatedExpression(defaultValue)
270+
)
271+
}
272+
273+
/*
194274
* an operator that does not evaluate its operand
195275
*/
276+
196277
class UnevaluatedExprExtension extends Expr {
197278
UnevaluatedExprExtension() {
198279
this.getAChild().isUnevaluated()

‎cpp/common/src/codingstandards/cpp/Scope.qll

Lines changed: 66 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,18 @@ private Element getParentScope(Element e) {
5757

5858
/** A variable which is defined by the user, rather than being from a third party or compiler generated. */
5959
class UserVariable extends Variable {
60-
UserVariable() {
60+
UserVariable() { this instanceof UserDeclaration }
61+
}
62+
63+
/** A construct which is defined by the user, rather than being from a third party or compiler generated. */
64+
class UserDeclaration extends Declaration {
65+
UserDeclaration() {
6166
exists(getFile().getRelativePath()) and
62-
not isCompilerGenerated() and
67+
not this.(Variable).isCompilerGenerated() and
68+
not this.(Function).isCompilerGenerated() and
6369
not this.(Parameter).getFunction().isCompilerGenerated() and
70+
// Class template instantiations are compiler generated instances that share the same parent scope. This will result in a cross-product on class template instantiations because they have the same name and same parent scope. We therefore exclude these from consideration like we do with other compiler generated identifiers of interest.
71+
not this instanceof ClassTemplateInstantiation and
6472
// compiler inferred parameters have name of p#0
6573
not this.(Parameter).getName() = "p#0"
6674
}
@@ -74,11 +82,13 @@ class Scope extends Element {
7482

7583
int getNumberOfVariables() { result = count(getAVariable()) }
7684

85+
int getNumberOfDeclarations() { result = count(getADeclaration()) }
86+
7787
Scope getAnAncestor() { result = this.getStrictParent+() }
7888

7989
Scope getStrictParent() { result = getParentScope(this) }
8090

81-
Declaration getADeclaration() { getParentScope(result) = this }
91+
UserDeclaration getADeclaration() { getParentScope(result) = this }
8292

8393
Expr getAnExpr() { this = getParentScope(result) }
8494

@@ -122,31 +132,31 @@ class GeneratedBlockStmt extends BlockStmt {
122132
GeneratedBlockStmt() { this.getLocation() instanceof UnknownLocation }
123133
}
124134

125-
/** Gets a variable that is in the potential scope of variable `v`. */
126-
private UserVariable getPotentialScopeOfVariable_candidate(UserVariable v) {
135+
/** Gets a Declaration that is in the potential scope of Declaration `v`. */
136+
private UserDeclaration getPotentialScopeOfDeclaration_candidate(UserDeclaration v) {
127137
exists(Scope s |
128-
result = s.getAVariable() and
138+
result = s.getADeclaration() and
129139
(
130-
// Variable in an ancestor scope, but only if there are less than 100 variables in this scope
131-
v = s.getAnAncestor().getAVariable() and
132-
s.getNumberOfVariables() < 100
140+
// Declaration in an ancestor scope, but only if there are less than 100 declarations in this scope
141+
v = s.getAnAncestor().getADeclaration() and
142+
s.getNumberOfDeclarations() < 100
133143
or
134-
// In the same scope, but not the same variable, and choose just one to report
135-
v = s.getAVariable() and
144+
// In the same scope, but not the same Declaration, and choose just one to report
145+
v = s.getADeclaration() and
136146
not result = v and
137147
v.getName() <= result.getName()
138148
)
139149
)
140150
}
141151

142-
/** Gets a variable that is in the potential scope of variable `v`. */
143-
private UserVariable getOuterScopesOfVariable_candidate(UserVariable v) {
152+
/** Gets a Declaration that is in the potential scope of Declaration `v`. */
153+
private UserDeclaration getPotentialScopeOfDeclarationStrict_candidate(UserDeclaration v) {
144154
exists(Scope s |
145-
result = s.getAVariable() and
155+
result = s.getADeclaration() and
146156
(
147-
// Variable in an ancestor scope, but only if there are less than 100 variables in this scope
148-
v = s.getAnAncestor().getAVariable() and
149-
s.getNumberOfVariables() < 100
157+
// Declaration in an ancestor scope, but only if there are less than 100 variables in this scope
158+
v = s.getAnAncestor().getADeclaration() and
159+
s.getNumberOfDeclarations() < 100
150160
)
151161
)
152162
}
@@ -161,20 +171,20 @@ predicate inSameTranslationUnit(File f1, File f2) {
161171
}
162172

163173
/**
164-
* Gets a user variable which occurs in the "potential scope" of variable `v`.
174+
* Gets a user Declaration which occurs in the "outer scope" of Declaration `v`.
165175
*/
166176
cached
167-
UserVariable getPotentialScopeOfVariable(UserVariable v) {
168-
result = getPotentialScopeOfVariable_candidate(v) and
177+
UserDeclaration getPotentialScopeOfDeclarationStrict(UserDeclaration v) {
178+
result = getPotentialScopeOfDeclarationStrict_candidate(v) and
169179
inSameTranslationUnit(v.getFile(), result.getFile())
170180
}
171181

172182
/**
173-
* Gets a user variable which occurs in the "outer scope" of variable `v`.
183+
* Gets a user variable which occurs in the "potential scope" of variable `v`.
174184
*/
175185
cached
176-
UserVariable getPotentialScopeOfVariableStrict(UserVariable v) {
177-
result = getOuterScopesOfVariable_candidate(v) and
186+
UserDeclaration getPotentialScopeOfDeclaration(UserDeclaration v) {
187+
result = getPotentialScopeOfDeclaration_candidate(v) and
178188
inSameTranslationUnit(v.getFile(), result.getFile())
179189
}
180190

@@ -204,18 +214,9 @@ class TranslationUnit extends SourceFile {
204214
}
205215

206216
/** Holds if `v2` may hide `v1`. */
207-
private predicate hides_candidate(UserVariable v1, UserVariable v2) {
217+
private predicate hides_candidateStrict(UserDeclaration v1, UserDeclaration v2) {
208218
not v1 = v2 and
209-
v2 = getPotentialScopeOfVariable(v1) and
210-
v1.getName() = v2.getName() and
211-
// Member variables cannot hide other variables nor be hidden because the can be referenced through their qualified name.
212-
not (v1.isMember() or v2.isMember())
213-
}
214-
215-
/** Holds if `v2` may hide `v1`. */
216-
private predicate hides_candidateStrict(UserVariable v1, UserVariable v2) {
217-
not v1 = v2 and
218-
v2 = getPotentialScopeOfVariableStrict(v1) and
219+
v2 = getPotentialScopeOfDeclarationStrict(v1) and
219220
v1.getName() = v2.getName() and
220221
// Member variables cannot hide other variables nor be hidden because the can be referenced through their qualified name.
221222
not (v1.isMember() or v2.isMember()) and
@@ -239,6 +240,15 @@ private predicate hides_candidateStrict(UserVariable v1, UserVariable v2) {
239240
)
240241
}
241242

243+
/** Holds if `v2` may hide `v1`. */
244+
private predicate hides_candidate(UserDeclaration v1, UserDeclaration v2) {
245+
not v1 = v2 and
246+
v2 = getPotentialScopeOfDeclaration(v1) and
247+
v1.getName() = v2.getName() and
248+
// Member variables cannot hide other variables nor be hidden because the can be referenced through their qualified name.
249+
not (v1.isMember() or v2.isMember())
250+
}
251+
242252
/**
243253
* Gets the enclosing statement of the given variable, if any.
244254
*/
@@ -257,20 +267,22 @@ private Stmt getEnclosingStmt(LocalScopeVariable v) {
257267
}
258268

259269
/** Holds if `v2` hides `v1`. */
260-
predicate hides(UserVariable v1, UserVariable v2) {
270+
predicate hides(UserDeclaration v1, UserDeclaration v2) {
261271
hides_candidate(v1, v2) and
262272
// Confirm that there's no closer candidate variable which `v2` hides
263-
not exists(UserVariable mid |
273+
not exists(UserDeclaration mid |
264274
hides_candidate(v1, mid) and
265275
hides_candidate(mid, v2)
266-
)
276+
) and
277+
// Unlike `hidesStrict`, that requires a different scope, `hides` considers declarations in the same scope. This will include function overloads based on their name. To remove overloads from consideration, we exclude them.
278+
not v1.(Function).getAnOverload() = v2
267279
}
268280

269281
/** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */
270-
predicate hidesStrict(UserVariable v1, UserVariable v2) {
282+
predicate hidesStrict(UserDeclaration v1, UserDeclaration v2) {
271283
hides_candidateStrict(v1, v2) and
272284
// Confirm that there's no closer candidate variable which `v2` hides
273-
not exists(UserVariable mid |
285+
not exists(UserDeclaration mid |
274286
hides_candidateStrict(v1, mid) and
275287
hides_candidateStrict(mid, v2)
276288
)
@@ -287,3 +299,18 @@ predicate hasClassScope(Declaration decl) { exists(decl.getDeclaringType()) }
287299

288300
/** Holds if `decl` has block scope. */
289301
predicate hasBlockScope(Declaration decl) { exists(BlockStmt b | b.getADeclaration() = decl) }
302+
303+
/**
304+
* identifiers in nested (named/nonglobal) namespaces are exceptions to hiding due to being able access via fully qualified ids
305+
*/
306+
predicate excludedViaNestedNamespaces(UserDeclaration outerDecl, UserDeclaration innerDecl) {
307+
exists(Namespace inner, Namespace outer |
308+
outer.getAChildNamespace+() = inner and
309+
//outer is not global
310+
not outer instanceof GlobalNamespace and
311+
not outer.isAnonymous() and
312+
not inner.isAnonymous() and
313+
innerDecl.getNamespace() = inner and
314+
outerDecl.getNamespace() = outer
315+
)
316+
}

‎cpp/common/src/codingstandards/cpp/rules/differentidentifiersnottypographicallyunambiguous/DifferentIdentifiersNotTypographicallyUnambiguous.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ string step1(string s) {
4747
string step2(string s) { s = "m_" and result = "rn" }
4848

4949
predicate violation(UserVariable v1, UserVariable v2) {
50-
v2 = getPotentialScopeOfVariable(v1) and
50+
v2 = getPotentialScopeOfDeclaration(v1) and
5151
exists(string s1, string s2 |
5252
// over-approximate a match, because it is cheaper to compute
5353
getCanon(v1) = getCanon(v2) and

‎cpp/common/src/codingstandards/cpp/rules/identifierhidden/IdentifierHidden.qll

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,88 @@ import cpp
66
import codingstandards.cpp.Customizations
77
import codingstandards.cpp.Exclusions
88
import codingstandards.cpp.Scope
9+
import codingstandards.cpp.ConstHelpers
910

1011
abstract class IdentifierHiddenSharedQuery extends Query { }
1112

1213
Query getQuery() { result instanceof IdentifierHiddenSharedQuery }
1314

14-
query predicate problems(UserVariable v2, string message, UserVariable v1, string varName) {
15-
not isExcluded(v1, getQuery()) and
16-
not isExcluded(v2, getQuery()) and
15+
/**
16+
* a `Variable` that is nonvolatile and const
17+
* and of type `IntegralOrEnumType`
18+
*/
19+
class NonVolatileConstIntegralOrEnumVariable extends Variable {
20+
NonVolatileConstIntegralOrEnumVariable() {
21+
not this.isVolatile() and
22+
this.isConst() and
23+
this.getUnspecifiedType() instanceof IntegralOrEnumType
24+
}
25+
}
26+
27+
/**
28+
* Holds if declaration `innerDecl`, declared in a lambda, hides a declaration `outerDecl` by the lambda.
29+
*/
30+
predicate hiddenInLambda(UserVariable outerDecl, UserVariable innerDecl) {
31+
exists(
32+
Scope innerScope, LambdaExpression lambdaExpr, Scope lambdaExprScope, Scope outerScope,
33+
Closure lambdaClosure
34+
|
35+
// The variable `innerDecl` is declared inside of the lambda.
36+
innerScope.getADeclaration() = innerDecl and
37+
// Because a lambda is compiled down to a closure, we need to use the closure to determine if the declaration
38+
// is part of the lambda.
39+
innerScope.getAnAncestor() = lambdaClosure and
40+
// Next we determine the scope of the lambda expression to determine if `outerDecl` is visible in the scope of the lambda.
41+
lambdaClosure.getLambdaExpression() = lambdaExpr and
42+
lambdaExprScope.getAnExpr() = lambdaExpr and
43+
outerScope.getADeclaration() = outerDecl and
44+
lambdaExprScope.getStrictParent*() = outerScope and
45+
(
46+
// A definition can be hidden if it is in scope and it is captured by the lambda,
47+
exists(LambdaCapture cap |
48+
lambdaExpr.getACapture() = cap and
49+
// The outer declaration is captured by the lambda
50+
outerDecl.getAnAccess() = cap.getInitializer()
51+
)
52+
or
53+
// it is is non-local,
54+
outerDecl instanceof GlobalVariable
55+
or
56+
// it has static or thread local storage duration,
57+
(outerDecl.isThreadLocal() or outerDecl.isStatic())
58+
or
59+
//it is a reference that has been initialized with a constant expression.
60+
outerDecl.getType().stripTopLevelSpecifiers() instanceof ReferenceType and
61+
outerDecl.getInitializer().getExpr() instanceof Literal
62+
or
63+
// //it const non-volatile integral or enumeration type and has been initialized with a constant expression
64+
outerDecl instanceof NonVolatileConstIntegralOrEnumVariable and
65+
outerDecl.getInitializer().getExpr() instanceof Literal
66+
or
67+
//it is constexpr and has no mutable members
68+
outerDecl.isConstexpr() and
69+
not exists(Class c |
70+
c = outerDecl.getType() and not c.getAMember() instanceof MutableVariable
71+
)
72+
) and
73+
// Finally, the variables must have the same names.
74+
innerDecl.getName() = outerDecl.getName()
75+
)
76+
}
77+
78+
query predicate problems(
79+
UserDeclaration innerDecl, string message, UserDeclaration outerDecl, string varName
80+
) {
81+
not isExcluded(outerDecl, getQuery()) and
82+
not isExcluded(innerDecl, getQuery()) and
1783
//ignore template variables for this rule
18-
not v1 instanceof TemplateVariable and
19-
not v2 instanceof TemplateVariable and
20-
hidesStrict(v1, v2) and
21-
varName = v1.getName() and
22-
message = "Variable is hiding variable $@."
84+
not outerDecl instanceof TemplateVariable and
85+
not innerDecl instanceof TemplateVariable and
86+
//ignore types for this rule as the Misra C/C++ 23 version of this rule (rule 6.4.1 and 6.4.2) focuses solely on variables and functions
87+
not innerDecl instanceof Type and
88+
not outerDecl instanceof Type and
89+
(hidesStrict(outerDecl, innerDecl) or hiddenInLambda(outerDecl, innerDecl)) and
90+
not excludedViaNestedNamespaces(outerDecl, innerDecl) and
91+
varName = outerDecl.getName() and
92+
message = "Declaration is hiding declaration $@."
2393
}
Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
| test.cpp:4:5:4:7 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 |
2-
| test.cpp:8:5:8:7 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 |
3-
| test.cpp:11:5:11:7 | id1 | Variable is hiding variable $@. | test.cpp:8:5:8:7 | id1 | id1 |
4-
| test.cpp:20:7:20:9 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 |
5-
| test.cpp:23:13:23:15 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 |
6-
| test.cpp:26:12:26:14 | id1 | Variable is hiding variable $@. | test.cpp:1:5:1:7 | id1 | id1 |
7-
| test.cpp:27:14:27:16 | id1 | Variable is hiding variable $@. | test.cpp:26:12:26:14 | id1 | id1 |
8-
| test.cpp:65:11:65:11 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i |
9-
| test.cpp:67:9:67:9 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i |
10-
| test.cpp:70:12:70:12 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i |
11-
| test.cpp:75:16:75:16 | i | Variable is hiding variable $@. | test.cpp:61:7:61:7 | i | i |
1+
| test.cpp:4:5:4:7 | id1 | Declaration is hiding declaration $@. | test.cpp:1:5:1:7 | id1 | id1 |
2+
| test.cpp:8:5:8:7 | id1 | Declaration is hiding declaration $@. | test.cpp:1:5:1:7 | id1 | id1 |
3+
| test.cpp:20:7:20:9 | id1 | Declaration is hiding declaration $@. | test.cpp:1:5:1:7 | id1 | id1 |
4+
| test.cpp:23:13:23:15 | id1 | Declaration is hiding declaration $@. | test.cpp:1:5:1:7 | id1 | id1 |
5+
| test.cpp:26:12:26:14 | id1 | Declaration is hiding declaration $@. | test.cpp:1:5:1:7 | id1 | id1 |
6+
| test.cpp:27:14:27:16 | id1 | Declaration is hiding declaration $@. | test.cpp:26:12:26:14 | id1 | id1 |
7+
| test.cpp:65:11:65:11 | i | Declaration is hiding declaration $@. | test.cpp:61:7:61:7 | i | i |
8+
| test.cpp:67:9:67:9 | i | Declaration is hiding declaration $@. | test.cpp:61:7:61:7 | i | i |
9+
| test.cpp:70:12:70:12 | i | Declaration is hiding declaration $@. | test.cpp:61:7:61:7 | i | i |
10+
| test.cpp:75:16:75:16 | i | Declaration is hiding declaration $@. | test.cpp:61:7:61:7 | i | i |
11+
| test.cpp:81:5:81:5 | a | Declaration is hiding declaration $@. | test.cpp:79:5:79:5 | a | a |
12+
| test.cpp:102:9:102:9 | b | Declaration is hiding declaration $@. | test.cpp:96:11:96:11 | b | b |
13+
| test.cpp:114:9:114:17 | globalvar | Declaration is hiding declaration $@. | test.cpp:110:5:110:13 | globalvar | globalvar |
14+
| test.cpp:133:11:133:11 | b | Declaration is hiding declaration $@. | test.cpp:127:13:127:13 | b | b |
15+
| test.cpp:142:9:142:10 | a1 | Declaration is hiding declaration $@. | test.cpp:140:14:140:15 | a1 | a1 |
16+
| test.cpp:147:9:147:10 | a2 | Declaration is hiding declaration $@. | test.cpp:145:20:145:21 | a2 | a2 |
17+
| test.cpp:152:9:152:10 | a3 | Declaration is hiding declaration $@. | test.cpp:150:17:150:18 | a3 | a3 |
18+
| test.cpp:164:9:164:10 | a5 | Declaration is hiding declaration $@. | test.cpp:162:13:162:14 | a5 | a5 |

‎cpp/common/test/rules/identifierhidden/test.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,102 @@ void test_scope_order() {
7474

7575
} catch (int i) { // NON_COMPLIANT
7676
}
77+
}
78+
79+
int a;
80+
namespace b {
81+
int a() {} // NON_COMPLIANT
82+
} // namespace b
83+
84+
namespace b1 {
85+
typedef int a; // COMPLIANT - do not consider types
86+
}
87+
88+
namespace ns_exception1_outer {
89+
int a1; // COMPLIANT - exception
90+
namespace ns_exception1_inner {
91+
void a1(); // COMPLIANT - exception
92+
}
93+
} // namespace ns_exception1_outer
94+
95+
void f4() {
96+
int a1, b;
97+
auto lambda1 = [a1]() {
98+
int b = 10; // COMPLIANT - exception - non captured variable b
99+
};
100+
101+
auto lambda2 = [b]() {
102+
int b = 10; // NON_COMPLIANT - not an exception - captured
103+
// variable b
104+
};
105+
}
106+
107+
void f5(int i) {} // COMPLIANT - exception - assume purposefully overloaded
108+
void f5(double d) {} // COMPLIANT - exception - assume purposefully overloaded
109+
110+
int globalvar = 0;
111+
112+
int f6() {
113+
auto lambda_with_shadowing = []() {
114+
int globalvar = 1; // NON_COMPLIANT - not an exception - not captured but
115+
// still accessible
116+
return globalvar + globalvar;
117+
};
118+
119+
auto lambda_without_shadowing = []() { return globalvar + globalvar; };
120+
121+
return lambda_with_shadowing();
122+
}
123+
124+
void f7(int p) {
125+
// Introduce a nested scope to test scope comparison.
126+
if (p != 0) {
127+
int a1, b;
128+
auto lambda1 = [a1]() {
129+
int b = 10; // COMPLIANT - exception - non captured variable b
130+
};
131+
132+
auto lambda2 = [b]() {
133+
int b = 10; // NON_COMPLIANT - not an exception - captured
134+
// variable b
135+
};
136+
}
137+
}
138+
139+
void f8() {
140+
static int a1;
141+
auto lambda1 = []() {
142+
int a1 = 10; // NON_COMPLIANT - Lambda can access static variable.
143+
};
144+
145+
thread_local int a2;
146+
auto lambda2 = []() {
147+
int a2 = 10; // NON_COMPLIANT - Lambda can access thread local variable.
148+
};
149+
150+
constexpr int a3 = 10;
151+
auto lambda3 = []() {
152+
int a3 = a3 + 1; // NON_COMPLIANT - Lambda can access const
153+
// expression without mutable members.
154+
};
155+
156+
const int &a4 = a3;
157+
auto lambda4 = []() {
158+
int a4 = a4 + 1; // NON_COMPLIANT[FALSE_NEGATIVE] - Lambda can access
159+
// reference initialized with constant expression.
160+
};
161+
162+
const int a5 = 10;
163+
auto lambda5 = []() {
164+
int a5 = a5 + 1; // NON_COMPLIANT - Lambda can access const
165+
// non-volatile integral or enumeration type initialized
166+
// with constant expression.
167+
};
168+
169+
volatile const int a6 = 10;
170+
auto lambda6 = []() {
171+
int a6 =
172+
a6 + 1; // COMPLIANT - Lambda cannot access const volatile integral or
173+
// enumeration type initialized with constant expression.
174+
};
77175
}

0 commit comments

Comments
 (0)
Please sign in to comment.