diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3147f97957..97bc7c4800 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -206,6 +206,8 @@ "Declarations", "Declarations1", "Declarations2", + "Declarations3", + "Declarations4", "Exceptions1", "Exceptions2", "Expressions", diff --git a/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.expected new file mode 100644 index 0000000000..8ea6eca50e --- /dev/null +++ b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/IdentifierWithExternalLinkageOneDefinitionShared.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/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/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.c b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.c new file mode 100644 index 0000000000..a2e9eeff8d --- /dev/null +++ b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/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/common/test/rules/identifierwithexternallinkageonedefinitionshared/test1.c b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/test1.c new file mode 100644 index 0000000000..6882a55800 --- /dev/null +++ b/c/common/test/rules/identifierwithexternallinkageonedefinitionshared/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/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 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 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-2/FunctionTypesNotInPrototypeForm.ql b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql new file mode 100644 index 0000000000..62aade0c0c --- /dev/null +++ b/c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql @@ -0,0 +1,58 @@ +/** + * @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() } +} + +/* + * 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 + f instanceof InterestingIdentifiers and + ( + f.getAParameter() instanceof UnnamedParameter and + msg = "Function " + f + " declares parameter that is unnamed." + or + 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." + ) + ) +select f, msg 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..6803af9380 --- /dev/null +++ b/c/misra/src/rules/RULE-8-3/DeclarationsOfAFunctionSameNameAndType.ql @@ -0,0 +1,38 @@ +/** + * @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 codingstandards.cpp.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 + parameterTypesIncompatible(f1, f2) and + case = "parameter types" + or + //parameter name check + parameterNamesIncompatible(f1, f2) 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..03acda6dd7 --- /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 codingstandards.cpp.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/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/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql b/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql new file mode 100644 index 0000000000..2eb5028dba --- /dev/null +++ b/c/misra/src/rules/RULE-8-6/IdentifierWithExternalLinkageOneDefinition.ql @@ -0,0 +1,22 @@ +/** + * @id c/misra/identifier-with-external-linkage-one-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 + * @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.rules.identifierwithexternallinkageonedefinitionshared.IdentifierWithExternalLinkageOneDefinitionShared + +class IdentifierWithExternalLinkageShallHaveOneDefinitionQuery extends IdentifierWithExternalLinkageOneDefinitionSharedSharedQuery { + IdentifierWithExternalLinkageShallHaveOneDefinitionQuery() { + this = Declarations4Package::identifierWithExternalLinkageOneDefinitionQuery() + } +} 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..f33a53174e --- /dev/null +++ b/c/misra/test/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.expected @@ -0,0 +1,4 @@ +| test.c:3:6:3:7 | f1 | Function f1 declares parameter that is unnamed. | +| 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/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..c254a221d9 --- /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 +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/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/cpp/autosar/test/rules/M3-2-4/test.cpp b/c/misra/test/rules/RULE-8-3/test.c similarity index 100% rename from cpp/autosar/test/rules/M3-2-4/test.cpp rename to c/misra/test/rules/RULE-8-3/test.c 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..9153fafa97 --- /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 | 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. | 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/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/Compatible.qll b/cpp/common/src/codingstandards/cpp/Compatible.qll new file mode 100644 index 0000000000..12a53965fe --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/Compatible.qll @@ -0,0 +1,26 @@ +import cpp + +predicate typesCompatible(Type t1, Type t2) { + t1 = t2 + or + //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/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..348fd97309 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Declarations4.qll @@ -0,0 +1,112 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Declarations4Query = + TFunctionTypesNotInPrototypeFormQuery() or + TDeclarationsOfAnObjectSameNameAndTypeQuery() or + TDeclarationsOfAFunctionSameNameAndTypeQuery() or + TCompatibleDeclarationObjectDefinedQuery() or + TCompatibleDeclarationFunctionDefinedQuery() or + TIdentifierWithExternalLinkageOneDefinitionQuery() + +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" and + category = "required" + 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" and + category = "required" + 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" and + category = "required" + 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" and + category = "required" + 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" and + category = "required" + or + 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" and + category = "required" +} + +module Declarations4Package { + Query functionTypesNotInPrototypeFormQuery() { + //autogenerate `Query` type + result = + // `Query` type for `functionTypesNotInPrototypeForm` query + 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 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 = + // `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 11994dd9fd..004719516c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -15,6 +15,7 @@ import Contracts4 import Declarations1 import Declarations2 import Declarations3 +import Declarations4 import Expressions import IO1 import IO2 @@ -53,6 +54,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 @@ -91,6 +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, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isIO1QueryMetadata(query, queryId, ruleId, category) or isIO2QueryMetadata(query, queryId, ruleId, category) or 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/common/src/codingstandards/cpp/rules/notdistinctidentifier/NotDistinctIdentifier.qll b/cpp/common/src/codingstandards/cpp/rules/notdistinctidentifier/NotDistinctIdentifier.qll index 944168f0fe..2d6767f664 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 { } @@ -37,6 +16,8 @@ query predicate problems( ) { not isExcluded(d, getQuery()) and not isExcluded(d2, 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/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/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.cpp b/cpp/common/test/rules/identifierwithexternallinkageonedefinitionshared/test.cpp new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..bfd0b18328 --- /dev/null +++ b/rule_packages/c/Declarations4.json @@ -0,0 +1,119 @@ +{ + "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-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-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" + }, + "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 definition", + "precision": "high", + "severity": "error", + "short_name": "IdentifierWithExternalLinkageOneDefinition", + "shared_implementation_short_name": "IdentifierWithExternalLinkageOneDefinitionShared", + "tags": [ + "correctness" + ] + } + ], + "title": "An identifier with external linkage shall have exactly one external definition" + } + } +} \ No newline at end of file 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" ] diff --git a/rules.csv b/rules.csv index bb4456877e..1e299ae44c 100644 --- a/rules.csv +++ b/rules.csv @@ -647,11 +647,11 @@ 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-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-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,,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,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,