diff --git a/change_notes/2024-06-03-a3-1-5-trivial-defs.md b/change_notes/2024-06-03-a3-1-5-trivial-defs.md new file mode 100644 index 0000000000..29a7f48eb5 --- /dev/null +++ b/change_notes/2024-06-03-a3-1-5-trivial-defs.md @@ -0,0 +1,4 @@ + - `A3-1-5` - `TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql`: + - Query deleted - rule was never intended to cover this case (see https://forum.misra.org.uk/archive/index.php?thread-1588.html). + - `A3-1-5` - `NonTrivialNonTemplateFunctionDefinedInsideClassDefinition.ql`: + - Removed false positives caused by flagging member functions in template instantiations diff --git a/cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql b/cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql deleted file mode 100644 index 920875ca3b..0000000000 --- a/cpp/autosar/src/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @id cpp/autosar/trivial-or-template-function-defined-outside-class-definition - * @name A3-1-5: A function shall be defined with a class body if and only if it is intended to be inlined - * @description A function that is either trivial, a template function, or a member of a template - * class may not be defined outside of a class body. - * @kind problem - * @precision very-high - * @problem.severity recommendation - * @tags external/autosar/id/a3-1-5 - * external/autosar/allocated-target/design - * external/autosar/enforcement/partially-automated - * external/autosar/obligation/required - */ - -import cpp -import codingstandards.cpp.autosar -import codingstandards.cpp.Class - -/* - * Find instances of `MemberFunction` where the `MemberFunction` is trivial - * and it is not inlined within the class. - */ - -from MemberFunction mf, string kind -where - not isExcluded(mf, ClassesPackage::trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery()) and - // The member function `mf` is not defined in the class body. - exists(FunctionDeclarationEntry fde | - fde = mf.getClassBodyDeclarationEntry() and not fde.isDefinition() - ) and - //ignore destructors - not mf instanceof Destructor and - // Report functions that are NOT defined in the class body if they are either trivial or - // either a template member or part of a template class (i.e., they should - // be defined in the class body) - ( - if - mf instanceof TemplateOrTemplateClassMemberFunction and - mf instanceof TrivialMemberFunction - then kind = "template" - else - if mf instanceof TrivialMemberFunction - then kind = "trivial" - else - if mf instanceof TemplateOrTemplateClassMemberFunction - then kind = "template" - else none() - ) -select mf, - "The " + kind + " member function " + mf.getName() + " is not defined in the class body of $@.", - mf.getDeclaringType(), mf.getDeclaringType().getName() diff --git a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected b/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected deleted file mode 100644 index dc0e220a94..0000000000 --- a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.expected +++ /dev/null @@ -1,7 +0,0 @@ -| test.cpp:65:5:65:11 | getB | The trivial member function getB is not defined in the class body of $@. | test.cpp:2:7:2:7 | A | A | -| test.cpp:67:25:67:28 | d | The template member function d is not defined in the class body of $@. | test.cpp:2:7:2:7 | A | A | -| test.cpp:69:5:69:8 | b | The trivial member function b is not defined in the class body of $@. | test.cpp:2:7:2:7 | A | A | -| test.cpp:88:34:88:57 | complexCalculation | The template member function complexCalculation is not defined in the class body of $@. | test.cpp:71:29:71:29 | B | B | -| test.cpp:104:47:104:53 | d | The template member function d is not defined in the class body of $@. | test.cpp:71:29:71:29 | B | B | -| test.cpp:108:27:108:33 | b | The template member function b is not defined in the class body of $@. | test.cpp:71:29:71:29 | B | B | -| test.cpp:113:27:113:36 | getB | The template member function getB is not defined in the class body of $@. | test.cpp:71:29:71:29 | B | B | diff --git a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref b/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref deleted file mode 100644 index c644147bb4..0000000000 --- a/cpp/autosar/test/rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A3-1-5/TrivialOrTemplateFunctionDefinedOutsideClassDefinition.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-1-5/test.cpp b/cpp/autosar/test/rules/A3-1-5/test.cpp index eb1de61b51..1b2898bf63 100644 --- a/cpp/autosar/test/rules/A3-1-5/test.cpp +++ b/cpp/autosar/test/rules/A3-1-5/test.cpp @@ -23,7 +23,7 @@ class A { int complexCalculation(); - int gcd(int a, int b) { + int gcd(int a, int b) { // NON_COMPLIANT if (b == 0) return a; int result = gcd(b, (a % b)); @@ -62,11 +62,11 @@ inline int A::complexCalculation() { // COMPLIANT return 1; } -int A::getB() { return 1; } // NON_COMPLIANT +int A::getB() { return 1; } // COMPLIANT -template T A::d(T t) { return t; } // NON_COMPLIANT +template T A::d(T t) { return t; } // COMPLIANT -int A::b() { return 3; } // NON_COMPLIANT +int A::b() { return 3; } // COMPLIANT template class B { public: @@ -83,9 +83,30 @@ template class B { template T d(T t); int complexCalculation(); + + int complexCalculation2() { // COMPLIANT - template + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + return 1; + } }; -template inline int B::complexCalculation() { // NON_COMPLIANT +void test_B() { + B b; + b.complexCalculation2(); +} + +template inline int B::complexCalculation() { // COMPLIANT ; ; ; @@ -101,16 +122,16 @@ template inline int B::complexCalculation() { // NON_COMPLIANT return 1; } -template template T B::d(T t) { // NON_COMPLIANT +template template T B::d(T t) { // COMPLIANT return t; } -template int B::b() { // NON_COMPLIANT +template int B::b() { // COMPLIANT C c; return 3; } -template int B::getB() { return 3; } // NON_COMPLIANT +template int B::getB() { return 3; } // COMPLIANT template class Foo { public: @@ -128,8 +149,29 @@ class FooBar { public: ~FooBar(); int f1(int a, int b); + + template int complexCalculation() { // COMPLIANT - template + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + return 1; + } }; +void test_FooBar() { + FooBar foobar; + foobar.complexCalculation(); +} + FooBar::~FooBar() {} // COMPLIANT want to ignore pImpl uses of destructors int FooBar::f1(int a, int b) { // COMPLIANT not a trivial function diff --git a/cpp/common/src/codingstandards/cpp/Class.qll b/cpp/common/src/codingstandards/cpp/Class.qll index 418f027809..6f730736f9 100644 --- a/cpp/common/src/codingstandards/cpp/Class.qll +++ b/cpp/common/src/codingstandards/cpp/Class.qll @@ -191,7 +191,13 @@ class TrivialMemberFunction extends IntrospectedMemberFunction { * class. */ class TemplateOrTemplateClassMemberFunction extends MemberFunction { - TemplateOrTemplateClassMemberFunction() { isFromUninstantiatedTemplate(_) } + TemplateOrTemplateClassMemberFunction() { + ( + isFromUninstantiatedTemplate(_) or + isFromTemplateInstantiation(_) + ) and + not this.isCompilerGenerated() + } } /** diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll index 92c7a4280e..3daf48c696 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll @@ -13,7 +13,6 @@ newtype ClassesQuery = TClassDataMembersInitializationConditionQuery() or TRedundantMemberFunctionsShouldBeDefaultedOrLeftUndefinedQuery() or TNonTemplateMemberDefinedInTemplateQuery() or - TTrivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() or TNonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() or TInParametersForNotCheapToCopyTypesNotPassedByReferenceQuery() or TInParametersForCheapToCopyTypesNotPassedByValueQuery() or @@ -105,15 +104,6 @@ predicate isClassesQueryMetadata(Query query, string queryId, string ruleId, str ruleId = "A14-5-2" and category = "advisory" or - query = - // `Query` instance for the `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - ClassesPackage::trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() and - queryId = - // `@id` for the `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - "cpp/autosar/trivial-or-template-function-defined-outside-class-definition" and - ruleId = "A3-1-5" and - category = "required" - or query = // `Query` instance for the `nonTrivialNonTemplateFunctionDefinedInsideClassDefinition` query ClassesPackage::nonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() and @@ -251,13 +241,6 @@ module ClassesPackage { TQueryCPP(TClassesPackageQuery(TNonTemplateMemberDefinedInTemplateQuery())) } - Query trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() { - //autogenerate `Query` type - result = - // `Query` type for `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - TQueryCPP(TClassesPackageQuery(TTrivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery())) - } - Query nonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() { //autogenerate `Query` type result = diff --git a/rule_packages/cpp/Classes.json b/rule_packages/cpp/Classes.json index 61eab45081..6dd130a55b 100644 --- a/rule_packages/cpp/Classes.json +++ b/rule_packages/cpp/Classes.json @@ -178,15 +178,6 @@ "obligation": "required" }, "queries": [ - { - "description": "A function that is either trivial, a template function, or a member of a template class may not be defined outside of a class body.", - "kind": "problem", - "name": "A function shall be defined with a class body if and only if it is intended to be inlined", - "precision": "very-high", - "severity": "recommendation", - "short_name": "TrivialOrTemplateFunctionDefinedOutsideClassDefinition", - "tags": [] - }, { "description": "A function that is not either trivial, a template function, or a member of a template class may not be defined within a class body.", "kind": "problem",