From fbc9cee2cf5149374ad3d24b6fb11f6322310795 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Mon, 20 Feb 2023 14:07:05 +0000 Subject: [PATCH 01/14] M14-6-1: Extra test cases for non-dependent base types The rule specifically only refers to dependent base types of class templates. --- cpp/autosar/test/rules/M14-6-1/test.cpp | 33 ++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/cpp/autosar/test/rules/M14-6-1/test.cpp b/cpp/autosar/test/rules/M14-6-1/test.cpp index 7358a5e5e0..d7e7313162 100644 --- a/cpp/autosar/test/rules/M14-6-1/test.cpp +++ b/cpp/autosar/test/rules/M14-6-1/test.cpp @@ -35,4 +35,35 @@ void f() { A a; a.m1(); a.m2(); -} \ No newline at end of file +} + +class D { +public: + typedef int TYPE; + void g(); + void g(int x); + static void sg(); + static void sg(int x); + int m; +}; + +class C : D { +public: + void m1() { + m = 0; // COMPLIANT - does not apply to non-class templates + g(); // COMPLIANT - does not apply to non-class templates + sg(); // COMPLIANT - does not apply to non-class templates + TYPE t = 0; // COMPLIANT - does not apply to non-class templates + // void (*p)() = &g; // NON_COMPILABLE + } +}; + +template class E : D { +public: + void m1() { + m = 0; // COMPLIANT - does not apply to non dependent base types + g(); // COMPLIANT - does not apply to non dependent base types + TYPE t = 0; // COMPLIANT - does not apply to non dependent base types + void (*p)() = &g; // COMPLIANT - does not apply to non dependent base types + } +}; \ No newline at end of file From 7b6cc90891c8892374fcda8087c08bd8bf2129bd Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 00:18:50 +0000 Subject: [PATCH 02/14] M14-6-1: Restrict to templates with dependent base The query didn't explicitly enforce this condition, and instead relied on the fact that NameQualifiableElement's without any qualifier would only point to the "wrong" element within templates. However, there are some edge cases (static member functions with overrides) where non-class templates could be flagged. This commit restricts the output to the set of template classes with dependent base types, therefore avoiding the sort of false positives seen above. In addition, this improves performance for this query because the set of template classes with dependent base types is much much much smaller than the overall set of base types. --- .../src/rules/M14-6-1/NameInDependentBase.qll | 15 +++++++++++++-- .../NameNotReferredUsingAQualifiedIdOrThis.ql | 10 +++++----- ...NameNotReferredUsingAQualifiedIdOrThisAudit.ql | 10 +++++----- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 93c99c3d76..223d54a434 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -2,9 +2,20 @@ import cpp import codingstandards.cpp.autosar /** - * Just the reverse of `Class.getABaseClass()` + * Gets a dependent base type of the given template class. + * + * This returns the `TemplateClass` for the base type, rather than the `ClassTemplateInstantiation`, + * as the instantiation does not appear to include any member declarations. */ -Class getParent(Class child) { child.getABaseClass() = result } +TemplateClass getADependentBaseType(TemplateClass t) { + exists(ClassTemplateInstantiation baseType | + baseType = t.getABaseClass() and + // Base type depends on at least one of the template parameters of class t + baseType.getATemplateArgument() = t.getATemplateArgument() and + // Return the template itself + result = baseType.getTemplate() + ) +} /** * There is a `MemberFunction` in parent class with same name diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql index 7d23ddb949..1ac4f17578 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql @@ -18,23 +18,23 @@ import cpp import codingstandards.cpp.autosar import NameInDependentBase -from Class c, Class p, NameQualifiableElement fn +from TemplateClass c, TemplateClass dependentBaseType, NameQualifiableElement fn where not isExcluded(fn, TemplatesPackage::nameNotReferredUsingAQualifiedIdOrThisQuery()) and not isCustomExcluded(fn) and - p = getParent(c) and + dependentBaseType = getADependentBaseType(c) and missingNameQualifier(fn) and ( fn instanceof FunctionAccess and - fn = parentMemberFunctionAccess(c, p) + fn = parentMemberFunctionAccess(c, dependentBaseType) or fn instanceof FunctionCall and - fn = parentMemberFunctionCall(c, p) and + fn = parentMemberFunctionCall(c, dependentBaseType) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or fn instanceof VariableAccess and not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = parentMemberAccess(c, p) and + fn = parentMemberAccess(c, dependentBaseType) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) and not fn.isAffectedByMacro() diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql index e231967ad1..6c06bf319a 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql @@ -18,23 +18,23 @@ import cpp import codingstandards.cpp.autosar import NameInDependentBase -from Class c, Class p, NameQualifiableElement fn +from TemplateClass c, TemplateClass dependentBaseType, NameQualifiableElement fn where not isExcluded(fn, TemplatesPackage::nameNotReferredUsingAQualifiedIdOrThisAuditQuery()) and not isCustomExcluded(fn) and - p = getParent(c) and + dependentBaseType = getADependentBaseType(c) and missingNameQualifier(fn) and ( fn instanceof FunctionAccess and - fn = parentMemberFunctionAccess(c, p) + fn = parentMemberFunctionAccess(c, dependentBaseType) or fn instanceof FunctionCall and - fn = parentMemberFunctionCall(c, p) and + fn = parentMemberFunctionCall(c, dependentBaseType) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or fn instanceof VariableAccess and not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = parentMemberAccess(c, p) and + fn = parentMemberAccess(c, dependentBaseType) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) select fn, "Use of identifier that also exists in a base class that is not fully qualified." From 0d43de51f4d2cd13aeb760b2608281ae93cf8780 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 00:35:37 +0000 Subject: [PATCH 03/14] M14-6-1: Push dependent base type context Push the dependent type context into the individual determination of contravening cases to work towards addressing performance issues. --- .../src/rules/M14-6-1/NameInDependentBase.qll | 31 ++++++++++--------- .../NameNotReferredUsingAQualifiedIdOrThis.ql | 9 +++--- ...NotReferredUsingAQualifiedIdOrThisAudit.ql | 9 +++--- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 223d54a434..60c73fd07f 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -18,16 +18,17 @@ TemplateClass getADependentBaseType(TemplateClass t) { } /** - * There is a `MemberFunction` in parent class with same name - * as a `FunctionCall` that exists in a child `MemberFunction` + * Gets a function call in `TemplateClass` `t` where the target function name exists in a dependent + * base type and the function does not call that function. */ -FunctionCall parentMemberFunctionCall(Class child, Class parent) { - exists(MemberFunction parentFunction, Function other | +FunctionCall parentMemberFunctionCall(TemplateClass t) { + exists(TemplateClass dependentBaseType, MemberFunction parentFunction, Function other | + dependentBaseType = getADependentBaseType(t) and not other = parentFunction and - parent.getAMember() = parentFunction and + dependentBaseType.getAMember() = parentFunction and other.getName() = parentFunction.getName() and result = other.getACallToThisFunction() and - result.getEnclosingFunction() = child.getAMemberFunction() + result.getEnclosingFunction() = t.getAMemberFunction() ) } @@ -35,13 +36,14 @@ FunctionCall parentMemberFunctionCall(Class child, Class parent) { * There is a `MemberFunction` in parent class with same name * as a `FunctionAccess` that exists in a child `MemberFunction` */ -FunctionAccess parentMemberFunctionAccess(Class child, Class parent) { - exists(MemberFunction parentFunction, Function other | +FunctionAccess parentMemberFunctionAccess(TemplateClass t) { + exists(TemplateClass dependentBaseType, MemberFunction parentFunction, Function other | + dependentBaseType = getADependentBaseType(t) and not other = parentFunction and - parent.getAMember() = parentFunction and + dependentBaseType.getAMember() = parentFunction and other.getName() = parentFunction.getName() and result = other.getAnAccess() and - result.getEnclosingFunction() = child.getAMemberFunction() + result.getEnclosingFunction() = t.getAMemberFunction() ) } @@ -49,13 +51,14 @@ FunctionAccess parentMemberFunctionAccess(Class child, Class parent) { * There is a `MemberVariable` in parent class with same name * as a `VariableAccess` that exists in a child `MemberFunction` */ -Access parentMemberAccess(Class child, Class parent) { - exists(MemberVariable parentMember, Variable other | +Access parentMemberAccess(TemplateClass t) { + exists(TemplateClass dependentBaseType, MemberVariable parentMember, Variable other | + dependentBaseType = getADependentBaseType(t) and not other = parentMember and - parent.getAMemberVariable() = parentMember and + dependentBaseType.getAMemberVariable() = parentMember and other.getName() = parentMember.getName() and result = other.getAnAccess() and - result.getEnclosingFunction() = child.getAMemberFunction() + result.getEnclosingFunction() = t.getAMemberFunction() ) } diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql index 1ac4f17578..ada692a626 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql @@ -18,23 +18,22 @@ import cpp import codingstandards.cpp.autosar import NameInDependentBase -from TemplateClass c, TemplateClass dependentBaseType, NameQualifiableElement fn +from TemplateClass c, NameQualifiableElement fn where not isExcluded(fn, TemplatesPackage::nameNotReferredUsingAQualifiedIdOrThisQuery()) and not isCustomExcluded(fn) and - dependentBaseType = getADependentBaseType(c) and missingNameQualifier(fn) and ( fn instanceof FunctionAccess and - fn = parentMemberFunctionAccess(c, dependentBaseType) + fn = parentMemberFunctionAccess(c) or fn instanceof FunctionCall and - fn = parentMemberFunctionCall(c, dependentBaseType) and + fn = parentMemberFunctionCall(c) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or fn instanceof VariableAccess and not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = parentMemberAccess(c, dependentBaseType) and + fn = parentMemberAccess(c) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) and not fn.isAffectedByMacro() diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql index 6c06bf319a..6bc958d4a6 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql @@ -18,23 +18,22 @@ import cpp import codingstandards.cpp.autosar import NameInDependentBase -from TemplateClass c, TemplateClass dependentBaseType, NameQualifiableElement fn +from TemplateClass c, NameQualifiableElement fn where not isExcluded(fn, TemplatesPackage::nameNotReferredUsingAQualifiedIdOrThisAuditQuery()) and not isCustomExcluded(fn) and - dependentBaseType = getADependentBaseType(c) and missingNameQualifier(fn) and ( fn instanceof FunctionAccess and - fn = parentMemberFunctionAccess(c, dependentBaseType) + fn = parentMemberFunctionAccess(c) or fn instanceof FunctionCall and - fn = parentMemberFunctionCall(c, dependentBaseType) and + fn = parentMemberFunctionCall(c) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or fn instanceof VariableAccess and not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = parentMemberAccess(c, dependentBaseType) and + fn = parentMemberAccess(c) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) select fn, "Use of identifier that also exists in a base class that is not fully qualified." From e5b9d159649a769d5df83ede756cd3680479fdb2 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 00:42:04 +0000 Subject: [PATCH 04/14] M14-6-1: Re-name vars for clarity --- .../src/rules/M14-6-1/NameInDependentBase.qll | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 60c73fd07f..50f1c5b4cf 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -22,12 +22,12 @@ TemplateClass getADependentBaseType(TemplateClass t) { * base type and the function does not call that function. */ FunctionCall parentMemberFunctionCall(TemplateClass t) { - exists(TemplateClass dependentBaseType, MemberFunction parentFunction, Function other | + exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | dependentBaseType = getADependentBaseType(t) and - not other = parentFunction and - dependentBaseType.getAMember() = parentFunction and - other.getName() = parentFunction.getName() and - result = other.getACallToThisFunction() and + not target = dependentTypeFunction and + dependentBaseType.getAMember() = dependentTypeFunction and + target.getName() = dependentTypeFunction.getName() and + result = target.getACallToThisFunction() and result.getEnclosingFunction() = t.getAMemberFunction() ) } @@ -37,12 +37,12 @@ FunctionCall parentMemberFunctionCall(TemplateClass t) { * as a `FunctionAccess` that exists in a child `MemberFunction` */ FunctionAccess parentMemberFunctionAccess(TemplateClass t) { - exists(TemplateClass dependentBaseType, MemberFunction parentFunction, Function other | + exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | dependentBaseType = getADependentBaseType(t) and - not other = parentFunction and - dependentBaseType.getAMember() = parentFunction and - other.getName() = parentFunction.getName() and - result = other.getAnAccess() and + not target = dependentTypeFunction and + dependentBaseType.getAMember() = dependentTypeFunction and + target.getName() = dependentTypeFunction.getName() and + result = target.getAnAccess() and result.getEnclosingFunction() = t.getAMemberFunction() ) } @@ -52,12 +52,14 @@ FunctionAccess parentMemberFunctionAccess(TemplateClass t) { * as a `VariableAccess` that exists in a child `MemberFunction` */ Access parentMemberAccess(TemplateClass t) { - exists(TemplateClass dependentBaseType, MemberVariable parentMember, Variable other | + exists( + TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, Variable target + | dependentBaseType = getADependentBaseType(t) and - not other = parentMember and - dependentBaseType.getAMemberVariable() = parentMember and - other.getName() = parentMember.getName() and - result = other.getAnAccess() and + not target = dependentTypeMemberVariable and + dependentBaseType.getAMemberVariable() = dependentTypeMemberVariable and + target.getName() = dependentTypeMemberVariable.getName() and + result = target.getAnAccess() and result.getEnclosingFunction() = t.getAMemberFunction() ) } From ac2762324f8b43061065e4bf1a0639f8447470e0 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 00:55:20 +0000 Subject: [PATCH 05/14] M14-6-1: Handle overloading Previously the logic of this query asserted that the function call did not target the selected function in the dependent base type with the same name. In theory this is wrong, as overloading can permit multiple functions declarations with the same name, but different signatures, so we now say that the target is not declared on the same base type. In practice, such results would be excluded because to call an overload of the same function would always have a qualifier in this case, however this logic makes the intention clearer. --- cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 50f1c5b4cf..3f41abe93f 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -24,7 +24,7 @@ TemplateClass getADependentBaseType(TemplateClass t) { FunctionCall parentMemberFunctionCall(TemplateClass t) { exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | dependentBaseType = getADependentBaseType(t) and - not target = dependentTypeFunction and + not target.getDeclaringType() = dependentBaseType and dependentBaseType.getAMember() = dependentTypeFunction and target.getName() = dependentTypeFunction.getName() and result = target.getACallToThisFunction() and @@ -39,7 +39,7 @@ FunctionCall parentMemberFunctionCall(TemplateClass t) { FunctionAccess parentMemberFunctionAccess(TemplateClass t) { exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | dependentBaseType = getADependentBaseType(t) and - not target = dependentTypeFunction and + not target.getDeclaringType() = dependentBaseType and dependentBaseType.getAMember() = dependentTypeFunction and target.getName() = dependentTypeFunction.getName() and result = target.getAnAccess() and @@ -56,7 +56,7 @@ Access parentMemberAccess(TemplateClass t) { TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, Variable target | dependentBaseType = getADependentBaseType(t) and - not target = dependentTypeMemberVariable and + not target.getDeclaringType() = dependentBaseType and dependentBaseType.getAMemberVariable() = dependentTypeMemberVariable and target.getName() = dependentTypeMemberVariable.getName() and result = target.getAnAccess() and From 8d89f17bbc176aa4950ec7b664b98459d318ebdf Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 01:00:42 +0000 Subject: [PATCH 06/14] M14-6-1: Clarify documention --- .../src/rules/M14-6-1/NameInDependentBase.qll | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 3f41abe93f..e28fdde03c 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -19,11 +19,12 @@ TemplateClass getADependentBaseType(TemplateClass t) { /** * Gets a function call in `TemplateClass` `t` where the target function name exists in a dependent - * base type and the function does not call that function. + * base type and the call is to a function that is not declared in the dependent base type. */ FunctionCall parentMemberFunctionCall(TemplateClass t) { exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | dependentBaseType = getADependentBaseType(t) and + // The target of the call is not declared in the dependent base type not target.getDeclaringType() = dependentBaseType and dependentBaseType.getAMember() = dependentTypeFunction and target.getName() = dependentTypeFunction.getName() and @@ -33,12 +34,13 @@ FunctionCall parentMemberFunctionCall(TemplateClass t) { } /** - * There is a `MemberFunction` in parent class with same name - * as a `FunctionAccess` that exists in a child `MemberFunction` + * Gets a function access in `TemplateClass` `t` where the target function name exists in a dependent + * base type and the access is to a function declared outside the dependent base type. */ FunctionAccess parentMemberFunctionAccess(TemplateClass t) { exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | dependentBaseType = getADependentBaseType(t) and + // The target of the access is not declared in the dependent base type not target.getDeclaringType() = dependentBaseType and dependentBaseType.getAMember() = dependentTypeFunction and target.getName() = dependentTypeFunction.getName() and @@ -48,14 +50,15 @@ FunctionAccess parentMemberFunctionAccess(TemplateClass t) { } /** - * There is a `MemberVariable` in parent class with same name - * as a `VariableAccess` that exists in a child `MemberFunction` + * Gets a memmber access in `TemplateClass` `t` where the target member name exists in a dependent + * base type and the access is to a variable declared outside the dependent base type. */ Access parentMemberAccess(TemplateClass t) { exists( TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, Variable target | dependentBaseType = getADependentBaseType(t) and + // The target of the access is not declared in the dependent base type not target.getDeclaringType() = dependentBaseType and dependentBaseType.getAMemberVariable() = dependentTypeMemberVariable and target.getName() = dependentTypeMemberVariable.getName() and From 82644bcd3c553ba2715301a4c9cf796705b8ad31 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 01:30:57 +0000 Subject: [PATCH 07/14] M14-6-3: Address perf problems Performance issues occurred because we are trying to find pairs of functions or variables which have the same name but are not the same. The join orderer is very keen on joining two copies of the function/ variable table early on which, on large databases like openpilot with a lot of name duplication, can cause signficant blow-up. The workaround is to provide helper predicates that ensure the restricted set of functions/variables we care about (targets of accesses or calls in templates with dependent base types) are computed first, then the name is joined with a member on the dependent base type. --- .../src/rules/M14-6-1/NameInDependentBase.qll | 89 ++++++++++++++----- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index e28fdde03c..8722dab604 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -17,53 +17,98 @@ TemplateClass getADependentBaseType(TemplateClass t) { ) } +/** + * Helper predicate that ensures we do not join on function pairs by name early on, as that creates + * a large dataset on big databases with lots of name duplication. + */ +pragma[noinline, nomagic] +private FunctionCall helper_functioncall( + TemplateClass t, TemplateClass dependentBaseType, Function target, string name +) { + dependentBaseType = getADependentBaseType(t) and + // The target of the call is not declared in the dependent base type + not target.getDeclaringType() = dependentBaseType and + result = target.getACallToThisFunction() and + result.getEnclosingFunction() = t.getAMemberFunction() and + name = target.getName() +} + /** * Gets a function call in `TemplateClass` `t` where the target function name exists in a dependent * base type and the call is to a function that is not declared in the dependent base type. */ FunctionCall parentMemberFunctionCall(TemplateClass t) { - exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | - dependentBaseType = getADependentBaseType(t) and - // The target of the call is not declared in the dependent base type - not target.getDeclaringType() = dependentBaseType and + exists( + string name, TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, + Function target + | + result = helper_functioncall(t, dependentBaseType, target, name) and + // The dependentTypeFunction is declared on the dependent base type dependentBaseType.getAMember() = dependentTypeFunction and - target.getName() = dependentTypeFunction.getName() and - result = target.getACallToThisFunction() and - result.getEnclosingFunction() = t.getAMemberFunction() + // And has the same name as the target of the function call in the child + name = dependentTypeFunction.getName() ) } +/** + * Helper predicate that ensures we do not join on function pairs by name early on, as that creates + * a large dataset on big databases with lots of name duplication. + */ +pragma[noinline, nomagic] +private FunctionAccess helper_functionaccess( + TemplateClass t, TemplateClass dependentBaseType, Function target, string name +) { + dependentBaseType = getADependentBaseType(t) and + // The target of the access is not declared in the dependent base type + not target.getDeclaringType() = dependentBaseType and + result = target.getAnAccess() and + result.getEnclosingFunction() = t.getAMemberFunction() and + name = target.getName() +} + /** * Gets a function access in `TemplateClass` `t` where the target function name exists in a dependent * base type and the access is to a function declared outside the dependent base type. */ FunctionAccess parentMemberFunctionAccess(TemplateClass t) { - exists(TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target | - dependentBaseType = getADependentBaseType(t) and - // The target of the access is not declared in the dependent base type - not target.getDeclaringType() = dependentBaseType and + exists( + string name, TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, + Function target + | + result = helper_functionaccess(t, dependentBaseType, target, name) and dependentBaseType.getAMember() = dependentTypeFunction and - target.getName() = dependentTypeFunction.getName() and - result = target.getAnAccess() and - result.getEnclosingFunction() = t.getAMemberFunction() + name = dependentTypeFunction.getName() ) } +/** + * Helper predicate that ensures we do not join on variable pairs by name early on, as that creates + * a large dataset on big databases with lots of name duplication. + */ +pragma[noinline, nomagic] +private VariableAccess helper_memberaccess( + TemplateClass t, TemplateClass dependentBaseType, Variable target, string name +) { + dependentBaseType = getADependentBaseType(t) and + // The target of the access is not declared in the dependent base type + not target.getDeclaringType() = dependentBaseType and + result = target.getAnAccess() and + result.getEnclosingFunction() = t.getAMemberFunction() and + name = target.getName() +} + /** * Gets a memmber access in `TemplateClass` `t` where the target member name exists in a dependent * base type and the access is to a variable declared outside the dependent base type. */ -Access parentMemberAccess(TemplateClass t) { +VariableAccess parentMemberAccess(TemplateClass t) { exists( - TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, Variable target + string name, TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, + Variable target | - dependentBaseType = getADependentBaseType(t) and - // The target of the access is not declared in the dependent base type - not target.getDeclaringType() = dependentBaseType and + result = helper_memberaccess(t, dependentBaseType, target, name) and dependentBaseType.getAMemberVariable() = dependentTypeMemberVariable and - target.getName() = dependentTypeMemberVariable.getName() and - result = target.getAnAccess() and - result.getEnclosingFunction() = t.getAMemberFunction() + name = dependentTypeMemberVariable.getName() ) } From 3f564a3811c62cac2317ccd0e4a0137305f19b0a Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 22:34:24 +0000 Subject: [PATCH 08/14] M14-6-1: Rename predicates for clarity --- cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll | 6 +++--- .../M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql | 9 +++------ .../NameNotReferredUsingAQualifiedIdOrThisAudit.ql | 9 +++------ 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 8722dab604..b4fdf0bbf8 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -37,7 +37,7 @@ private FunctionCall helper_functioncall( * Gets a function call in `TemplateClass` `t` where the target function name exists in a dependent * base type and the call is to a function that is not declared in the dependent base type. */ -FunctionCall parentMemberFunctionCall(TemplateClass t) { +FunctionCall getConfusingFunctionCall(TemplateClass t) { exists( string name, TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target @@ -70,7 +70,7 @@ private FunctionAccess helper_functionaccess( * Gets a function access in `TemplateClass` `t` where the target function name exists in a dependent * base type and the access is to a function declared outside the dependent base type. */ -FunctionAccess parentMemberFunctionAccess(TemplateClass t) { +FunctionAccess getConfusingFunctionAccess(TemplateClass t) { exists( string name, TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, Function target @@ -101,7 +101,7 @@ private VariableAccess helper_memberaccess( * Gets a memmber access in `TemplateClass` `t` where the target member name exists in a dependent * base type and the access is to a variable declared outside the dependent base type. */ -VariableAccess parentMemberAccess(TemplateClass t) { +VariableAccess getConfusingMemberVariableAccess(TemplateClass t) { exists( string name, TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, Variable target diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql index ada692a626..a46023e4e9 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql @@ -24,16 +24,13 @@ where not isCustomExcluded(fn) and missingNameQualifier(fn) and ( - fn instanceof FunctionAccess and - fn = parentMemberFunctionAccess(c) + fn = getConfusingFunctionAccess(c) or - fn instanceof FunctionCall and - fn = parentMemberFunctionCall(c) and + fn = getConfusingFunctionCall(c) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or - fn instanceof VariableAccess and not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = parentMemberAccess(c) and + fn = getConfusingMemberVariableAccess(c) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) and not fn.isAffectedByMacro() diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql index 6bc958d4a6..648a3e6a3c 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql @@ -24,16 +24,13 @@ where not isCustomExcluded(fn) and missingNameQualifier(fn) and ( - fn instanceof FunctionAccess and - fn = parentMemberFunctionAccess(c) + fn = getConfusingFunctionAccess(c) or - fn instanceof FunctionCall and - fn = parentMemberFunctionCall(c) and + fn = getConfusingFunctionCall(c) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or - fn instanceof VariableAccess and not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = parentMemberAccess(c) and + fn = getConfusingMemberVariableAccess(c) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) select fn, "Use of identifier that also exists in a base class that is not fully qualified." From c308956de8e4c1a843ad8f53b53b2c10c92bda64 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 22:52:56 +0000 Subject: [PATCH 09/14] M14-6-1: Add improved alert message Improve the alert message to include: - The name of the identifier - A link to the target of the use of the identifier - A link to the dependent base type member with the same name. --- .../src/rules/M14-6-1/NameInDependentBase.qll | 27 +++++++++---------- .../NameNotReferredUsingAQualifiedIdOrThis.ql | 16 +++++++---- ...NotReferredUsingAQualifiedIdOrThisAudit.ql | 16 +++++++---- ...otReferredUsingAQualifiedIdOrThis.expected | 6 ++--- ...erredUsingAQualifiedIdOrThisAudit.expected | 6 ++--- 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index b4fdf0bbf8..3673348ba2 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -37,11 +37,10 @@ private FunctionCall helper_functioncall( * Gets a function call in `TemplateClass` `t` where the target function name exists in a dependent * base type and the call is to a function that is not declared in the dependent base type. */ -FunctionCall getConfusingFunctionCall(TemplateClass t) { - exists( - string name, TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, - Function target - | +FunctionCall getConfusingFunctionCall( + TemplateClass t, string name, Function target, MemberFunction dependentTypeFunction +) { + exists(TemplateClass dependentBaseType | result = helper_functioncall(t, dependentBaseType, target, name) and // The dependentTypeFunction is declared on the dependent base type dependentBaseType.getAMember() = dependentTypeFunction and @@ -70,11 +69,10 @@ private FunctionAccess helper_functionaccess( * Gets a function access in `TemplateClass` `t` where the target function name exists in a dependent * base type and the access is to a function declared outside the dependent base type. */ -FunctionAccess getConfusingFunctionAccess(TemplateClass t) { - exists( - string name, TemplateClass dependentBaseType, MemberFunction dependentTypeFunction, - Function target - | +FunctionAccess getConfusingFunctionAccess( + TemplateClass t, string name, Function target, MemberFunction dependentTypeFunction +) { + exists(TemplateClass dependentBaseType | result = helper_functionaccess(t, dependentBaseType, target, name) and dependentBaseType.getAMember() = dependentTypeFunction and name = dependentTypeFunction.getName() @@ -101,11 +99,10 @@ private VariableAccess helper_memberaccess( * Gets a memmber access in `TemplateClass` `t` where the target member name exists in a dependent * base type and the access is to a variable declared outside the dependent base type. */ -VariableAccess getConfusingMemberVariableAccess(TemplateClass t) { - exists( - string name, TemplateClass dependentBaseType, MemberVariable dependentTypeMemberVariable, - Variable target - | +VariableAccess getConfusingMemberVariableAccess( + TemplateClass t, string name, Variable target, MemberVariable dependentTypeMemberVariable +) { + exists(TemplateClass dependentBaseType | result = helper_memberaccess(t, dependentBaseType, target, name) and dependentBaseType.getAMemberVariable() = dependentTypeMemberVariable and name = dependentTypeMemberVariable.getName() diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql index a46023e4e9..646535b977 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql @@ -18,20 +18,26 @@ import cpp import codingstandards.cpp.autosar import NameInDependentBase -from TemplateClass c, NameQualifiableElement fn +from + TemplateClass c, NameQualifiableElement fn, string targetName, Element actualTarget, + Element dependentTypeMemberWithSameName where not isExcluded(fn, TemplatesPackage::nameNotReferredUsingAQualifiedIdOrThisQuery()) and not isCustomExcluded(fn) and missingNameQualifier(fn) and ( - fn = getConfusingFunctionAccess(c) + fn = getConfusingFunctionAccess(c, targetName, actualTarget, dependentTypeMemberWithSameName) or - fn = getConfusingFunctionCall(c) and + fn = getConfusingFunctionCall(c, targetName, actualTarget, dependentTypeMemberWithSameName) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = getConfusingMemberVariableAccess(c) and + fn = + getConfusingMemberVariableAccess(c, targetName, actualTarget, dependentTypeMemberWithSameName) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) and not fn.isAffectedByMacro() -select fn, "Use of identifier that also exists in a base class that is not fully qualified." +select fn, + "Use of unqualified identifier " + targetName + + " targets $@ but a member with the name also exists $@.", actualTarget, targetName, + dependentTypeMemberWithSameName, "in the dependent base class" diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql index 648a3e6a3c..401edf3b61 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.ql @@ -18,19 +18,25 @@ import cpp import codingstandards.cpp.autosar import NameInDependentBase -from TemplateClass c, NameQualifiableElement fn +from + TemplateClass c, NameQualifiableElement fn, string targetName, Element actualTarget, + Element dependentTypeMemberWithSameName where not isExcluded(fn, TemplatesPackage::nameNotReferredUsingAQualifiedIdOrThisAuditQuery()) and not isCustomExcluded(fn) and missingNameQualifier(fn) and ( - fn = getConfusingFunctionAccess(c) + fn = getConfusingFunctionAccess(c, targetName, actualTarget, dependentTypeMemberWithSameName) or - fn = getConfusingFunctionCall(c) and + fn = getConfusingFunctionCall(c, targetName, actualTarget, dependentTypeMemberWithSameName) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or not fn.(VariableAccess).getTarget() instanceof Parameter and - fn = getConfusingMemberVariableAccess(c) and + fn = + getConfusingMemberVariableAccess(c, targetName, actualTarget, dependentTypeMemberWithSameName) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) ) -select fn, "Use of identifier that also exists in a base class that is not fully qualified." +select fn, + "Use of unqualified identifier " + targetName + + " targets $@ but a member with the name also exists $@.", actualTarget, targetName, + dependentTypeMemberWithSameName, "in the dependent base class" diff --git a/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.expected b/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.expected index c117f6d9ed..1ea2cb3ab5 100644 --- a/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.expected +++ b/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.expected @@ -1,3 +1,3 @@ -| test.cpp:16:5:16:5 | m | Use of identifier that also exists in a base class that is not fully qualified. | -| test.cpp:17:5:17:5 | call to g | Use of identifier that also exists in a base class that is not fully qualified. | -| test.cpp:19:20:19:20 | g | Use of identifier that also exists in a base class that is not fully qualified. | +| test.cpp:16:5:16:5 | m | Use of unqualified identifier m targets $@ but a member with the name also exists $@. | test.cpp:4:5:4:5 | m | m | test.cpp:10:7:10:7 | m | in the dependent base class | +| test.cpp:17:5:17:5 | call to g | Use of unqualified identifier g targets $@ but a member with the name also exists $@. | test.cpp:2:6:2:6 | g | g | test.cpp:9:8:9:8 | g | in the dependent base class | +| test.cpp:19:20:19:20 | g | Use of unqualified identifier g targets $@ but a member with the name also exists $@. | test.cpp:2:6:2:6 | g | g | test.cpp:9:8:9:8 | g | in the dependent base class | diff --git a/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.expected b/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.expected index c117f6d9ed..1ea2cb3ab5 100644 --- a/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.expected +++ b/cpp/autosar/test/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThisAudit.expected @@ -1,3 +1,3 @@ -| test.cpp:16:5:16:5 | m | Use of identifier that also exists in a base class that is not fully qualified. | -| test.cpp:17:5:17:5 | call to g | Use of identifier that also exists in a base class that is not fully qualified. | -| test.cpp:19:20:19:20 | g | Use of identifier that also exists in a base class that is not fully qualified. | +| test.cpp:16:5:16:5 | m | Use of unqualified identifier m targets $@ but a member with the name also exists $@. | test.cpp:4:5:4:5 | m | m | test.cpp:10:7:10:7 | m | in the dependent base class | +| test.cpp:17:5:17:5 | call to g | Use of unqualified identifier g targets $@ but a member with the name also exists $@. | test.cpp:2:6:2:6 | g | g | test.cpp:9:8:9:8 | g | in the dependent base class | +| test.cpp:19:20:19:20 | g | Use of unqualified identifier g targets $@ but a member with the name also exists $@. | test.cpp:2:6:2:6 | g | g | test.cpp:9:8:9:8 | g | in the dependent base class | From f6afab6f3146948979186165ce5e99a9dfb19fb3 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Sun, 26 Feb 2023 23:20:36 +0000 Subject: [PATCH 10/14] M14-6-1: Ensure local scope variables are ignored Access of a local scope variable shadowing a dependent base member is not a case with confusing behaviour - the local scope variable would be expected to be the target. --- cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll | 4 +++- .../M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql | 1 - cpp/autosar/test/rules/M14-6-1/test.cpp | 9 +++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 3673348ba2..33b5c4b651 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -92,7 +92,9 @@ private VariableAccess helper_memberaccess( not target.getDeclaringType() = dependentBaseType and result = target.getAnAccess() and result.getEnclosingFunction() = t.getAMemberFunction() and - name = target.getName() + name = target.getName() and + // The target is not a local variable, which isn't subject to confusion + not target instanceof LocalScopeVariable } /** diff --git a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql index 646535b977..2736d39290 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql +++ b/cpp/autosar/src/rules/M14-6-1/NameNotReferredUsingAQualifiedIdOrThis.ql @@ -31,7 +31,6 @@ where fn = getConfusingFunctionCall(c, targetName, actualTarget, dependentTypeMemberWithSameName) and not exists(Expr e | e = fn.(FunctionCall).getQualifier()) or - not fn.(VariableAccess).getTarget() instanceof Parameter and fn = getConfusingMemberVariableAccess(c, targetName, actualTarget, dependentTypeMemberWithSameName) and not exists(Expr e | e = fn.(VariableAccess).getQualifier()) diff --git a/cpp/autosar/test/rules/M14-6-1/test.cpp b/cpp/autosar/test/rules/M14-6-1/test.cpp index d7e7313162..1813251098 100644 --- a/cpp/autosar/test/rules/M14-6-1/test.cpp +++ b/cpp/autosar/test/rules/M14-6-1/test.cpp @@ -29,12 +29,21 @@ template class A : B { typename B::TYPE t2 = 0; // COMPLIANT g1(); // COMPLIANT, identifier not found in B } + void m3(int m) { + m = 0; // COMPLIANT, hides member + } + void m4() { + int m = 0; + m = 0; // COMPLIANT, hides member + } }; void f() { A a; a.m1(); a.m2(); + a.m3(1); + a.m4(); } class D { From 6c5827cac4dab56ac1611ffde19abc6c516f8621 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 1 Mar 2023 11:09:50 +0000 Subject: [PATCH 11/14] M14-6-1: Address test irregularities * Formatting * Address compiler testing issues - Accidental name conflicts - Type of member function parameter --- cpp/autosar/test/rules/M14-6-1/test.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cpp/autosar/test/rules/M14-6-1/test.cpp b/cpp/autosar/test/rules/M14-6-1/test.cpp index 1813251098..d5d99597f4 100644 --- a/cpp/autosar/test/rules/M14-6-1/test.cpp +++ b/cpp/autosar/test/rules/M14-6-1/test.cpp @@ -30,11 +30,11 @@ template class A : B { g1(); // COMPLIANT, identifier not found in B } void m3(int m) { - m = 0; // COMPLIANT, hides member + m = 0; // COMPLIANT, hides member } void m4() { int m = 0; - m = 0; // COMPLIANT, hides member + m = 0; // COMPLIANT, hides member } }; @@ -59,20 +59,21 @@ class D { class C : D { public: void m1() { - m = 0; // COMPLIANT - does not apply to non-class templates - g(); // COMPLIANT - does not apply to non-class templates + m = 0; // COMPLIANT - does not apply to non-class templates + g(); // COMPLIANT - does not apply to non-class templates sg(); // COMPLIANT - does not apply to non-class templates - TYPE t = 0; // COMPLIANT - does not apply to non-class templates + TYPE t1 = 0; // COMPLIANT - does not apply to non-class templates // void (*p)() = &g; // NON_COMPILABLE } }; -template class E : D { +template class E : D { public: void m1() { - m = 0; // COMPLIANT - does not apply to non dependent base types - g(); // COMPLIANT - does not apply to non dependent base types - TYPE t = 0; // COMPLIANT - does not apply to non dependent base types - void (*p)() = &g; // COMPLIANT - does not apply to non dependent base types + m = 0; // COMPLIANT - does not apply to non dependent base types + g(); // COMPLIANT - does not apply to non dependent base types + TYPE t1 = 0; // COMPLIANT - does not apply to non dependent base types + void (D::*p)() = + &g; // COMPLIANT - does not apply to non dependent base types } }; \ No newline at end of file From a80c8b0a82d634cc5fe80bfa4289722ef0b1dedd Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Wed, 1 Mar 2023 11:25:24 +0000 Subject: [PATCH 12/14] M14-6-1: Remove incompatible clang case --- cpp/autosar/test/rules/M14-6-1/test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/autosar/test/rules/M14-6-1/test.cpp b/cpp/autosar/test/rules/M14-6-1/test.cpp index d5d99597f4..be3c7c0b5f 100644 --- a/cpp/autosar/test/rules/M14-6-1/test.cpp +++ b/cpp/autosar/test/rules/M14-6-1/test.cpp @@ -73,7 +73,6 @@ template class E : D { m = 0; // COMPLIANT - does not apply to non dependent base types g(); // COMPLIANT - does not apply to non dependent base types TYPE t1 = 0; // COMPLIANT - does not apply to non dependent base types - void (D::*p)() = - &g; // COMPLIANT - does not apply to non dependent base types + // void (*p)() = &g; // NON_COMPILABLE - clang does not accept this } }; \ No newline at end of file From cc0372e65b7f929b2b36d1fdcb6a9ea1e7e06da6 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 2 Mar 2023 10:00:12 +0000 Subject: [PATCH 13/14] M14-6-1: Identify non-compilable cases To take a pointer to a member function we need to provide a qualifier to the name. The cases in the COMPLIANT classes are therefore non-compilable. The reason some cases were not previously causing EDG to crash was that the templates weren't instantiated. We now instantiate all templates, and add explanatory comments. --- cpp/autosar/test/rules/M14-6-1/test.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/cpp/autosar/test/rules/M14-6-1/test.cpp b/cpp/autosar/test/rules/M14-6-1/test.cpp index be3c7c0b5f..b16e6b40dc 100644 --- a/cpp/autosar/test/rules/M14-6-1/test.cpp +++ b/cpp/autosar/test/rules/M14-6-1/test.cpp @@ -63,7 +63,8 @@ class C : D { g(); // COMPLIANT - does not apply to non-class templates sg(); // COMPLIANT - does not apply to non-class templates TYPE t1 = 0; // COMPLIANT - does not apply to non-class templates - // void (*p)() = &g; // NON_COMPILABLE + // void (*p)() = &g; // NON_COMPILABLE - not valid to take address of member + // function without qualifier } }; @@ -73,6 +74,14 @@ template class E : D { m = 0; // COMPLIANT - does not apply to non dependent base types g(); // COMPLIANT - does not apply to non dependent base types TYPE t1 = 0; // COMPLIANT - does not apply to non dependent base types - // void (*p)() = &g; // NON_COMPILABLE - clang does not accept this + // void (*p)() = &g; // NON_COMPILABLE - not valid to take address of member + // function without qualifier } -}; \ No newline at end of file +}; + +void f2() { + C c; + c.m1(); + E e; + e.m1(); +} \ No newline at end of file From dd4a1eaa87f3af547eafbd5b9c26a7a9b22f3427 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 2 Mar 2023 10:04:32 +0000 Subject: [PATCH 14/14] M14-6-1: nomagic implies noinline --- cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll index 33b5c4b651..b3d12c044b 100644 --- a/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll +++ b/cpp/autosar/src/rules/M14-6-1/NameInDependentBase.qll @@ -21,7 +21,7 @@ TemplateClass getADependentBaseType(TemplateClass t) { * Helper predicate that ensures we do not join on function pairs by name early on, as that creates * a large dataset on big databases with lots of name duplication. */ -pragma[noinline, nomagic] +pragma[nomagic] private FunctionCall helper_functioncall( TemplateClass t, TemplateClass dependentBaseType, Function target, string name ) { @@ -53,7 +53,7 @@ FunctionCall getConfusingFunctionCall( * Helper predicate that ensures we do not join on function pairs by name early on, as that creates * a large dataset on big databases with lots of name duplication. */ -pragma[noinline, nomagic] +pragma[nomagic] private FunctionAccess helper_functionaccess( TemplateClass t, TemplateClass dependentBaseType, Function target, string name ) { @@ -83,7 +83,7 @@ FunctionAccess getConfusingFunctionAccess( * Helper predicate that ensures we do not join on variable pairs by name early on, as that creates * a large dataset on big databases with lots of name duplication. */ -pragma[noinline, nomagic] +pragma[nomagic] private VariableAccess helper_memberaccess( TemplateClass t, TemplateClass dependentBaseType, Variable target, string name ) {