Skip to content

Commit 8bcf85d

Browse files
committed
Fix RULE-5-10-1 false positives on compiler-predefined function identifiers
RULE-5-10-1 (poorly-formed identifier) flagged the compiler-predefined function identifiers __func__, __FUNCTION__ and __PRETTY_FUNCTION__ for containing double underscores / leading underscores. These are not user-defined identifiers: __func__ is mandated by the C++ standard and __FUNCTION__/__PRETTY_FUNCTION__ are GCC/Clang extensions, synthesized once per enclosing function. They frequently surface via assert-style macros, producing one finding per macro invocation site (on this codebase, 228 findings, ~79% of the rule's results). The shared IdentifierIntroduction library already excludes `variable.isCompilerGenerated()`, but the extractor does not mark these predefined variables as compiler generated, so they leak through. Exclude them in VariableDeclarationEntryIdentifier using a name-independent structural signal: they are `static` local variables with no definition (their only declaration entry is located at a use site), whereas a genuine `static` local always has an in-source definition. This deliberately avoids hard-coding the names, so a user who really declares such an identifier (on a compiler that does not predefine it) still has a definition and is therefore still flagged. Add a regression test to RULE-5-10-1 covering __func__ and __PRETTY_FUNCTION__ (COMPLIANT). The false positive reproduces in the single-translation-unit test harness: without this fix the test fails with the four spurious findings; with it the test passes. The existing RULE-5-10-1 and Identifiers library tests continue to pass. Fixes #1170
1 parent 62bf905 commit 8bcf85d

4 files changed

Lines changed: 33 additions & 1 deletion

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `RULE-5-10-1` - `PoorlyFormedIdentifier.ql`:
2+
- Avoid false positives for none user defined identifiers like __PRETTY_FUNCTION__

cpp/common/src/codingstandards/cpp/Identifiers.qll

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,20 @@ private module IdentifierIntroductionImpl {
332332
not variable.isCompilerGenerated() and
333333
// Some variables are not correctly marked as compiler generated, such as parameters of lambda
334334
// conversion operators.
335-
not variable.(Parameter).getFunction().isCompilerGenerated()
335+
not variable.(Parameter).getFunction().isCompilerGenerated() and
336+
// The compiler-provided predefined function identifiers (`__func__`, and the GCC/Clang
337+
// extensions `__FUNCTION__` and `__PRETTY_FUNCTION__`) are synthesized once per enclosing
338+
// function, but the extractor does not flag them as compiler generated, so they leak through
339+
// the check above. They are not user-defined identifiers and should not be reported. Rather
340+
// than hard-coding these names (which would wrongly suppress a genuine user declaration of
341+
// such an identifier on a compiler that does not predefine it), we identify them
342+
// structurally: they are `static` local variables with no definition (their only declaration
343+
// entry is located at a use site), whereas a real `static` local always has an in-source
344+
// definition.
345+
not (
346+
variable.(LocalVariable).isStatic() and
347+
not variable.hasDefinition()
348+
)
336349
// Note: Some duplicate and/or unflagged compiler-generated variables seem to exist in tests,
337350
// which may be related to constexpr in templates. These redundant variables seem to only be
338351
// distinguishable by the fact that their start location is the same as their end location.

cpp/misra/test/rules/RULE-5-10-1/PoorlyFormedIdentifier.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,5 @@
4949
| test.cpp:184:7:184:15 | wctrans_t | Identifier 'wctrans_t' is a reserved name. |
5050
| test.cpp:185:7:185:14 | wctype_t | Identifier 'wctype_t' is a reserved name. |
5151
| test.cpp:186:7:186:12 | wint_t | Identifier 'wint_t' is a reserved name. |
52+
| test.cpp:202:1:202:42 | __PRETTY_FUNCTION__ | Identifier '__PRETTY_FUNCTION__' contains double underscores. |
53+
| test.cpp:202:1:202:42 | __PRETTY_FUNCTION__ | Identifier '__PRETTY_FUNCTION__' starts with underscore. |

cpp/misra/test/rules/RULE-5-10-1/test.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,21 @@ void test_reserved_names() {
186186
int wint_t = 20; // NON_COMPLIANT - reserved name
187187
}
188188

189+
// Test case for compiler-predefined function identifiers (not user-defined).
190+
// __func__ is standard; __FUNCTION__ and __PRETTY_FUNCTION__ are GCC/Clang
191+
// extensions. They are synthesized per-function by the compiler, so despite
192+
// containing double underscores / leading underscores they must not be flagged.
193+
const char *test_predefined_function_identifiers() {
194+
const char *a = __func__; // COMPLIANT - compiler-predefined, not user-defined
195+
const char *b = __PRETTY_FUNCTION__; // COMPLIANT - compiler-predefined, not user-defined
196+
return a ? a : b;
197+
}
198+
199+
// Test case for a user-defined macro that reuses a compiler-predefined name.
200+
// Redefining __PRETTY_FUNCTION__ as a macro is a user-defined identifier and
201+
// should be flagged (double underscores + lowercase).
202+
#define __PRETTY_FUNCTION__ "user_defined" // NON_COMPLIANT - user-defined macro
203+
189204
// Test case for valid identifiers
190205
void test_valid_identifiers() {
191206
int validName = 1; // COMPLIANT

0 commit comments

Comments
 (0)