Skip to content

Commit 908b6e9

Browse files
committed
IdentifierHidden: improve lambda handling case
1 parent 37d9bd9 commit 908b6e9

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

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

+40-4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,22 @@ 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

15+
/**
16+
* a `IntegralOrEnumType` that is nonvolatile and const
17+
*/
18+
class NonVolatileConstIntegralOrEnumType extends IntegralOrEnumType {
19+
NonVolatileConstIntegralOrEnumType() {
20+
not this.isVolatile() and
21+
this.isConst()
22+
}
23+
}
24+
1425
/**
1526
* Holds if declaration `innerDecl`, declared in a lambda, hides a declaration `outerDecl` captured by the lambda.
1627
*/
@@ -19,10 +30,35 @@ predicate hiddenInLambda(UserVariable outerDecl, UserVariable innerDecl) {
1930
//innerDecl declared inside of the lambda
2031
s.getADeclaration() = innerDecl and
2132
s.getAnAncestor() = le and
22-
le.getEnclosingFunction().getBasicBlock().(Scope) = outerDecl.getParentScope() and
23-
exists(LambdaCapture cap |
24-
outerDecl.getAnAccess() = cap.getInitializer().(VariableAccess) and
25-
le.getLambdaExpression().getACapture() = cap
33+
//a variable can be accessed (therefore hide) another when:
34+
//it is explicitly captured
35+
(
36+
exists(LambdaCapture cap |
37+
outerDecl.getAnAccess() = cap.getInitializer().(VariableAccess) and
38+
le.getLambdaExpression().getACapture() = cap and
39+
//captured variable (outerDecl) is in the same (function) scope as the lambda itself
40+
outerDecl.getParentScope() = le.getEnclosingFunction().getBasicBlock().(Scope)
41+
)
42+
or
43+
//is non-local
44+
outerDecl instanceof GlobalVariable
45+
or
46+
//has static or thread local storage duration
47+
(outerDecl.isThreadLocal() or outerDecl.isStatic())
48+
or
49+
//is a reference that has been initialized with a constant expression.
50+
outerDecl.getType().stripTopLevelSpecifiers() instanceof ReferenceType and
51+
exists(outerDecl.getInitializer().getExpr().getValue())
52+
or
53+
//const non-volatile integral or enumeration type and has been initialized with a constant expression
54+
outerDecl.getType() instanceof NonVolatileConstIntegralOrEnumType and
55+
exists(outerDecl.getInitializer().getExpr().getValue())
56+
or
57+
//is constexpr and has no mutable members
58+
outerDecl.isConstexpr() and
59+
not exists(Class c |
60+
c = outerDecl.getType() and not c.getAMember() instanceof MutableVariable
61+
)
2662
) and
2763
innerDecl.getName() = outerDecl.getName()
2864
)

cpp/common/test/rules/identifierhidden/IdentifierHidden.expected

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
| test.cpp:75:16:75:16 | i | Declaration is hiding declaration $@. | test.cpp:61:7:61:7 | i | i |
1111
| test.cpp:81:5:81:5 | a | Declaration is hiding declaration $@. | test.cpp:79:5:79:5 | a | a |
1212
| 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 |

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,18 @@ void f4() {
105105
}
106106

107107
void f5(int i) {} // COMPLIANT - exception - assume purposefully overloaded
108-
void f5(double d) {} // 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+
}

0 commit comments

Comments
 (0)