From ee2ed074cdaf35869dee19e47d03416cd6fe859f Mon Sep 17 00:00:00 2001 From: Jan Schlosser Date: Mon, 26 Oct 2026 15:06:12 +0100 Subject: [PATCH] Fix RULE-7-11-3 false positives for callees in templates Inside class and function templates, an unqualified call to a member or free function can be modelled as a FunctionAccess that is the called expression of an ExprCall. Such an access is the callee of a call, not an implicit conversion to a function pointer, but it has function pointer type and was reported by FunctionPointerConversionContext. Exclude function accesses that are the called expression of an ExprCall, and add test cases for member, static member and free function calls inside templates. --- ...0-26-fix-fp-rule-7-11-3-template-callee.md | 2 ++ .../FunctionPointerConversionContext.ql | 5 ++- cpp/misra/test/rules/RULE-7-11-3/test.cpp | 31 ++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 change_notes/2026-10-26-fix-fp-rule-7-11-3-template-callee.md diff --git a/change_notes/2026-10-26-fix-fp-rule-7-11-3-template-callee.md b/change_notes/2026-10-26-fix-fp-rule-7-11-3-template-callee.md new file mode 100644 index 0000000000..58b2232a33 --- /dev/null +++ b/change_notes/2026-10-26-fix-fp-rule-7-11-3-template-callee.md @@ -0,0 +1,2 @@ +- `RULE-7-11-3` - `FunctionPointerConversionContext.ql`: + - Fixed false positives on unqualified calls to member and free functions inside class and function templates, where the callee is modelled as a function access that is the called expression of a call rather than a conversion to a function pointer. diff --git a/cpp/misra/src/rules/RULE-7-11-3/FunctionPointerConversionContext.ql b/cpp/misra/src/rules/RULE-7-11-3/FunctionPointerConversionContext.ql index f58629f536..c7cb1d18d6 100644 --- a/cpp/misra/src/rules/RULE-7-11-3/FunctionPointerConversionContext.ql +++ b/cpp/misra/src/rules/RULE-7-11-3/FunctionPointerConversionContext.ql @@ -33,7 +33,10 @@ class FunctionAccessConversionToFunctionPointer extends FunctionAccess, FunctionToFunctionPointerConversion { FunctionAccessConversionToFunctionPointer() { - this.getType().getUnspecifiedType() instanceof FunctionPointerIshType + this.getType().getUnspecifiedType() instanceof FunctionPointerIshType and + // In templates, the callee of a dependent call is modelled as a function access that is the + // called expression of an ExprCall. This is a function call, not a conversion. + not any(ExprCall call).getExpr() = this } } diff --git a/cpp/misra/test/rules/RULE-7-11-3/test.cpp b/cpp/misra/test/rules/RULE-7-11-3/test.cpp index 0522a703fc..5fd6f61f23 100644 --- a/cpp/misra/test/rules/RULE-7-11-3/test.cpp +++ b/cpp/misra/test/rules/RULE-7-11-3/test.cpp @@ -95,4 +95,33 @@ void test_logical_expressions() { // Lambda used in logical OR expression if (lam || false) { // NON_COMPLIANT } -} \ No newline at end of file +} +template class TemplateWithMemberCalls { +public: + void callMembers() { + helper(); // COMPLIANT: callee of a call, not a conversion + this->helper(); // COMPLIANT + staticHelper(); // COMPLIANT + TemplateWithMemberCalls::staticHelper(); // COMPLIANT + } + + auto takeAddress() { + return &TemplateWithMemberCalls::helper; // COMPLIANT: member pointer, not a + // function pointer + } + +private: + void helper() {} + static void staticHelper() {} +}; + +template void templateCallsFree() { + f(); // COMPLIANT +} + +void instantiate() { + TemplateWithMemberCalls t; + t.callMembers(); + t.takeAddress(); + templateCallsFree(); +}