Skip to content

Commit 2c6baca

Browse files
authored
Merge branch 'main' into lcartey/rule-11-4-improvements
2 parents 6e6250f + 9e73400 commit 2c6baca

File tree

3 files changed

+112
-5
lines changed

3 files changed

+112
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `M3-4-1` - `UnnecessaryExposedIdentifierDeclarationShared.qll`:
2+
- Fixes #665. Exclude variables that are constexpr and coming from template instantiations.

cpp/common/src/codingstandards/cpp/rules/unnecessaryexposedidentifierdeclarationshared/UnnecessaryExposedIdentifierDeclarationShared.qll

+17-4
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ private predicate isTypeUse(Type t1, Type t2) {
120120
}
121121

122122
newtype TDeclarationAccess =
123-
ObjectAccess(Variable v, VariableAccess va) { va = v.getAnAccess() } or
123+
ObjectAccess(Variable v, VariableAccess va) {
124+
va = v.getAnAccess() or
125+
v.(TemplateVariable).getAnInstantiation().getAnAccess() = va
126+
} or
124127
/* Type access can be done in a declaration or an expression (e.g., static member function call) */
125128
TypeAccess(Type t, Element access) {
126129
isTypeUse(access.(Variable).getUnspecifiedType(), t)
@@ -205,9 +208,13 @@ class DeclarationAccess extends TDeclarationAccess {
205208

206209
class CandidateDeclaration extends Declaration {
207210
CandidateDeclaration() {
208-
this instanceof LocalVariable
211+
this instanceof LocalVariable and
212+
not this.(LocalVariable).isConstexpr() and
213+
not this.isFromTemplateInstantiation(_)
209214
or
210-
this instanceof GlobalOrNamespaceVariable
215+
this instanceof GlobalOrNamespaceVariable and
216+
not this.isFromTemplateInstantiation(_) and
217+
not this.(GlobalOrNamespaceVariable).isConstexpr()
211218
or
212219
this instanceof Type and
213220
not this instanceof ClassTemplateInstantiation and
@@ -229,7 +236,13 @@ Scope possibleScopesForDeclaration(CandidateDeclaration d) {
229236
result = scope.getStrictParent*()
230237
) and
231238
// Limit the best scope to block statements and namespaces or control structures
232-
(result instanceof BlockStmt or result instanceof Namespace)
239+
(
240+
result instanceof BlockStmt and
241+
// Template variables cannot be in block scope
242+
not d instanceof TemplateVariable
243+
or
244+
result instanceof Namespace
245+
)
233246
}
234247

235248
/* Gets the smallest scope that includes all the declaration accesses of declaration `d`. */

cpp/common/test/rules/unnecessaryexposedidentifierdeclarationshared/test.cpp

+93-1
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,96 @@ void f17() {
136136
ptr = &i;
137137
}
138138
*ptr = 1;
139-
}
139+
}
140+
141+
namespace a_namespace {
142+
143+
constexpr static unsigned int a_constexpr_var{
144+
10U}; // COMPLIANT; used in
145+
// a_namespace and
146+
// another_namespace_function
147+
static unsigned int
148+
a_namespace_var[a_constexpr_var]{}; // COMPLIANT; used in
149+
// a_namespace_function and
150+
// another_namespace_function
151+
152+
constexpr static unsigned int a_namespace_function(void) noexcept {
153+
unsigned int a_return_value{0U};
154+
155+
for (auto loop_var : a_namespace_var) { // usage of a_namespace_var
156+
a_return_value += loop_var;
157+
}
158+
return a_return_value;
159+
}
160+
161+
constexpr static unsigned int another_namespace_function(void) noexcept {
162+
unsigned int a_return_value{0U};
163+
164+
for (unsigned int i{0U}; i < a_constexpr_var;
165+
i++) { // usage of a_constexpr_var
166+
a_return_value += a_namespace_var[i]; // usage of a_namespace_var
167+
}
168+
return a_return_value;
169+
}
170+
} // namespace a_namespace
171+
172+
namespace parent_namespace {
173+
namespace child_namespace {
174+
template <typename From> class a_class_in_child_namespace {
175+
public:
176+
template <typename To> constexpr auto &&operator()(To &&val) const noexcept {
177+
return static_cast<To>(val);
178+
}
179+
}; // a_class_in_child_namespace end
180+
181+
template <typename From>
182+
extern constexpr a_class_in_child_namespace<From>
183+
a_class_in_child_namespace_impl{};
184+
185+
} // namespace child_namespace
186+
187+
template <typename From>
188+
static constexpr auto const &a_parent_namespace_variable =
189+
child_namespace::a_class_in_child_namespace_impl<
190+
From>; // COMPLIANT; used in child_namespace2::a_class::bar() and
191+
// parent_namespace::another_class::foo()
192+
193+
namespace child_namespace2 {
194+
class a_class {
195+
public:
196+
int func(...) { return 0; }
197+
void foo(int x) { x++; }
198+
template <typename F> constexpr auto bar(F(*func), int b) {
199+
foo(func(a_parent_namespace_variable<F>(
200+
b))); // usage of a_parent_namespace_variable
201+
}
202+
}; // a_class
203+
} // namespace child_namespace2
204+
205+
class another_class {
206+
int a;
207+
int b;
208+
void bar(int param) { param++; }
209+
210+
bool has_value() { return a == b; }
211+
212+
public:
213+
template <typename F> int foo(F(*func), int b) {
214+
if (has_value()) {
215+
bar(func(a_parent_namespace_variable<F>(
216+
b))); // usage of a_parent_namespace_variable
217+
}
218+
return 0;
219+
}
220+
}; // another_class
221+
} // namespace parent_namespace
222+
223+
template <typename T> T a_func(T v) { return v++; }
224+
225+
int main() {
226+
parent_namespace::child_namespace2::a_class a_class_obj;
227+
a_class_obj.bar(a_func<int>, 10);
228+
parent_namespace::another_class another_class_obj;
229+
another_class_obj.foo(a_func<int>, 10);
230+
return 0;
231+
}

0 commit comments

Comments
 (0)