From 9367bd6264bc96f4144b10d867fbfe8e2fffec9e Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 18 Oct 2022 14:14:33 -0400 Subject: [PATCH 01/13] Declarations4: add RULE-8-6 and refactor RULE-5-7 for lib mv --- .../src/rules/RULE-5-7/TagNameNotUnique.ql | 2 +- ...ntifierWithExternalLinkageOneDefinition.ql | 38 +++++++++++++++++++ ...rWithExternalLinkageOneDefinition.expected | 2 + ...fierWithExternalLinkageOneDefinition.qlref | 1 + c/misra/test/rules/RULE-8-6/test.c | 6 +++ c/misra/test/rules/RULE-8-6/test1.c | 6 +++ .../src/codingstandards/cpp}/Identifiers.qll | 15 ++++++++ .../cpp/exclusions/c/Declarations4.qll | 25 ++++++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 ++ .../NotDistinctIdentifier.qll | 25 ++---------- rule_packages/c/Declarations4.json | 23 +++++++++++ rules.csv | 2 +- 12 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql create mode 100644 c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected create mode 100644 c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref create mode 100644 c/misra/test/rules/RULE-8-6/test.c create mode 100644 c/misra/test/rules/RULE-8-6/test1.c rename {c/common/src/codingstandards/c => cpp/common/src/codingstandards/cpp}/Identifiers.qll (57%) create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll create mode 100644 rule_packages/c/Declarations4.json diff --git a/c/misra/src/rules/RULE-5-7/TagNameNotUnique.ql b/c/misra/src/rules/RULE-5-7/TagNameNotUnique.ql index f7c005d7fa..672e302c92 100644 --- a/c/misra/src/rules/RULE-5-7/TagNameNotUnique.ql +++ b/c/misra/src/rules/RULE-5-7/TagNameNotUnique.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.c.Identifiers +import codingstandards.cpp.Identifiers from Struct s, InterestingIdentifiers s2 where diff --git a/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql b/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql new file mode 100644 index 0000000000..7cc3846687 --- /dev/null +++ b/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql @@ -0,0 +1,38 @@ +/** + * @id c/misra/identifier-with-external-linkage-one-definition + * @name RULE-8-6: An identifier with external linkage shall have exactly one external definition + * @description An identifier with multiple definitions in different translation units leads to + * undefined behavior. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-8-6 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Identifiers + +from ExternalIdentifiers d, DeclarationEntry de1, DeclarationEntry de2 +where + not isExcluded(d, Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery()) and + not isExcluded([de1, de2], Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery()) and + d.isTopLevel() and + d = de1.getDeclaration() and + d = de2.getDeclaration() and + de1 != de2 and + de1.isDefinition() and + de2.isDefinition() and + //exceptions + (d instanceof Function implies not d.(Function).isInline()) and + // Apply an ordering based on location to enforce that (de1, de2) = (de2, de1) and we only report (de1, de2). + ( + de1.getFile().getAbsolutePath() < de2.getFile().getAbsolutePath() + or + de1.getFile().getAbsolutePath() = de2.getFile().getAbsolutePath() and + de1.getLocation().getStartLine() < de2.getLocation().getStartLine() + ) +select de1, "The identifier " + de1.getName() + " has external linkage and is redefined $@.", de2, + "here" diff --git a/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected new file mode 100644 index 0000000000..8ea6eca50e --- /dev/null +++ b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected @@ -0,0 +1,2 @@ +| test.c:1:5:1:6 | definition of g1 | The identifier g1 has external linkage and is redefined $@. | test1.c:1:5:1:6 | definition of g1 | here | +| test.c:6:6:6:7 | definition of f2 | The identifier f2 has external linkage and is redefined $@. | test1.c:6:6:6:7 | definition of f2 | here | diff --git a/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref new file mode 100644 index 0000000000..aa86a9534d --- /dev/null +++ b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref @@ -0,0 +1 @@ +rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-6/test.c b/c/misra/test/rules/RULE-8-6/test.c new file mode 100644 index 0000000000..a2e9eeff8d --- /dev/null +++ b/c/misra/test/rules/RULE-8-6/test.c @@ -0,0 +1,6 @@ +int g1 = 1; // NON_COMPLIANT +static int g2 = 1; // COMPLIANT; internal linkage + +inline void f1() {} // COMPLIANT; inline functions are an exception + +void f2() {} // NON_COMPLIANT \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-6/test1.c b/c/misra/test/rules/RULE-8-6/test1.c new file mode 100644 index 0000000000..6882a55800 --- /dev/null +++ b/c/misra/test/rules/RULE-8-6/test1.c @@ -0,0 +1,6 @@ +int g1 = 0; // NON_COMPLIANT +static int g2 = 1; // COMPLIANT; internal linkage + +inline void f1() {} // COMPLIANT; inline functions are an exception + +void f2() {} // NON_COMPLIANT \ No newline at end of file diff --git a/c/common/src/codingstandards/c/Identifiers.qll b/cpp/common/src/codingstandards/cpp/Identifiers.qll similarity index 57% rename from c/common/src/codingstandards/c/Identifiers.qll rename to cpp/common/src/codingstandards/cpp/Identifiers.qll index 580cd8cfdd..d7ba4eee27 100644 --- a/c/common/src/codingstandards/c/Identifiers.qll +++ b/cpp/common/src/codingstandards/cpp/Identifiers.qll @@ -1,4 +1,19 @@ import cpp +import codingstandards.cpp.Linkage + +class ExternalIdentifiers extends InterestingIdentifiers { + ExternalIdentifiers() { + hasExternalLinkage(this) and + getNamespace() instanceof GlobalNamespace + } + + string getSignificantName() { + //C99 states the first 31 characters of external identifiers are significant + //C90 states the first 6 characters of external identifiers are significant and case is not required to be significant + //C90 is not currently considered by this rule + result = this.getName().prefix(31) + } +} //Identifiers that are candidates for checking uniqueness class InterestingIdentifiers extends Declaration { diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll new file mode 100644 index 0000000000..d4a6b443ef --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll @@ -0,0 +1,25 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Declarations4Query = TIdentifierWithExternalLinkageOneDefinitionQuery() + +predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleId) { + query = + // `Query` instance for the `identifierWithExternalLinkageOneDefinition` query + Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery() and + queryId = + // `@id` for the `identifierWithExternalLinkageOneDefinition` query + "c/misra/identifier-with-external-linkage-one-definition" and + ruleId = "RULE-8-6" +} + +module Declarations4Package { + Query identifierWithExternalLinkageOneDefinitionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `identifierWithExternalLinkageOneDefinition` query + TQueryC(TDeclarations4PackageQuery(TIdentifierWithExternalLinkageOneDefinitionQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 638e68492e..5c1f45f1ee 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -12,6 +12,7 @@ import Contracts3 import Declarations1 import Declarations2 import Declarations3 +import Declarations4 import Expressions import IO1 import IO2 @@ -44,6 +45,7 @@ newtype TCQuery = TDeclarations1PackageQuery(Declarations1Query q) or TDeclarations2PackageQuery(Declarations2Query q) or TDeclarations3PackageQuery(Declarations3Query q) or + TDeclarations4PackageQuery(Declarations4Query q) or TExpressionsPackageQuery(ExpressionsQuery q) or TIO1PackageQuery(IO1Query q) or TIO2PackageQuery(IO2Query q) or @@ -76,6 +78,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId) { isDeclarations1QueryMetadata(query, queryId, ruleId) or isDeclarations2QueryMetadata(query, queryId, ruleId) or isDeclarations3QueryMetadata(query, queryId, ruleId) or + isDeclarations4QueryMetadata(query, queryId, ruleId) or isExpressionsQueryMetadata(query, queryId, ruleId) or isIO1QueryMetadata(query, queryId, ruleId) or isIO2QueryMetadata(query, queryId, ruleId) or diff --git a/cpp/common/src/codingstandards/cpp/rules/notdistinctidentifier/NotDistinctIdentifier.qll b/cpp/common/src/codingstandards/cpp/rules/notdistinctidentifier/NotDistinctIdentifier.qll index 8e58cbac07..aa2110c5aa 100644 --- a/cpp/common/src/codingstandards/cpp/rules/notdistinctidentifier/NotDistinctIdentifier.qll +++ b/cpp/common/src/codingstandards/cpp/rules/notdistinctidentifier/NotDistinctIdentifier.qll @@ -5,28 +5,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.Linkage - -class ExternalIdentifiers extends Declaration { - ExternalIdentifiers() { - this.getName().length() >= 31 and - hasExternalLinkage(this) and - getNamespace() instanceof GlobalNamespace and - not this.isFromTemplateInstantiation(_) and - not this.isFromUninstantiatedTemplate(_) and - not this.hasDeclaringType() and - not this instanceof UserType and - not this instanceof Operator and - not this.hasName("main") - } - - string getSignificantName() { - //C99 states the first 31 characters of external identifiers are significant - //C90 states the first 6 characters of external identifiers are significant and case is not required to be significant - //C90 is not currently considered by this rule - result = this.getName().prefix(31) - } -} +import codingstandards.cpp.Identifiers abstract class NotDistinctIdentifierSharedQuery extends Query { } @@ -35,6 +14,8 @@ Query getQuery() { result instanceof NotDistinctIdentifierSharedQuery } query predicate problems(ExternalIdentifiers d, ExternalIdentifiers d2, string message) { not isExcluded(d, getQuery()) and not isExcluded(d, getQuery()) and + d.getName().length() >= 31 and + d2.getName().length() >= 31 and not d = d2 and d.getLocation().getStartLine() >= d2.getLocation().getStartLine() and d.getSignificantName() = d2.getSignificantName() and diff --git a/rule_packages/c/Declarations4.json b/rule_packages/c/Declarations4.json new file mode 100644 index 0000000000..56f79c08e7 --- /dev/null +++ b/rule_packages/c/Declarations4.json @@ -0,0 +1,23 @@ +{ + "MISRA-C-2012": { + "RULE-8-6": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "An identifier with multiple definitions in different translation units leads to undefined behavior.", + "kind": "problem", + "name": "An identifier with external linkage shall have exactly one external definition", + "precision": "high", + "severity": "error", + "short_name": "IdentifierWithExternalLinkageOneDefinition", + "tags": [ + "correctness" + ] + } + ], + "title": "An identifier with external linkage shall have exactly one external definition" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index cb14aec2c0..677b2678fa 100755 --- a/rules.csv +++ b/rules.csv @@ -651,7 +651,7 @@ c,MISRA-C-2012,RULE-8-2,Yes,Required,,,Function types shall be in prototype form c,MISRA-C-2012,RULE-8-3,Yes,Required,,,All declarations of an object or function shall use the same names and type qualifiers,M3-2-1,Declarations,Medium, c,MISRA-C-2012,RULE-8-4,Yes,Required,,,A compatible declaration shall be visible when an object or function with external linkage is defined,,Declarations,Medium, c,MISRA-C-2012,RULE-8-5,Yes,Required,,,An external object or function shall be declared once in one and only one file,,Declarations,Medium, -c,MISRA-C-2012,RULE-8-6,Yes,Required,,,An identifier with external linkage shall have exactly one external definition,M3-2-4,Declarations,Import, +c,MISRA-C-2012,RULE-8-6,Yes,Required,,,An identifier with external linkage shall have exactly one external definition,M3-2-4,Declarations4,Import, c,MISRA-C-2012,RULE-8-7,Yes,Advisory,,,Functions and objects should not be defined with external linkage if they are referenced in only one translation unit,,Declarations,Medium, c,MISRA-C-2012,RULE-8-8,Yes,Required,,,The static storage class specifier shall be used in all declarations of objects and functions that have internal linkage,M3-3-2,Declarations,Medium, c,MISRA-C-2012,RULE-8-9,Yes,Advisory,,,An object should be defined at block scope if its identifier only appears in a single function,M3-4-1,Declarations,Medium, From cde7f029049becf5eab22c5395f52318c02811b0 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 18 Oct 2022 15:56:45 -0400 Subject: [PATCH 02/13] Declarations4: fix RULE-5-5 for refactored lib loc --- .../src/rules/RULE-5-5/IdentifiersNotDistinctFromMacroNames.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-5-5/IdentifiersNotDistinctFromMacroNames.ql b/c/misra/src/rules/RULE-5-5/IdentifiersNotDistinctFromMacroNames.ql index 2ee6ef26d2..a63d9656b8 100644 --- a/c/misra/src/rules/RULE-5-5/IdentifiersNotDistinctFromMacroNames.ql +++ b/c/misra/src/rules/RULE-5-5/IdentifiersNotDistinctFromMacroNames.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.c.Identifiers +import codingstandards.cpp.Identifiers from Macro m, InterestingIdentifiers i, string mName, string iName where From 30811eba4f0f395ca6cb6fd54c487fc8160e51f3 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Thu, 20 Oct 2022 12:56:09 -0400 Subject: [PATCH 03/13] Declarations4: fix RULE-5-6 for refactored lib loc --- c/misra/src/rules/RULE-5-6/TypedefNameNotUnique.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-5-6/TypedefNameNotUnique.ql b/c/misra/src/rules/RULE-5-6/TypedefNameNotUnique.ql index eebdabe956..2e9126d3af 100644 --- a/c/misra/src/rules/RULE-5-6/TypedefNameNotUnique.ql +++ b/c/misra/src/rules/RULE-5-6/TypedefNameNotUnique.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.c.Identifiers +import codingstandards.cpp.Identifiers from TypedefType t, InterestingIdentifiers d where From be0eca902024e567364318804c8e67c898f25771 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 24 Oct 2022 16:04:40 -0400 Subject: [PATCH 04/13] Declarations4: add RULE-8-2 --- .../FunctionTypesNotInPrototypeForm.ql | 46 +++++++++++++++++++ .../FunctionTypesNotInPrototypeForm.expected | 5 ++ .../FunctionTypesNotInPrototypeForm.qlref | 1 + c/misra/test/rules/RULE-8-2/test.c | 9 ++++ .../cpp/exclusions/c/Declarations4.qll | 19 +++++++- rule_packages/c/Declarations4.json | 23 ++++++++++ rules.csv | 2 +- 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql create mode 100644 c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected create mode 100644 c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.qlref create mode 100644 c/misra/test/rules/RULE-8-2/test.c diff --git a/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql new file mode 100644 index 0000000000..5a89df23d4 --- /dev/null +++ b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql @@ -0,0 +1,46 @@ +/** + * @id c/misra/function-types-not-in-prototype-form + * @name RULE-8-2: Function types shall be in prototype form with named parameters + * @description Omission of parameter types or names prevents the compiler from doing type checking + * when those functions are used and therefore may result in undefined behaviour. + * @kind problem + * @precision medium + * @problem.severity error + * @tags external/misra/id/rule-8-2 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Identifiers + +/** + * `Parameter`s without names + */ +class UnnamedParameter extends Parameter { + UnnamedParameter() { not this.isNamed() } +} + +from Function f, string msg +where + not isExcluded(f, Declarations4Package::functionTypesNotInPrototypeFormQuery()) and + f instanceof InterestingIdentifiers and + ( + f.getAParameter() instanceof UnnamedParameter and + msg = "Function " + f + " declares parameter that is unnamed." + or + //void keyword not present in function signature, no way to tell which + not exists(f.getAParameter()) and + msg = + "Function " + f + + " may not specify all parameter types or may not specifiy void for no parameters present." + or + exists(Parameter p | + p.getFunction() = f and + not p.getFile() = f.getFile() and + msg = "Function " + f + " declares parameter in unsupported declaration list." + ) + ) and + not f.isInMacroExpansion() +select f, msg diff --git a/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected new file mode 100644 index 0000000000..e33bdcfd28 --- /dev/null +++ b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected @@ -0,0 +1,5 @@ +| test.c:2:6:2:7 | f0 | Function f0 may not specify all parameter types or may not specifiy void for no parameters present. | +| test.c:3:6:3:7 | f1 | Function f1 declares parameter that is unnamed. | +| test.c:4:6:4:7 | f2 | Function f2 may not specify all parameter types or may not specifiy void for no parameters present. | +| test.c:5:6:5:7 | f3 | Function f3 may not specify all parameter types or may not specifiy void for no parameters present. | +| test.c:7:5:7:6 | f5 | Function f5 declares parameter in unsupported declaration list. | diff --git a/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.qlref b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.qlref new file mode 100644 index 0000000000..0a6121b324 --- /dev/null +++ b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.qlref @@ -0,0 +1 @@ +rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-2/test.c b/c/misra/test/rules/RULE-8-2/test.c new file mode 100644 index 0000000000..4f1b3509c6 --- /dev/null +++ b/c/misra/test/rules/RULE-8-2/test.c @@ -0,0 +1,9 @@ +void f(int x); // COMPLIANT +void f0(void); // COMPLIANT[FALSE_POSITIVE] +void f1(int); // NON_COMPLIANT +void f2(); // NON_COMPLIANT +void f3(x); // NON_COMPLIANT +void f4(const x); // NON_COMPLIANT[FALSE_NEGATIVE] +int f5(x) // NON_COMPLIANT +int x; +{ return 1; } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll index d4a6b443ef..29cae700f3 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll @@ -3,9 +3,19 @@ import cpp import RuleMetadata import codingstandards.cpp.exclusions.RuleMetadata -newtype Declarations4Query = TIdentifierWithExternalLinkageOneDefinitionQuery() +newtype Declarations4Query = + TFunctionTypesNotInPrototypeFormQuery() or + TIdentifierWithExternalLinkageOneDefinitionQuery() predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleId) { + query = + // `Query` instance for the `functionTypesNotInPrototypeForm` query + Declarations4Package::functionTypesNotInPrototypeFormQuery() and + queryId = + // `@id` for the `functionTypesNotInPrototypeForm` query + "c/misra/function-types-not-in-prototype-form" and + ruleId = "RULE-8-2" + or query = // `Query` instance for the `identifierWithExternalLinkageOneDefinition` query Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery() and @@ -16,6 +26,13 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI } module Declarations4Package { + Query functionTypesNotInPrototypeFormQuery() { + //autogenerate `Query` type + result = + // `Query` type for `functionTypesNotInPrototypeForm` query + TQueryC(TDeclarations4PackageQuery(TFunctionTypesNotInPrototypeFormQuery())) + } + Query identifierWithExternalLinkageOneDefinitionQuery() { //autogenerate `Query` type result = diff --git a/rule_packages/c/Declarations4.json b/rule_packages/c/Declarations4.json index 56f79c08e7..4efd48d25a 100644 --- a/rule_packages/c/Declarations4.json +++ b/rule_packages/c/Declarations4.json @@ -1,5 +1,28 @@ { "MISRA-C-2012": { + "RULE-8-2": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Omission of parameter types or names prevents the compiler from doing type checking when those functions are used and therefore may result in undefined behaviour.", + "kind": "problem", + "name": "Function types shall be in prototype form with named parameters", + "precision": "medium", + "severity": "error", + "short_name": "FunctionTypesNotInPrototypeForm", + "tags": [ + "correctness" + ], + "implementation_scope": { + "description": "This query does not check for implicitly typed parameters and checks function declarations and definitions but not function pointer types. This query cannot determine when the keyword void is used in place of no parameter.", + "items": [] + } + } + ], + "title": "Function types shall be in prototype form with named parameters" + }, "RULE-8-6": { "properties": { "obligation": "required" diff --git a/rules.csv b/rules.csv index 677b2678fa..ce93dd72e9 100755 --- a/rules.csv +++ b/rules.csv @@ -647,7 +647,7 @@ c,MISRA-C-2012,RULE-7-2,Yes,Required,,,A �u� or �U� suffix shall be appl c,MISRA-C-2012,RULE-7-3,Yes,Required,,,The lowercase character �l� shall not be used in a literal suffix,M2-13-4,Syntax,Easy, c,MISRA-C-2012,RULE-7-4,Yes,Required,,,A string literal shall not be assigned to an object unless the object�s type is �pointer to const-qualified char�,A2-13-4,Types,Easy, c,MISRA-C-2012,RULE-8-1,Yes,Required,,,Types shall be explicitly specified,,Declarations3,Medium, -c,MISRA-C-2012,RULE-8-2,Yes,Required,,,Function types shall be in prototype form with named parameters,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-2,Yes,Required,,,Function types shall be in prototype form with named parameters,,Declarations4,Medium, c,MISRA-C-2012,RULE-8-3,Yes,Required,,,All declarations of an object or function shall use the same names and type qualifiers,M3-2-1,Declarations,Medium, c,MISRA-C-2012,RULE-8-4,Yes,Required,,,A compatible declaration shall be visible when an object or function with external linkage is defined,,Declarations,Medium, c,MISRA-C-2012,RULE-8-5,Yes,Required,,,An external object or function shall be declared once in one and only one file,,Declarations,Medium, From 2f23fe2a150d782ed8a1bca76ab49fab87965da0 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 26 Oct 2022 11:08:36 -0400 Subject: [PATCH 05/13] Declarations4: improve RULE-8-2 --- .../FunctionTypesNotInPrototypeForm.ql | 21 ++++++++++++++----- .../FunctionTypesNotInPrototypeForm.expected | 5 ++--- c/misra/test/rules/RULE-8-2/test.c | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql index 5a89df23d4..2abeaa2f04 100644 --- a/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql +++ b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql @@ -22,6 +22,20 @@ class UnnamedParameter extends Parameter { UnnamedParameter() { not this.isNamed() } } +/* + * This is a copy of the private `hasZeroParamDecl` predicate from the standard set of + * queries as of the `codeql-cli/2.11.2` tag in `github/codeql`. + */ + +predicate hasZeroParamDecl(Function f) { + exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() | + not fde.isImplicit() and + not fde.hasVoidParamList() and + fde.getNumberOfParameters() = 0 and + not fde.isDefinition() + ) +} + from Function f, string msg where not isExcluded(f, Declarations4Package::functionTypesNotInPrototypeFormQuery()) and @@ -30,11 +44,8 @@ where f.getAParameter() instanceof UnnamedParameter and msg = "Function " + f + " declares parameter that is unnamed." or - //void keyword not present in function signature, no way to tell which - not exists(f.getAParameter()) and - msg = - "Function " + f + - " may not specify all parameter types or may not specifiy void for no parameters present." + hasZeroParamDecl(f) and + msg = "Function " + f + " does not specifiy void for no parameters present." or exists(Parameter p | p.getFunction() = f and diff --git a/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected index e33bdcfd28..f33a53174e 100644 --- a/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected +++ b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected @@ -1,5 +1,4 @@ -| test.c:2:6:2:7 | f0 | Function f0 may not specify all parameter types or may not specifiy void for no parameters present. | | test.c:3:6:3:7 | f1 | Function f1 declares parameter that is unnamed. | -| test.c:4:6:4:7 | f2 | Function f2 may not specify all parameter types or may not specifiy void for no parameters present. | -| test.c:5:6:5:7 | f3 | Function f3 may not specify all parameter types or may not specifiy void for no parameters present. | +| test.c:4:6:4:7 | f2 | Function f2 does not specifiy void for no parameters present. | +| test.c:5:6:5:7 | f3 | Function f3 does not specifiy void for no parameters present. | | test.c:7:5:7:6 | f5 | Function f5 declares parameter in unsupported declaration list. | diff --git a/c/misra/test/rules/RULE-8-2/test.c b/c/misra/test/rules/RULE-8-2/test.c index 4f1b3509c6..c254a221d9 100644 --- a/c/misra/test/rules/RULE-8-2/test.c +++ b/c/misra/test/rules/RULE-8-2/test.c @@ -1,5 +1,5 @@ void f(int x); // COMPLIANT -void f0(void); // COMPLIANT[FALSE_POSITIVE] +void f0(void); // COMPLIANT void f1(int); // NON_COMPLIANT void f2(); // NON_COMPLIANT void f3(x); // NON_COMPLIANT From 57d83bc507a97eb3d18ed0985be52fb4eee52329 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 9 Nov 2022 17:06:57 -0500 Subject: [PATCH 06/13] Declarations4: add RULE-8-3 --- .vscode/tasks.json | 2 + c/misra/src/rules/RULE-8-3/Compatible.qll | 30 ++++++++++++ .../DeclarationsOfAFunctionSameNameAndType.ql | 48 +++++++++++++++++++ .../DeclarationsOfAnObjectSameNameAndType.ql | 28 +++++++++++ ...rationsOfAFunctionSameNameAndType.expected | 12 +++++ ...clarationsOfAFunctionSameNameAndType.qlref | 1 + ...arationsOfAnObjectSameNameAndType.expected | 16 +++++++ ...eclarationsOfAnObjectSameNameAndType.qlref | 1 + c/misra/test/rules/RULE-8-3/function1.c | 27 +++++++++++ c/misra/test/rules/RULE-8-3/function2.c | 19 ++++++++ c/misra/test/rules/RULE-8-3/object1.c | 17 +++++++ c/misra/test/rules/RULE-8-3/object2.c | 26 ++++++++++ c/misra/test/rules/RULE-8-3/test.c | 0 .../cpp/exclusions/c/Declarations4.qll | 32 +++++++++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 ++ rule_packages/c/Declarations4.json | 30 ++++++++++++ rules.csv | 2 +- 17 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 c/misra/src/rules/RULE-8-3/Compatible.qll create mode 100644 c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql create mode 100644 c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql create mode 100644 c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected create mode 100644 c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.qlref create mode 100644 c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected create mode 100644 c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.qlref create mode 100644 c/misra/test/rules/RULE-8-3/function1.c create mode 100644 c/misra/test/rules/RULE-8-3/function2.c create mode 100644 c/misra/test/rules/RULE-8-3/object1.c create mode 100644 c/misra/test/rules/RULE-8-3/object2.c create mode 100644 c/misra/test/rules/RULE-8-3/test.c diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f027524374..4190ff1d79 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -205,6 +205,8 @@ "Declarations", "Declarations1", "Declarations2", + "Declarations3", + "Declarations4", "Exceptions1", "Exceptions2", "Expressions", diff --git a/c/misra/src/rules/RULE-8-3/Compatible.qll b/c/misra/src/rules/RULE-8-3/Compatible.qll new file mode 100644 index 0000000000..52e77692c5 --- /dev/null +++ b/c/misra/src/rules/RULE-8-3/Compatible.qll @@ -0,0 +1,30 @@ +import cpp + +/* + * This is a copy of the `arithTypesMatch` predicate from the standard set of + * queries as of the `codeql-cli/2.9.4` tag in `github/codeql`. + */ + +pragma[inline] +predicate arithTypesMatch(Type t1, Type t2) { + t1 = t2 + or + t1.getSize() = t2.getSize() and + ( + t1 instanceof IntegralOrEnumType and + t2 instanceof IntegralOrEnumType + or + t1 instanceof FloatingPointType and + t2 instanceof FloatingPointType + ) +} + +predicate typesCompatible(Type t1, Type t2) { + if t1 instanceof BuiltInType and t2 instanceof BuiltInType + then + //for simple types consider compatible + arithTypesMatch(t1, t2) + else + //otherwise include type qualifiers and typedef names + t1 = t2 +} diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql new file mode 100644 index 0000000000..28f17e30d3 --- /dev/null +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -0,0 +1,48 @@ +/** + * @id c/misra/declarations-of-a-function-same-name-and-type + * @name RULE-8-3: All declarations of a function shall use the same names and type qualifiers + * @description Using different types across the same declarations disallows strong type checking + * and can lead to undefined behaviour. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-8-3 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import Compatible + +from FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, string case +where + not isExcluded(f1, Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery()) and + not isExcluded(f2, Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery()) and + not f1 = f2 and + f1.getDeclaration() = f2.getDeclaration() and + //return type check + ( + not typesCompatible(f1.getType(), f2.getType()) and + case = "return type" + or + //parameter type check + exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | + p1 = f1.getParameterDeclarationEntry(i) and + p2 = f2.getParameterDeclarationEntry(i) + | + not typesCompatible(p1.getType(), p2.getType()) + ) and + case = "parameter types" + or + //parameter name check + exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | + p1 = f1.getParameterDeclarationEntry(i) and + p2 = f2.getParameterDeclarationEntry(i) + | + not p1.getName() = p2.getName() + ) and + case = "parameter names" + ) +select f1, "The " + case + " of re-declaration of $@ is not compatible with declaration $@", f1, + f1.getName(), f2, f2.getName() diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql new file mode 100644 index 0000000000..b1f437c676 --- /dev/null +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql @@ -0,0 +1,28 @@ +/** + * @id c/misra/declarations-of-an-object-same-name-and-type + * @name RULE-8-3: All declarations of an object shall use the same names and type qualifiers + * @description Using different types across the same declarations disallows strong type checking + * and can lead to undefined behaviour. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-8-3 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import Compatible + +from VariableDeclarationEntry decl1, VariableDeclarationEntry decl2 +where + not isExcluded(decl1, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and + not isExcluded(decl2, Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery()) and + not decl1 = decl2 and + decl1.getVariable().getQualifiedName() = decl2.getVariable().getQualifiedName() and + not typesCompatible(decl1.getType(), decl2.getType()) +select decl1, + "The object $@ of type " + decl1.getType().toString() + + " is not compatible with re-declaration $@ of type " + decl2.getType().toString(), decl1, + decl1.getName(), decl2, decl2.getName() diff --git a/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected b/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected new file mode 100644 index 0000000000..08e419ef4f --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.expected @@ -0,0 +1,12 @@ +| function1.c:6:6:6:7 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:6:6:6:7 | declaration of f3 | f3 | function1.c:8:4:8:5 | declaration of f3 | f3 | +| function1.c:8:4:8:5 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:8:4:8:5 | declaration of f3 | f3 | function1.c:6:6:6:7 | declaration of f3 | f3 | +| function1.c:8:4:8:5 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:8:4:8:5 | declaration of f3 | f3 | function2.c:4:6:4:7 | declaration of f3 | f3 | +| function1.c:9:6:9:7 | declaration of f4 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:9:6:9:7 | declaration of f4 | f4 | function2.c:5:5:5:6 | declaration of f4 | f4 | +| function1.c:13:5:13:6 | definition of f6 | The return type of re-declaration of $@ is not compatible with declaration $@ | function1.c:13:5:13:6 | definition of f6 | f6 | function2.c:9:6:9:7 | definition of f6 | f6 | +| function1.c:21:3:21:5 | definition of f21 | The parameter types of re-declaration of $@ is not compatible with declaration $@ | function1.c:21:3:21:5 | definition of f21 | f21 | function2.c:17:10:17:12 | declaration of f21 | f21 | +| function1.c:25:6:25:8 | definition of f22 | The parameter names of re-declaration of $@ is not compatible with declaration $@ | function1.c:25:6:25:8 | definition of f22 | f22 | function2.c:19:13:19:15 | declaration of f22 | f22 | +| function2.c:4:6:4:7 | declaration of f3 | The return type of re-declaration of $@ is not compatible with declaration $@ | function2.c:4:6:4:7 | declaration of f3 | f3 | function1.c:8:4:8:5 | declaration of f3 | f3 | +| function2.c:5:5:5:6 | declaration of f4 | The return type of re-declaration of $@ is not compatible with declaration $@ | function2.c:5:5:5:6 | declaration of f4 | f4 | function1.c:9:6:9:7 | declaration of f4 | f4 | +| function2.c:9:6:9:7 | definition of f6 | The return type of re-declaration of $@ is not compatible with declaration $@ | function2.c:9:6:9:7 | definition of f6 | f6 | function1.c:13:5:13:6 | definition of f6 | f6 | +| function2.c:17:10:17:12 | declaration of f21 | The parameter types of re-declaration of $@ is not compatible with declaration $@ | function2.c:17:10:17:12 | declaration of f21 | f21 | function1.c:21:3:21:5 | definition of f21 | f21 | +| function2.c:19:13:19:15 | declaration of f22 | The parameter names of re-declaration of $@ is not compatible with declaration $@ | function2.c:19:13:19:15 | declaration of f22 | f22 | function1.c:25:6:25:8 | definition of f22 | f22 | diff --git a/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.qlref b/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.qlref new file mode 100644 index 0000000000..f7c628941f --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.qlref @@ -0,0 +1 @@ +rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected b/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected new file mode 100644 index 0000000000..a90e0aa57d --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.expected @@ -0,0 +1,16 @@ +| object1.c:3:6:3:7 | definition of a3 | The object $@ of type long is not compatible with re-declaration $@ of type LL | object1.c:3:6:3:7 | definition of a3 | a3 | object2.c:9:11:9:12 | declaration of a3 | a3 | +| object1.c:4:6:4:7 | definition of a4 | The object $@ of type long is not compatible with re-declaration $@ of type int | object1.c:4:6:4:7 | definition of a4 | a4 | object2.c:11:12:11:13 | declaration of a4 | a4 | +| object1.c:5:5:5:6 | definition of a5 | The object $@ of type int is not compatible with re-declaration $@ of type long | object1.c:5:5:5:6 | definition of a5 | a5 | object2.c:13:13:13:14 | declaration of a5 | a5 | +| object1.c:6:6:6:7 | definition of a6 | The object $@ of type long is not compatible with re-declaration $@ of type int | object1.c:6:6:6:7 | definition of a6 | a6 | object2.c:17:1:17:3 | declaration of a6 | a6 | +| object1.c:7:5:7:6 | definition of a7 | The object $@ of type int is not compatible with re-declaration $@ of type LL | object1.c:7:5:7:6 | definition of a7 | a7 | object2.c:19:11:19:12 | declaration of a7 | a7 | +| object1.c:13:5:13:7 | definition of a10 | The object $@ of type int[100] is not compatible with re-declaration $@ of type LI[100] | object1.c:13:5:13:7 | definition of a10 | a10 | object2.c:22:4:22:6 | definition of a10 | a10 | +| object1.c:14:5:14:7 | definition of a11 | The object $@ of type int[100] is not compatible with re-declaration $@ of type int[101] | object1.c:14:5:14:7 | definition of a11 | a11 | object2.c:23:12:23:14 | declaration of a11 | a11 | +| object1.c:17:12:17:14 | definition of a13 | The object $@ of type int *const is not compatible with re-declaration $@ of type int * | object1.c:17:12:17:14 | definition of a13 | a13 | object2.c:26:13:26:15 | declaration of a13 | a13 | +| object2.c:9:11:9:12 | declaration of a3 | The object $@ of type LL is not compatible with re-declaration $@ of type long | object2.c:9:11:9:12 | declaration of a3 | a3 | object1.c:3:6:3:7 | definition of a3 | a3 | +| object2.c:11:12:11:13 | declaration of a4 | The object $@ of type int is not compatible with re-declaration $@ of type long | object2.c:11:12:11:13 | declaration of a4 | a4 | object1.c:4:6:4:7 | definition of a4 | a4 | +| object2.c:13:13:13:14 | declaration of a5 | The object $@ of type long is not compatible with re-declaration $@ of type int | object2.c:13:13:13:14 | declaration of a5 | a5 | object1.c:5:5:5:6 | definition of a5 | a5 | +| object2.c:17:1:17:3 | declaration of a6 | The object $@ of type int is not compatible with re-declaration $@ of type long | object2.c:17:1:17:3 | declaration of a6 | a6 | object1.c:6:6:6:7 | definition of a6 | a6 | +| object2.c:19:11:19:12 | declaration of a7 | The object $@ of type LL is not compatible with re-declaration $@ of type int | object2.c:19:11:19:12 | declaration of a7 | a7 | object1.c:7:5:7:6 | definition of a7 | a7 | +| object2.c:22:4:22:6 | definition of a10 | The object $@ of type LI[100] is not compatible with re-declaration $@ of type int[100] | object2.c:22:4:22:6 | definition of a10 | a10 | object1.c:13:5:13:7 | definition of a10 | a10 | +| object2.c:23:12:23:14 | declaration of a11 | The object $@ of type int[101] is not compatible with re-declaration $@ of type int[100] | object2.c:23:12:23:14 | declaration of a11 | a11 | object1.c:14:5:14:7 | definition of a11 | a11 | +| object2.c:26:13:26:15 | declaration of a13 | The object $@ of type int * is not compatible with re-declaration $@ of type int *const | object2.c:26:13:26:15 | declaration of a13 | a13 | object1.c:17:12:17:14 | definition of a13 | a13 | diff --git a/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.qlref b/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.qlref new file mode 100644 index 0000000000..132b3d8f29 --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.qlref @@ -0,0 +1 @@ +rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/function1.c b/c/misra/test/rules/RULE-8-3/function1.c new file mode 100644 index 0000000000..2072748047 --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/function1.c @@ -0,0 +1,27 @@ +typedef long LL; + +int f1(); // COMPLIANT +int f2(int f2a); // COMPLIANT + +long f3(); // NON_COMPLIANT + +LL f3(); // NON_COMPLIANT +long f4(int f4a); // NON_COMPLIANT + +long f5(int f5a) { return 0; } // COMPLIANT + +int f6(int f6a) { return 0; } // NON_COMPLIANT + +int f20(int f20a); // COMPLIANT - overloaded function + +typedef int wi; +typedef int hi; +typedef long a; + +a f21(wi w, wi h) { // NON_COMPLIANT + return (a)w * h; +} + +void f22(int f22b, int f22a) { // NON_COMPLIANT + return; +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/function2.c b/c/misra/test/rules/RULE-8-3/function2.c new file mode 100644 index 0000000000..979e002466 --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/function2.c @@ -0,0 +1,19 @@ +int f1(); // COMPLIANT +int f2(int f2a); // COMPLIANT + +long f3(); // NON_COMPLIANT +int f4(int f4a); // NON_COMPLIANT + +long f5(int f5a) { return 0; } // COMPLIANT + +long f6(int f6a) { return 0; } // NON_COMPLIANT + +int f20(int f20a, int f20b); // COMPLIANT -- overloaded function + +typedef int wi; +typedef int hi; +typedef long a; + +extern a f21(wi w, hi h); // NON_COMPLIANT + +extern void f22(int f22a, int f22b); // NON_COMPLIANT \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/object1.c b/c/misra/test/rules/RULE-8-3/object1.c new file mode 100644 index 0000000000..2c79cf6e91 --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/object1.c @@ -0,0 +1,17 @@ +int a1; // COMPLIANT +int a2; // COMPLIANT +long a3; // NON_COMPLIANT +long a4; // NON_COMPLIANT +int a5; // NON_COMPLIANT +long a6; // NON_COMPLIANT +int a7; // NON_COMPLIANT + +int a8; // COMPLIANT +extern int a8; // COMPLIANT + +int a9[100]; // COMPLIANT +int a10[100]; // NON_COMPLIANT +int a11[100]; // NON_COMPLIANT - different sizes +int a12; // COMPLIANT + +int *const a13; // NON_COMPLIANT diff --git a/c/misra/test/rules/RULE-8-3/object2.c b/c/misra/test/rules/RULE-8-3/object2.c new file mode 100644 index 0000000000..c53cbb6176 --- /dev/null +++ b/c/misra/test/rules/RULE-8-3/object2.c @@ -0,0 +1,26 @@ +extern int a1; // COMPLIANT + +#define EE extern int a2 +EE; // COMPLIANT + +typedef long LL; +typedef int LI; + +extern LL a3; // NON_COMPLIANT + +extern int a4; // NON_COMPLIANT + +extern long a5; // NON_COMPLIANT + +#define EE1 extern int a6 + +EE1; // NON_COMPLIANT + +extern LL a7; // NON_COMPLIANT + +extern int a9[100]; // COMPLIANT +LI a10[100]; // NON_COMPLIANT +extern int a11[101]; // NON_COMPLIANT - different sizes +signed a12; // COMPLIANT + +extern int *a13; // NON_COMPLIANT \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-3/test.c b/c/misra/test/rules/RULE-8-3/test.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll index 29cae700f3..97efaccd85 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll @@ -5,6 +5,8 @@ import codingstandards.cpp.exclusions.RuleMetadata newtype Declarations4Query = TFunctionTypesNotInPrototypeFormQuery() or + TDeclarationsOfAnObjectSameNameAndTypeQuery() or + TDeclarationsOfAFunctionSameNameAndTypeQuery() or TIdentifierWithExternalLinkageOneDefinitionQuery() predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleId) { @@ -16,6 +18,22 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI "c/misra/function-types-not-in-prototype-form" and ruleId = "RULE-8-2" or + query = + // `Query` instance for the `declarationsOfAnObjectSameNameAndType` query + Declarations4Package::declarationsOfAnObjectSameNameAndTypeQuery() and + queryId = + // `@id` for the `declarationsOfAnObjectSameNameAndType` query + "c/misra/declarations-of-an-object-same-name-and-type" and + ruleId = "RULE-8-3" + or + query = + // `Query` instance for the `declarationsOfAFunctionSameNameAndType` query + Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery() and + queryId = + // `@id` for the `declarationsOfAFunctionSameNameAndType` query + "c/misra/declarations-of-a-function-same-name-and-type" and + ruleId = "RULE-8-3" + or query = // `Query` instance for the `identifierWithExternalLinkageOneDefinition` query Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery() and @@ -33,6 +51,20 @@ module Declarations4Package { TQueryC(TDeclarations4PackageQuery(TFunctionTypesNotInPrototypeFormQuery())) } + Query declarationsOfAnObjectSameNameAndTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `declarationsOfAnObjectSameNameAndType` query + TQueryC(TDeclarations4PackageQuery(TDeclarationsOfAnObjectSameNameAndTypeQuery())) + } + + Query declarationsOfAFunctionSameNameAndTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `declarationsOfAFunctionSameNameAndType` query + TQueryC(TDeclarations4PackageQuery(TDeclarationsOfAFunctionSameNameAndTypeQuery())) + } + Query identifierWithExternalLinkageOneDefinitionQuery() { //autogenerate `Query` type result = diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 5c1f45f1ee..0a118a6c6f 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -18,6 +18,7 @@ import IO1 import IO2 import IO3 import IO4 +import Language2 import Misc import Pointers1 import Pointers2 @@ -51,6 +52,7 @@ newtype TCQuery = TIO2PackageQuery(IO2Query q) or TIO3PackageQuery(IO3Query q) or TIO4PackageQuery(IO4Query q) or + TLanguage2PackageQuery(Language2Query q) or TMiscPackageQuery(MiscQuery q) or TPointers1PackageQuery(Pointers1Query q) or TPointers2PackageQuery(Pointers2Query q) or @@ -84,6 +86,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId) { isIO2QueryMetadata(query, queryId, ruleId) or isIO3QueryMetadata(query, queryId, ruleId) or isIO4QueryMetadata(query, queryId, ruleId) or + isLanguage2QueryMetadata(query, queryId, ruleId) or isMiscQueryMetadata(query, queryId, ruleId) or isPointers1QueryMetadata(query, queryId, ruleId) or isPointers2QueryMetadata(query, queryId, ruleId) or diff --git a/rule_packages/c/Declarations4.json b/rule_packages/c/Declarations4.json index 4efd48d25a..cb232061ab 100644 --- a/rule_packages/c/Declarations4.json +++ b/rule_packages/c/Declarations4.json @@ -23,6 +23,36 @@ ], "title": "Function types shall be in prototype form with named parameters" }, + "RULE-8-3": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Using different types across the same declarations disallows strong type checking and can lead to undefined behaviour.", + "kind": "problem", + "name": "All declarations of an object shall use the same names and type qualifiers", + "precision": "very-high", + "severity": "error", + "short_name": "DeclarationsOfAnObjectSameNameAndType", + "tags": [ + "correctness" + ] + }, + { + "description": "Using different types across the same declarations disallows strong type checking and can lead to undefined behaviour.", + "kind": "problem", + "name": "All declarations of a function shall use the same names and type qualifiers", + "precision": "very-high", + "severity": "error", + "short_name": "DeclarationsOfAFunctionSameNameAndType", + "tags": [ + "correctness" + ] + } + ], + "title": "All declarations of an object or function shall use the same names and type qualifiers" + }, "RULE-8-6": { "properties": { "obligation": "required" diff --git a/rules.csv b/rules.csv index ce93dd72e9..b91bbdafb5 100755 --- a/rules.csv +++ b/rules.csv @@ -648,7 +648,7 @@ c,MISRA-C-2012,RULE-7-3,Yes,Required,,,The lowercase character �l� shall not c,MISRA-C-2012,RULE-7-4,Yes,Required,,,A string literal shall not be assigned to an object unless the object�s type is �pointer to const-qualified char�,A2-13-4,Types,Easy, c,MISRA-C-2012,RULE-8-1,Yes,Required,,,Types shall be explicitly specified,,Declarations3,Medium, c,MISRA-C-2012,RULE-8-2,Yes,Required,,,Function types shall be in prototype form with named parameters,,Declarations4,Medium, -c,MISRA-C-2012,RULE-8-3,Yes,Required,,,All declarations of an object or function shall use the same names and type qualifiers,M3-2-1,Declarations,Medium, +c,MISRA-C-2012,RULE-8-3,Yes,Required,,,All declarations of an object or function shall use the same names and type qualifiers,M3-2-1,Declarations4,Medium, c,MISRA-C-2012,RULE-8-4,Yes,Required,,,A compatible declaration shall be visible when an object or function with external linkage is defined,,Declarations,Medium, c,MISRA-C-2012,RULE-8-5,Yes,Required,,,An external object or function shall be declared once in one and only one file,,Declarations,Medium, c,MISRA-C-2012,RULE-8-6,Yes,Required,,,An identifier with external linkage shall have exactly one external definition,M3-2-4,Declarations4,Import, From 2224ab5a07a66623465c2cdc35efda5a2260e0cd Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 9 Nov 2022 17:09:54 -0500 Subject: [PATCH 07/13] Revert accidental addition to exclusion file after test writing --- .../src/codingstandards/cpp/exclusions/c/RuleMetadata.qll | 3 --- 1 file changed, 3 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 0a118a6c6f..5c1f45f1ee 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -18,7 +18,6 @@ import IO1 import IO2 import IO3 import IO4 -import Language2 import Misc import Pointers1 import Pointers2 @@ -52,7 +51,6 @@ newtype TCQuery = TIO2PackageQuery(IO2Query q) or TIO3PackageQuery(IO3Query q) or TIO4PackageQuery(IO4Query q) or - TLanguage2PackageQuery(Language2Query q) or TMiscPackageQuery(MiscQuery q) or TPointers1PackageQuery(Pointers1Query q) or TPointers2PackageQuery(Pointers2Query q) or @@ -86,7 +84,6 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId) { isIO2QueryMetadata(query, queryId, ruleId) or isIO3QueryMetadata(query, queryId, ruleId) or isIO4QueryMetadata(query, queryId, ruleId) or - isLanguage2QueryMetadata(query, queryId, ruleId) or isMiscQueryMetadata(query, queryId, ruleId) or isPointers1QueryMetadata(query, queryId, ruleId) or isPointers2QueryMetadata(query, queryId, ruleId) or From ce559bc7b8fcf841a4f88c6021e452216b83422d Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Thu, 10 Nov 2022 12:02:06 -0500 Subject: [PATCH 08/13] Declarations4: fix formatting --- c/misra/src/rules/RULE-8-3/Compatible.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/RULE-8-3/Compatible.qll b/c/misra/src/rules/RULE-8-3/Compatible.qll index 52e77692c5..407e275032 100644 --- a/c/misra/src/rules/RULE-8-3/Compatible.qll +++ b/c/misra/src/rules/RULE-8-3/Compatible.qll @@ -26,5 +26,5 @@ predicate typesCompatible(Type t1, Type t2) { arithTypesMatch(t1, t2) else //otherwise include type qualifiers and typedef names - t1 = t2 + t1 = t2 } From b601c91b2aa6cb8caac21635f5cc75c02c2d0472 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Thu, 17 Nov 2022 12:44:59 -0500 Subject: [PATCH 09/13] Declarations4: refactor RULE-8-3 compatible lib and compatible correctness --- c/misra/src/rules/RULE-8-3/Compatible.qll | 30 ---------------- .../DeclarationsOfAFunctionSameNameAndType.ql | 34 ++++++++++++------- .../DeclarationsOfAnObjectSameNameAndType.ql | 2 +- .../src/codingstandards/cpp/Compatible.qll | 8 +++++ 4 files changed, 30 insertions(+), 44 deletions(-) delete mode 100644 c/misra/src/rules/RULE-8-3/Compatible.qll create mode 100644 cpp/common/src/codingstandards/cpp/Compatible.qll diff --git a/c/misra/src/rules/RULE-8-3/Compatible.qll b/c/misra/src/rules/RULE-8-3/Compatible.qll deleted file mode 100644 index 407e275032..0000000000 --- a/c/misra/src/rules/RULE-8-3/Compatible.qll +++ /dev/null @@ -1,30 +0,0 @@ -import cpp - -/* - * This is a copy of the `arithTypesMatch` predicate from the standard set of - * queries as of the `codeql-cli/2.9.4` tag in `github/codeql`. - */ - -pragma[inline] -predicate arithTypesMatch(Type t1, Type t2) { - t1 = t2 - or - t1.getSize() = t2.getSize() and - ( - t1 instanceof IntegralOrEnumType and - t2 instanceof IntegralOrEnumType - or - t1 instanceof FloatingPointType and - t2 instanceof FloatingPointType - ) -} - -predicate typesCompatible(Type t1, Type t2) { - if t1 instanceof BuiltInType and t2 instanceof BuiltInType - then - //for simple types consider compatible - arithTypesMatch(t1, t2) - else - //otherwise include type qualifiers and typedef names - t1 = t2 -} diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index 28f17e30d3..f02fb78066 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -13,7 +13,25 @@ import cpp import codingstandards.c.misra -import Compatible +import codingstandards.cpp.Compatible + +predicate parameterTypesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | + p1 = f1.getParameterDeclarationEntry(i) and + p2 = f2.getParameterDeclarationEntry(i) + | + not typesCompatible(p1.getType(), p2.getType()) + ) +} + +predicate parameterNamesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | + p1 = f1.getParameterDeclarationEntry(i) and + p2 = f2.getParameterDeclarationEntry(i) + | + not p1.getName() = p2.getName() + ) +} from FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, string case where @@ -27,21 +45,11 @@ where case = "return type" or //parameter type check - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) - | - not typesCompatible(p1.getType(), p2.getType()) - ) and + parameterTypesIncompatible(f1, f2) and case = "parameter types" or //parameter name check - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) - | - not p1.getName() = p2.getName() - ) and + parameterNamesIncompatible(f1, f2) and case = "parameter names" ) select f1, "The " + case + " of re-declaration of $@ is not compatible with declaration $@", f1, diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql index b1f437c676..03acda6dd7 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAnObjectSameNameAndType.ql @@ -13,7 +13,7 @@ import cpp import codingstandards.c.misra -import Compatible +import codingstandards.cpp.Compatible from VariableDeclarationEntry decl1, VariableDeclarationEntry decl2 where diff --git a/cpp/common/src/codingstandards/cpp/Compatible.qll b/cpp/common/src/codingstandards/cpp/Compatible.qll new file mode 100644 index 0000000000..da54da3489 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/Compatible.qll @@ -0,0 +1,8 @@ +import cpp + +predicate typesCompatible(Type t1, Type t2) { + t1 = t2 + or + //signed int is same as int ect + t1.(IntegralType).getCanonicalArithmeticType() = t2.(IntegralType).getCanonicalArithmeticType() +} From 3b4443e27bb6757414219e7d1b70bde536ac7622 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Thu, 17 Nov 2022 13:01:04 -0500 Subject: [PATCH 10/13] Declarations4: add RULE-8-4 --- .../DeclarationsOfAFunctionSameNameAndType.ql | 18 ------- .../CompatibleDeclarationFunctionDefined.ql | 50 +++++++++++++++++++ .../CompatibleDeclarationObjectDefined.ql | 38 ++++++++++++++ ...patibleDeclarationFunctionDefined.expected | 2 + ...CompatibleDeclarationFunctionDefined.qlref | 1 + ...ompatibleDeclarationObjectDefined.expected | 3 ++ .../CompatibleDeclarationObjectDefined.qlref | 1 + c/misra/test/rules/RULE-8-4/function1.c | 3 ++ c/misra/test/rules/RULE-8-4/function2.c | 9 ++++ c/misra/test/rules/RULE-8-4/object1.c | 10 ++++ c/misra/test/rules/RULE-8-4/object2.c | 3 ++ c/misra/test/rules/RULE-8-4/test.c | 0 .../src/codingstandards/cpp/Compatible.qll | 18 +++++++ .../cpp/exclusions/c/Declarations4.qll | 32 ++++++++++++ rule_packages/c/Declarations4.json | 42 ++++++++++++++++ rules.csv | 2 +- 16 files changed, 213 insertions(+), 19 deletions(-) create mode 100644 c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql create mode 100644 c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql create mode 100644 c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected create mode 100644 c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.qlref create mode 100644 c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.expected create mode 100644 c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.qlref create mode 100644 c/misra/test/rules/RULE-8-4/function1.c create mode 100644 c/misra/test/rules/RULE-8-4/function2.c create mode 100644 c/misra/test/rules/RULE-8-4/object1.c create mode 100644 c/misra/test/rules/RULE-8-4/object2.c create mode 100644 c/misra/test/rules/RULE-8-4/test.c diff --git a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql index f02fb78066..6803af9380 100644 --- a/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -15,24 +15,6 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.Compatible -predicate parameterTypesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) - | - not typesCompatible(p1.getType(), p2.getType()) - ) -} - -predicate parameterNamesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { - exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | - p1 = f1.getParameterDeclarationEntry(i) and - p2 = f2.getParameterDeclarationEntry(i) - | - not p1.getName() = p2.getName() - ) -} - from FunctionDeclarationEntry f1, FunctionDeclarationEntry f2, string case where not isExcluded(f1, Declarations4Package::declarationsOfAFunctionSameNameAndTypeQuery()) and diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql new file mode 100644 index 0000000000..c87e5b556c --- /dev/null +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql @@ -0,0 +1,50 @@ +/** + * @id c/misra/compatible-declaration-function-defined + * @name RULE-8-4: A compatible declaration shall be visible when a function with external linkage is defined + * @description A compatible declaration shall be visible when a function with external linkage is + * defined, otherwise program behaviour may be undefined. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-8-4 + * readability + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Identifiers +import codingstandards.cpp.Compatible + +from FunctionDeclarationEntry f1 +where + not isExcluded(f1, Declarations4Package::compatibleDeclarationFunctionDefinedQuery()) and + f1.isDefinition() and + f1.getDeclaration() instanceof ExternalIdentifiers and + //no declaration matches exactly + ( + not exists(FunctionDeclarationEntry f2 | + not f2.isDefinition() and + f2.getDeclaration() = f1.getDeclaration() + ) + or + //or one exists that is close but incompatible in some way + exists(FunctionDeclarationEntry f2 | + f1.getName() = f2.getName() and + not f2.isDefinition() and + f2.getDeclaration() = f1.getDeclaration() and + //return types differ + ( + not typesCompatible(f1.getType(), f2.getType()) + or + //parameter types differ + parameterTypesIncompatible(f1, f2) + or + //parameter names differ + parameterNamesIncompatible(f1, f2) + ) + ) + ) +select f1, "No separate compatible declaration found for this definition." diff --git a/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql new file mode 100644 index 0000000000..7b0e194afb --- /dev/null +++ b/c/misra/src/rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql @@ -0,0 +1,38 @@ +/** + * @id c/misra/compatible-declaration-object-defined + * @name RULE-8-4: A compatible declaration shall be visible when an object with external linkage is defined + * @description A compatible declaration shall be visible when an object with external linkage is + * defined, otherwise program behaviour may be undefined. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-8-4 + * readability + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.Identifiers +import codingstandards.cpp.Compatible + +from VariableDeclarationEntry decl1 +where + not isExcluded(decl1, Declarations4Package::compatibleDeclarationObjectDefinedQuery()) and + decl1.isDefinition() and + decl1.getDeclaration() instanceof ExternalIdentifiers and + ( + //no declaration matches exactly + not exists(VariableDeclarationEntry decl2 | + not decl2.isDefinition() and decl2.getDeclaration() = decl1.getDeclaration() + ) and + //and none is close enough + not exists(VariableDeclarationEntry decl2 | + not decl2.isDefinition() and + decl1.getVariable().getQualifiedName() = decl2.getVariable().getQualifiedName() and + typesCompatible(decl1.getType(), decl2.getType()) + ) + ) +select decl1, "No separate compatible declaration found for this definition." diff --git a/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected new file mode 100644 index 0000000000..6671f904c2 --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected @@ -0,0 +1,2 @@ +| function2.c:5:6:5:7 | definition of f3 | | +| function2.c:7:6:7:7 | definition of f4 | | diff --git a/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.qlref b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.qlref new file mode 100644 index 0000000000..d5c5e458c6 --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.qlref @@ -0,0 +1 @@ +rules/RULE-8-4/CompatibleDeclarationFunctionDefined.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.expected b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.expected new file mode 100644 index 0000000000..6655c5d6f7 --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.expected @@ -0,0 +1,3 @@ +| object1.c:4:12:4:13 | definition of i1 | No separate compatible declaration found for this definition. | +| object1.c:6:5:6:6 | definition of i2 | No separate compatible declaration found for this definition. | +| object2.c:1:7:1:8 | definition of i3 | No separate compatible declaration found for this definition. | diff --git a/c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.qlref b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.qlref new file mode 100644 index 0000000000..a277016125 --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationObjectDefined.qlref @@ -0,0 +1 @@ +rules/RULE-8-4/CompatibleDeclarationObjectDefined.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-4/function1.c b/c/misra/test/rules/RULE-8-4/function1.c new file mode 100644 index 0000000000..952b6c7d0e --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/function1.c @@ -0,0 +1,3 @@ +extern void f1(); // COMPLIANT +extern void f2(int x, int y); // COMPLIANT +extern void f3(int x, int y); // NON_COMPLIANT diff --git a/c/misra/test/rules/RULE-8-4/function2.c b/c/misra/test/rules/RULE-8-4/function2.c new file mode 100644 index 0000000000..00c7c28200 --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/function2.c @@ -0,0 +1,9 @@ +void f1() {} // COMPLIANT + +void f2(int x, int y) {} // COMPLIANT + +void f3(short x, int y) {} // NON_COMPLIANT + +void f4() {} // NON_COMPLIANT + +static void f5() {} // COMPLIANT \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-4/object1.c b/c/misra/test/rules/RULE-8-4/object1.c new file mode 100644 index 0000000000..3de20eabcc --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/object1.c @@ -0,0 +1,10 @@ +extern int i; +i = 0; // COMPLIANT + +extern int i1 = 0; // NON_COMPLIANT + +int i2 = 0; // NON_COMPLIANT + +extern int i3; // NON_COMPLIANT + +extern int i4; // COMPLIANT \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-4/object2.c b/c/misra/test/rules/RULE-8-4/object2.c new file mode 100644 index 0000000000..78c5bee421 --- /dev/null +++ b/c/misra/test/rules/RULE-8-4/object2.c @@ -0,0 +1,3 @@ +short i3 = 0; // NON_COMPLIANT + +signed int i4 = 0; // COMPLIANT \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-4/test.c b/c/misra/test/rules/RULE-8-4/test.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cpp/common/src/codingstandards/cpp/Compatible.qll b/cpp/common/src/codingstandards/cpp/Compatible.qll index da54da3489..12a53965fe 100644 --- a/cpp/common/src/codingstandards/cpp/Compatible.qll +++ b/cpp/common/src/codingstandards/cpp/Compatible.qll @@ -6,3 +6,21 @@ predicate typesCompatible(Type t1, Type t2) { //signed int is same as int ect t1.(IntegralType).getCanonicalArithmeticType() = t2.(IntegralType).getCanonicalArithmeticType() } + +predicate parameterTypesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | + p1 = f1.getParameterDeclarationEntry(i) and + p2 = f2.getParameterDeclarationEntry(i) + | + not typesCompatible(p1.getType(), p2.getType()) + ) +} + +predicate parameterNamesIncompatible(FunctionDeclarationEntry f1, FunctionDeclarationEntry f2) { + exists(ParameterDeclarationEntry p1, ParameterDeclarationEntry p2, int i | + p1 = f1.getParameterDeclarationEntry(i) and + p2 = f2.getParameterDeclarationEntry(i) + | + not p1.getName() = p2.getName() + ) +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll index 97efaccd85..5e2b9d0695 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll @@ -7,6 +7,8 @@ newtype Declarations4Query = TFunctionTypesNotInPrototypeFormQuery() or TDeclarationsOfAnObjectSameNameAndTypeQuery() or TDeclarationsOfAFunctionSameNameAndTypeQuery() or + TCompatibleDeclarationObjectDefinedQuery() or + TCompatibleDeclarationFunctionDefinedQuery() or TIdentifierWithExternalLinkageOneDefinitionQuery() predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleId) { @@ -34,6 +36,22 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI "c/misra/declarations-of-a-function-same-name-and-type" and ruleId = "RULE-8-3" or + query = + // `Query` instance for the `compatibleDeclarationObjectDefined` query + Declarations4Package::compatibleDeclarationObjectDefinedQuery() and + queryId = + // `@id` for the `compatibleDeclarationObjectDefined` query + "c/misra/compatible-declaration-object-defined" and + ruleId = "RULE-8-4" + or + query = + // `Query` instance for the `compatibleDeclarationFunctionDefined` query + Declarations4Package::compatibleDeclarationFunctionDefinedQuery() and + queryId = + // `@id` for the `compatibleDeclarationFunctionDefined` query + "c/misra/compatible-declaration-function-defined" and + ruleId = "RULE-8-4" + or query = // `Query` instance for the `identifierWithExternalLinkageOneDefinition` query Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery() and @@ -65,6 +83,20 @@ module Declarations4Package { TQueryC(TDeclarations4PackageQuery(TDeclarationsOfAFunctionSameNameAndTypeQuery())) } + Query compatibleDeclarationObjectDefinedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `compatibleDeclarationObjectDefined` query + TQueryC(TDeclarations4PackageQuery(TCompatibleDeclarationObjectDefinedQuery())) + } + + Query compatibleDeclarationFunctionDefinedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `compatibleDeclarationFunctionDefined` query + TQueryC(TDeclarations4PackageQuery(TCompatibleDeclarationFunctionDefinedQuery())) + } + Query identifierWithExternalLinkageOneDefinitionQuery() { //autogenerate `Query` type result = diff --git a/rule_packages/c/Declarations4.json b/rule_packages/c/Declarations4.json index cb232061ab..7b7a546d9a 100644 --- a/rule_packages/c/Declarations4.json +++ b/rule_packages/c/Declarations4.json @@ -53,6 +53,48 @@ ], "title": "All declarations of an object or function shall use the same names and type qualifiers" }, + "RULE-8-4": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "A compatible declaration shall be visible when an object with external linkage is defined, otherwise program behaviour may be undefined.", + "kind": "problem", + "name": "A compatible declaration shall be visible when an object with external linkage is defined", + "precision": "very-high", + "severity": "error", + "short_name": "CompatibleDeclarationObjectDefined", + "tags": [ + "readability", + "maintainability", + "correctness" + ], + "implementation_scope": { + "description": "This query does not check for the recommendation of declarations in headers.", + "items": [] + } + }, + { + "description": "A compatible declaration shall be visible when a function with external linkage is defined, otherwise program behaviour may be undefined.", + "kind": "problem", + "name": "A compatible declaration shall be visible when a function with external linkage is defined", + "precision": "very-high", + "severity": "error", + "short_name": "CompatibleDeclarationFunctionDefined", + "tags": [ + "readability", + "maintainability", + "correctness" + ], + "implementation_scope": { + "description": "This query does not check for the recommendation of declarations in headers.", + "items": [] + } + } + ], + "title": "A compatible declaration shall be visible when an object or function with external linkage is defined" + }, "RULE-8-6": { "properties": { "obligation": "required" diff --git a/rules.csv b/rules.csv index d8749687d7..f6adf0d196 100644 --- a/rules.csv +++ b/rules.csv @@ -649,7 +649,7 @@ c,MISRA-C-2012,RULE-7-4,Yes,Required,,,A string literal shall not be assigned to c,MISRA-C-2012,RULE-8-1,Yes,Required,,,Types shall be explicitly specified,,Declarations3,Medium, c,MISRA-C-2012,RULE-8-2,Yes,Required,,,Function types shall be in prototype form with named parameters,,Declarations4,Medium, c,MISRA-C-2012,RULE-8-3,Yes,Required,,,All declarations of an object or function shall use the same names and type qualifiers,M3-2-1,Declarations4,Medium, -c,MISRA-C-2012,RULE-8-4,Yes,Required,,,A compatible declaration shall be visible when an object or function with external linkage is defined,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-4,Yes,Required,,,A compatible declaration shall be visible when an object or function with external linkage is defined,,Declarations4,Medium, c,MISRA-C-2012,RULE-8-5,Yes,Required,,,An external object or function shall be declared once in one and only one file,,Declarations,Medium, c,MISRA-C-2012,RULE-8-6,Yes,Required,,,An identifier with external linkage shall have exactly one external definition,M3-2-4,Declarations4,Import, c,MISRA-C-2012,RULE-8-7,Yes,Advisory,,,Functions and objects should not be defined with external linkage if they are referenced in only one translation unit,,Declarations,Medium, From aa6742eb0f0c3c8103e2443e5d162ee35b453bb0 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 18 Nov 2022 12:45:09 -0500 Subject: [PATCH 11/13] Declarations4: change RULE-8-6 to share with M3-2-4 --- ...ternalLinkageOneDefinitionShared.expected} | 0 ...rWithExternalLinkageOneDefinitionShared.ql | 2 + .../test.c | 0 .../test1.c | 0 ...ntifierWithExternalLinkageOneDefinition.ql | 30 ++++----------- ...fierWithExternalLinkageOneDefinition.qlref | 1 - ...erWithExternalLinkageOneDefinition.testref | 1 + ...thExternalLinkageShallHaveOneDefinition.ql | 30 +++------------ ...xternalLinkageShallHaveOneDefinition.qlref | 1 - ...ernalLinkageShallHaveOneDefinition.testref | 1 + ...WithExternalLinkageOneDefinitionShared.qll | 37 +++++++++++++++++++ ...ternalLinkageOneDefinitionShared.expected} | 0 ...rWithExternalLinkageOneDefinitionShared.ql | 2 + .../test.cpp | 0 .../test1.cpp | 0 .../test2.cpp | 0 rule_packages/c/Declarations4.json | 3 +- rule_packages/cpp/Scope.json | 1 + 18 files changed, 59 insertions(+), 50 deletions(-) rename c/{misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected => common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected} (100%) create mode 100644 c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql rename c/{misra/test/rules/RULE-8-6 => common/test/rules/identifierwithexternallinkageonedefinitionshared}/test.c (100%) rename c/{misra/test/rules/RULE-8-6 => common/test/rules/identifierwithexternallinkageonedefinitionshared}/test1.c (100%) delete mode 100644 c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref create mode 100644 c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.testref delete mode 100644 cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.qlref create mode 100644 cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.testref create mode 100644 cpp/common/src/codingstandards/cpp/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.qll rename cpp/{autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.expected => common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected} (100%) create mode 100644 cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql rename cpp/{autosar/test/rules/M3-2-4 => common/test/rules/identifierwithexternallinkageonedefinitionshared}/test.cpp (100%) rename cpp/{autosar/test/rules/M3-2-4 => common/test/rules/identifierwithexternallinkageonedefinitionshared}/test1.cpp (100%) rename cpp/{autosar/test/rules/M3-2-4 => common/test/rules/identifierwithexternallinkageonedefinitionshared}/test2.cpp (100%) diff --git a/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected similarity index 100% rename from c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.expected rename to c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected diff --git a/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql new file mode 100644 index 0000000000..0d540a0fb1 --- /dev/null +++ b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.identifierwithexternallinkageonedefinitionshared.IdentifierWithExternalLinkageOneDefinitionShared diff --git a/c/misra/test/rules/RULE-8-6/test.c b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.c similarity index 100% rename from c/misra/test/rules/RULE-8-6/test.c rename to c/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.c diff --git a/c/misra/test/rules/RULE-8-6/test1.c b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/test1.c similarity index 100% rename from c/misra/test/rules/RULE-8-6/test1.c rename to c/common/test/rules/identifierwithexternallinkageonedefinitionshared/test1.c diff --git a/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql b/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql index 7cc3846687..2eb5028dba 100644 --- a/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql +++ b/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql @@ -1,6 +1,6 @@ /** * @id c/misra/identifier-with-external-linkage-one-definition - * @name RULE-8-6: An identifier with external linkage shall have exactly one external definition + * @name RULE-8-6: An identifier with external linkage shall have exactly one definition * @description An identifier with multiple definitions in different translation units leads to * undefined behavior. * @kind problem @@ -13,26 +13,10 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Identifiers +import codingstandards.cpp.rules.identifierwithexternallinkageonedefinitionshared.IdentifierWithExternalLinkageOneDefinitionShared -from ExternalIdentifiers d, DeclarationEntry de1, DeclarationEntry de2 -where - not isExcluded(d, Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery()) and - not isExcluded([de1, de2], Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery()) and - d.isTopLevel() and - d = de1.getDeclaration() and - d = de2.getDeclaration() and - de1 != de2 and - de1.isDefinition() and - de2.isDefinition() and - //exceptions - (d instanceof Function implies not d.(Function).isInline()) and - // Apply an ordering based on location to enforce that (de1, de2) = (de2, de1) and we only report (de1, de2). - ( - de1.getFile().getAbsolutePath() < de2.getFile().getAbsolutePath() - or - de1.getFile().getAbsolutePath() = de2.getFile().getAbsolutePath() and - de1.getLocation().getStartLine() < de2.getLocation().getStartLine() - ) -select de1, "The identifier " + de1.getName() + " has external linkage and is redefined $@.", de2, - "here" +class IdentifierWithExternalLinkageShallHaveOneDefinitionQuery extends IdentifierWithExternalLinkageOneDefinitionSharedSharedQuery { + IdentifierWithExternalLinkageShallHaveOneDefinitionQuery() { + this = Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery() + } +} diff --git a/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref deleted file mode 100644 index aa86a9534d..0000000000 --- a/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.testref b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.testref new file mode 100644 index 0000000000..4ab2802c0d --- /dev/null +++ b/c/misra/test/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.testref @@ -0,0 +1 @@ +c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql \ No newline at end of file diff --git a/cpp/autosar/src/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.ql b/cpp/autosar/src/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.ql index 150547078c..b7ace226a0 100644 --- a/cpp/autosar/src/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.ql +++ b/cpp/autosar/src/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.ql @@ -15,28 +15,10 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.Linkage +import codingstandards.cpp.rules.identifierwithexternallinkageonedefinitionshared.IdentifierWithExternalLinkageOneDefinitionShared -from Declaration d, DeclarationEntry de1, DeclarationEntry de2 -where - not isExcluded(d) and - not isExcluded([de1, de2]) and - hasExternalLinkage(d) and - d.isTopLevel() and - d = de1.getDeclaration() and - d = de2.getDeclaration() and - de1 != de2 and - de1.isDefinition() and - de2.isDefinition() and - // exceptions - not d instanceof TemplateClass and - (d instanceof Function implies not d.(Function).isInline()) and - // Apply an ordering based on location to enforce that (de1, de2) = (de2, de1) and we only report (de1, de2). - ( - de1.getFile().getAbsolutePath() < de2.getFile().getAbsolutePath() - or - de1.getFile().getAbsolutePath() = de2.getFile().getAbsolutePath() and - de1.getLocation().getStartLine() < de2.getLocation().getStartLine() - ) -select de1, "The identifier " + de1.getName() + " has external linkage and is redefined $@.", de2, - "here" +class IdentifierWithExternalLinkageOneDefinitionQuery extends IdentifierWithExternalLinkageOneDefinitionSharedSharedQuery { + IdentifierWithExternalLinkageOneDefinitionQuery() { + this = ScopePackage::identifierWithExternalLinkageShallHaveOneDefinitionQuery() + } +} diff --git a/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.qlref b/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.qlref deleted file mode 100644 index b202c8c8b4..0000000000 --- a/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.testref b/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.testref new file mode 100644 index 0000000000..6695553885 --- /dev/null +++ b/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.testref @@ -0,0 +1 @@ +cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.qll b/cpp/common/src/codingstandards/cpp/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.qll new file mode 100644 index 0000000000..17808841eb --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.qll @@ -0,0 +1,37 @@ +/** + * Provides a library which includes a `problems` predicate for reporting.... + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.Linkage + +abstract class IdentifierWithExternalLinkageOneDefinitionSharedSharedQuery extends Query { } + +Query getQuery() { result instanceof IdentifierWithExternalLinkageOneDefinitionSharedSharedQuery } + +query predicate problems(DeclarationEntry de1, string message, DeclarationEntry de2, string de2Str) { + exists(Declaration d | + not isExcluded(de1, getQuery()) and + hasExternalLinkage(d) and + d.isTopLevel() and + d = de1.getDeclaration() and + d = de2.getDeclaration() and + de1 != de2 and + de1.isDefinition() and + de2.isDefinition() and + // exceptions + not d instanceof TemplateClass and + (d instanceof Function implies not d.(Function).isInline()) and + // Apply an ordering based on location to enforce that (de1, de2) = (de2, de1) and we only report (de1, de2). + ( + de1.getFile().getAbsolutePath() < de2.getFile().getAbsolutePath() + or + de1.getFile().getAbsolutePath() = de2.getFile().getAbsolutePath() and + de1.getLocation().getStartLine() < de2.getLocation().getStartLine() + ) and + message = "The identifier " + de1.getName() + " has external linkage and is redefined $@." and + de2Str = "here" + ) +} diff --git a/cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.expected b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected similarity index 100% rename from cpp/autosar/test/rules/M3-2-4/IdentifierWithExternalLinkageShallHaveOneDefinition.expected rename to cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected diff --git a/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql new file mode 100644 index 0000000000..0d540a0fb1 --- /dev/null +++ b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.identifierwithexternallinkageonedefinitionshared.IdentifierWithExternalLinkageOneDefinitionShared diff --git a/cpp/autosar/test/rules/M3-2-4/test.cpp b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.cpp similarity index 100% rename from cpp/autosar/test/rules/M3-2-4/test.cpp rename to cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.cpp diff --git a/cpp/autosar/test/rules/M3-2-4/test1.cpp b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test1.cpp similarity index 100% rename from cpp/autosar/test/rules/M3-2-4/test1.cpp rename to cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test1.cpp diff --git a/cpp/autosar/test/rules/M3-2-4/test2.cpp b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test2.cpp similarity index 100% rename from cpp/autosar/test/rules/M3-2-4/test2.cpp rename to cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test2.cpp diff --git a/rule_packages/c/Declarations4.json b/rule_packages/c/Declarations4.json index 7b7a546d9a..bfd0b18328 100644 --- a/rule_packages/c/Declarations4.json +++ b/rule_packages/c/Declarations4.json @@ -103,10 +103,11 @@ { "description": "An identifier with multiple definitions in different translation units leads to undefined behavior.", "kind": "problem", - "name": "An identifier with external linkage shall have exactly one external definition", + "name": "An identifier with external linkage shall have exactly one definition", "precision": "high", "severity": "error", "short_name": "IdentifierWithExternalLinkageOneDefinition", + "shared_implementation_short_name": "IdentifierWithExternalLinkageOneDefinitionShared", "tags": [ "correctness" ] diff --git a/rule_packages/cpp/Scope.json b/rule_packages/cpp/Scope.json index c169badcbe..6db01eba25 100644 --- a/rule_packages/cpp/Scope.json +++ b/rule_packages/cpp/Scope.json @@ -156,6 +156,7 @@ "precision": "high", "severity": "error", "short_name": "IdentifierWithExternalLinkageShallHaveOneDefinition", + "shared_implementation_short_name": "IdentifierWithExternalLinkageOneDefinitionShared", "tags": [ "correctness" ] From 6309dbcfe18693f55b0be52e379e9a2660e73308 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 18 Nov 2022 13:09:57 -0500 Subject: [PATCH 12/13] Declarations4: address review comments --- .../src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql | 5 +++-- .../RULE-8-4/CompatibleDeclarationFunctionDefined.expected | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql index 2abeaa2f04..62aade0c0c 100644 --- a/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql +++ b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql @@ -47,11 +47,12 @@ where hasZeroParamDecl(f) and msg = "Function " + f + " does not specifiy void for no parameters present." or + //parameters declared in declaration list (not in function signature) + //have placeholder file location associated only exists(Parameter p | p.getFunction() = f and not p.getFile() = f.getFile() and msg = "Function " + f + " declares parameter in unsupported declaration list." ) - ) and - not f.isInMacroExpansion() + ) select f, msg diff --git a/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected index 6671f904c2..9153fafa97 100644 --- a/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected +++ b/c/misra/test/rules/RULE-8-4/CompatibleDeclarationFunctionDefined.expected @@ -1,2 +1,2 @@ -| function2.c:5:6:5:7 | definition of f3 | | -| function2.c:7:6:7:7 | definition of f4 | | +| function2.c:5:6:5:7 | definition of f3 | No separate compatible declaration found for this definition. | +| function2.c:7:6:7:7 | definition of f4 | No separate compatible declaration found for this definition. | From a27d650e1e690c04be48c04d2d45a3f5728325be Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 4 Jan 2023 09:54:05 -0500 Subject: [PATCH 13/13] Declarations4: fix rule metadata files --- .../cpp/exclusions/c/Declarations4.qll | 20 ++++++++++++------- .../cpp/exclusions/c/RuleMetadata.qll | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll index 5e2b9d0695..348fd97309 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll @@ -11,14 +11,15 @@ newtype Declarations4Query = TCompatibleDeclarationFunctionDefinedQuery() or TIdentifierWithExternalLinkageOneDefinitionQuery() -predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleId) { +predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleId, string category) { query = // `Query` instance for the `functionTypesNotInPrototypeForm` query Declarations4Package::functionTypesNotInPrototypeFormQuery() and queryId = // `@id` for the `functionTypesNotInPrototypeForm` query "c/misra/function-types-not-in-prototype-form" and - ruleId = "RULE-8-2" + ruleId = "RULE-8-2" and + category = "required" or query = // `Query` instance for the `declarationsOfAnObjectSameNameAndType` query @@ -26,7 +27,8 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI queryId = // `@id` for the `declarationsOfAnObjectSameNameAndType` query "c/misra/declarations-of-an-object-same-name-and-type" and - ruleId = "RULE-8-3" + ruleId = "RULE-8-3" and + category = "required" or query = // `Query` instance for the `declarationsOfAFunctionSameNameAndType` query @@ -34,7 +36,8 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI queryId = // `@id` for the `declarationsOfAFunctionSameNameAndType` query "c/misra/declarations-of-a-function-same-name-and-type" and - ruleId = "RULE-8-3" + ruleId = "RULE-8-3" and + category = "required" or query = // `Query` instance for the `compatibleDeclarationObjectDefined` query @@ -42,7 +45,8 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI queryId = // `@id` for the `compatibleDeclarationObjectDefined` query "c/misra/compatible-declaration-object-defined" and - ruleId = "RULE-8-4" + ruleId = "RULE-8-4" and + category = "required" or query = // `Query` instance for the `compatibleDeclarationFunctionDefined` query @@ -50,7 +54,8 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI queryId = // `@id` for the `compatibleDeclarationFunctionDefined` query "c/misra/compatible-declaration-function-defined" and - ruleId = "RULE-8-4" + ruleId = "RULE-8-4" and + category = "required" or query = // `Query` instance for the `identifierWithExternalLinkageOneDefinition` query @@ -58,7 +63,8 @@ predicate isDeclarations4QueryMetadata(Query query, string queryId, string ruleI queryId = // `@id` for the `identifierWithExternalLinkageOneDefinition` query "c/misra/identifier-with-external-linkage-one-definition" and - ruleId = "RULE-8-6" + ruleId = "RULE-8-6" and + category = "required" } module Declarations4Package { diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 1f218804ea..004719516c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -93,7 +93,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isDeclarations1QueryMetadata(query, queryId, ruleId, category) or isDeclarations2QueryMetadata(query, queryId, ruleId, category) or isDeclarations3QueryMetadata(query, queryId, ruleId, category) or - isDeclarations4QueryMetadata(query, queryId, ruleId) or + isDeclarations4QueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isIO1QueryMetadata(query, queryId, ruleId, category) or isIO2QueryMetadata(query, queryId, ruleId, category) or