Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@
"Language1",
"Language2",
"Language3",
"Linkage1",
"Linkage2",
"Literals",
"Loops",
"Macros",
Expand Down
4 changes: 4 additions & 0 deletions change_notes/2026-01-26-improve-queries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- `A3-1-1` - `ViolationsOfOneDefinitionRule.ql`:
- The query previously would incorrectly allow cases where something was defined with `extern` and did not use the defined external linkage library to find external linkage. This change may result in the query finding more results. Additionally a typo has been fixed in the alert message which will cause the old alerts for this query to now show up as new ones.
- `RULE-6-0-2`, `A3-1-4` - `ExternalLinkageArrayWithoutExplicitSizeMisra.ql`, `ExternalLinkageArrayWithoutExplicitSizeAutosar.ql`:
- The queries listed now find flexible member arrays in structs, as those do not have an explicit size.
67 changes: 5 additions & 62 deletions cpp/autosar/src/rules/A3-1-1/ViolationsOfOneDefinitionRule.ql
Original file line number Diff line number Diff line change
Expand Up @@ -20,67 +20,10 @@

import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.AcceptableHeader
import codingstandards.cpp.rules.violationsofonedefinitionrule.ViolationsOfOneDefinitionRule

predicate isInline(Function decl) {
exists(Specifier spec |
spec = decl.getASpecifier() and
(
spec.hasName("inline") or
spec.hasName("constexpr")
)
)
class ViolationsOfOneDefinitionRuleQuery extends ViolationsOfOneDefinitionRuleSharedQuery {
ViolationsOfOneDefinitionRuleQuery() {
this = IncludesPackage::violationsOfOneDefinitionRuleQuery()
}
}

predicate isExtern(FunctionDeclarationEntry decl) {
exists(string spec |
spec = decl.getASpecifier() and
spec = "extern"
)
}

from DeclarationEntry decl, string case, string name
where
(
//a non-inline/non-extern function defined in a header
exists(FunctionDeclarationEntry fn |
fn.isDefinition() and
not (
isInline(fn.getDeclaration())
or
isExtern(fn)
or
//any (defined) templates do not violate the ODR
fn.isFromUninstantiatedTemplate(_)
or
fn.isFromTemplateInstantiation(_) and
//except for specializations, those do violate ODR
not fn.isSpecialization()
or
fn.getDeclaration().isStatic()
) and
decl = fn and
case = "function"
)
or
//an non-const object defined in a header
exists(GlobalOrNamespaceVariable object |
object.hasDefinition() and
not (
object.isConstexpr()
or
object.isConst()
or
object.isStatic()
) and
decl = object.getDefinition() and
case = "object"
)
) and
not decl.getDeclaration().getNamespace().isAnonymous() and
decl.getFile() instanceof AcceptableHeader and
not isExcluded(decl, IncludesPackage::violationsOfOneDefinitionRuleQuery()) and
name = decl.getName()
select decl,
"Header file $@ contains " + case + " " + name + " that lead to One Defintion Rule violation.",
decl.getFile(), decl.getFile().getBaseName()

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cpp/common/test/rules/violationsofonedefinitionrule/ViolationsOfOneDefinitionRule.ql
26 changes: 0 additions & 26 deletions cpp/autosar/test/rules/A3-1-1/test.hpp

This file was deleted.

3 changes: 3 additions & 0 deletions cpp/common/src/codingstandards/cpp/Scope.qll
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@ predicate hidesStrict(UserVariable v1, UserVariable v2) {
predicate hasNamespaceScope(Declaration decl) {
// getNamespace always returns a namespace (e.g. the global namespace).
exists(Namespace n | namespacembrs(unresolveElement(n), underlyingElement(decl)))
or
decl.isTopLevel() and
not namespacembrs(_, decl)
}

/** Holds if `decl` has class scope. */
Expand Down
44 changes: 44 additions & 0 deletions cpp/common/src/codingstandards/cpp/exclusions/cpp/Linkage2.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
import cpp
import RuleMetadata
import codingstandards.cpp.exclusions.RuleMetadata

newtype Linkage2Query =
TViolationsOfOneDefinitionRuleMisraQuery() or
TInternalLinkageSpecifiedAppropriatelyQuery()

predicate isLinkage2QueryMetadata(Query query, string queryId, string ruleId, string category) {
query =
// `Query` instance for the `violationsOfOneDefinitionRuleMisra` query
Linkage2Package::violationsOfOneDefinitionRuleMisraQuery() and
queryId =
// `@id` for the `violationsOfOneDefinitionRuleMisra` query
"cpp/misra/violations-of-one-definition-rule-misra" and
ruleId = "RULE-6-2-4" and
category = "required"
or
query =
// `Query` instance for the `internalLinkageSpecifiedAppropriately` query
Linkage2Package::internalLinkageSpecifiedAppropriatelyQuery() and
queryId =
// `@id` for the `internalLinkageSpecifiedAppropriately` query
"cpp/misra/internal-linkage-specified-appropriately" and
ruleId = "RULE-6-5-2" and
category = "advisory"
}

module Linkage2Package {
Query violationsOfOneDefinitionRuleMisraQuery() {
//autogenerate `Query` type
result =
// `Query` type for `violationsOfOneDefinitionRuleMisra` query
TQueryCPP(TLinkage2PackageQuery(TViolationsOfOneDefinitionRuleMisraQuery()))
}

Query internalLinkageSpecifiedAppropriatelyQuery() {
//autogenerate `Query` type
result =
// `Query` type for `internalLinkageSpecifiedAppropriately` query
TQueryCPP(TLinkage2PackageQuery(TInternalLinkageSpecifiedAppropriatelyQuery()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Invariants
import Iterators
import Lambdas
import Linkage1
import Linkage2
import Literals
import Loops
import Macros
Expand Down Expand Up @@ -98,6 +99,7 @@ newtype TCPPQuery =
TIteratorsPackageQuery(IteratorsQuery q) or
TLambdasPackageQuery(LambdasQuery q) or
TLinkage1PackageQuery(Linkage1Query q) or
TLinkage2PackageQuery(Linkage2Query q) or
TLiteralsPackageQuery(LiteralsQuery q) or
TLoopsPackageQuery(LoopsQuery q) or
TMacrosPackageQuery(MacrosQuery q) or
Expand Down Expand Up @@ -161,6 +163,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isIteratorsQueryMetadata(query, queryId, ruleId, category) or
isLambdasQueryMetadata(query, queryId, ruleId, category) or
isLinkage1QueryMetadata(query, queryId, ruleId, category) or
isLinkage2QueryMetadata(query, queryId, ruleId, category) or
isLiteralsQueryMetadata(query, queryId, ruleId, category) or
isLoopsQueryMetadata(query, queryId, ruleId, category) or
isMacrosQueryMetadata(query, queryId, ruleId, category) or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Provides a library with a `problems` predicate for the following issue:
* Placing the definitions of functions or objects that are non-inline and have
* external linkage can lead to violations of the ODR and can lead to undefined
* behaviour.
*/

import cpp
import codingstandards.cpp.Customizations
import codingstandards.cpp.Exclusions
import codingstandards.cpp.AcceptableHeader
import codingstandards.cpp.Linkage

predicate isInline(Function decl) {
exists(Specifier spec |
spec = decl.getASpecifier() and
(
spec.hasName("inline") or
spec.hasName("constexpr")
)
)
}

abstract class ViolationsOfOneDefinitionRuleSharedQuery extends Query { }

Query getQuery() { result instanceof ViolationsOfOneDefinitionRuleSharedQuery }

query predicate problems(DeclarationEntry decl, string message, File declFile, string secondmessage) {
exists(string case |
not isExcluded(decl, getQuery()) and
declFile = decl.getFile() and
secondmessage = decl.getFile().getBaseName() and
message =
"Header file $@ contains " + case + " " + decl.getName() +
" that lead to One Definition Rule violation." and
hasExternalLinkage(decl.getDeclaration()) and
(
//a non-inline/non-extern function defined in a header
exists(FunctionDeclarationEntry fn |
fn.isDefinition() and
not (
isInline(fn.getDeclaration())
or
//any (defined) templates do not violate the ODR
fn.isFromUninstantiatedTemplate(_)
or
fn.isFromTemplateInstantiation(_) and
//except for specializations, those do violate ODR
not fn.isSpecialization()
or
//static/nonstatic member functions should still not be defined (so do not exclude here)
fn.getDeclaration().isStatic() and not fn.getFunction() instanceof MemberFunction
) and
decl = fn and
case = "function"
)
or
//an non-const object defined in a header
exists(Variable object |
not (
object.isConstexpr()
or
object.isConst()
or
object.isStatic()
) and
decl = object.getDefinition() and
case = "object"
)
) and
not decl.getDeclaration().getNamespace().isAnonymous() and
decl.getFile() instanceof AcceptableHeader
)
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
| test.cpp:19:14:19:15 | declaration of e1 | The declared array 'e1' with external linkage doesn't specify the size explicitly. |
| test.cpp:27:20:27:38 | declaration of flexibleArrayMember | The declared array 'flexibleArrayMember' with external linkage doesn't specify the size explicitly. |
| test.cpp:28:14:28:33 | declaration of flexibleArrayMember2 | The declared array 'flexibleArrayMember2' with external linkage doesn't specify the size explicitly. |
| test.hpp:2:13:2:26 | declaration of header_and_cpp | The declared array 'header_and_cpp' with external linkage doesn't specify the size explicitly. |
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ struct s {
// Structs must have at least one non-flexible array member.
int foo;

// static data members have external linkage - but not currently detected in
// our external linkage lib - also FAMs are expected to be detected
// specifically in RULE-18-7
static const int flexibleArrayMember[]; // NON_COMPLIANT[FALSE_NEGATIVE]
static int flexibleArrayMember2[]; // NON_COMPLIANT[FALSE_NEGATIVE]
// FAMs are expected to be detected specifically in RULE-18-7
static const int flexibleArrayMember[]; // NON_COMPLIANT
static int flexibleArrayMember2[]; // NON_COMPLIANT
};

// test.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
| test.hpp:3:6:3:7 | definition of f1 | Header file $@ contains function f1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
| test.hpp:8:5:8:5 | definition of i | Header file $@ contains object i that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
| test.hpp:9:12:9:13 | definition of i1 | Header file $@ contains object i1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
| test.hpp:23:5:23:8 | definition of m | Header file $@ contains function m that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
| test.hpp:25:5:25:9 | definition of m1 | Header file $@ contains function m1 that lead to One Definition Rule violation. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// GENERATED FILE - DO NOT MODIFY
import codingstandards.cpp.rules.violationsofonedefinitionrule.ViolationsOfOneDefinitionRule

class TestFileQuery extends ViolationsOfOneDefinitionRuleSharedQuery, TestQuery { }
24 changes: 24 additions & 0 deletions cpp/common/test/rules/violationsofonedefinitionrule/test.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
void f(); // COMPLIANT

void f1() {} // NON_COMPLIANT
inline void f2() {} // COMPLIANT

template <typename T> void f3(T){}; // COMPLIANT - implicitly inline

int i; // NON_COMPLIANT
extern int i1 = 1; // NON_COMPLIANT

constexpr auto i2{1}; // COMPLIANT - not external linkage

struct S {
int i; // COMPLIANT - no linkage
inline static const int i1{1}; // COMPLIANT - inline
};

class C {
static int m(); // COMPLIANT
int m1(); // COMPLIANT
};

int C::m() {} // NON_COMPLIANT
int C::m1() {} // NON_COMPLIANT
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @id cpp/misra/violations-of-one-definition-rule-misra
* @name RULE-6-2-4: A header file shall not contain definitions of functions or objects that are non-inline and have external linkage
* @description Placing the definitions of functions or objects that are non-inline and have
* external linkage can lead to violations of the ODR and can lead to undefined
* behaviour.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/misra/id/rule-6-2-4
* correctness
* maintainability
* readability
* scope/single-translation-unit
* external/misra/enforcement/decidable
* external/misra/obligation/required
*/

import cpp
import codingstandards.cpp.misra
import codingstandards.cpp.rules.violationsofonedefinitionrule.ViolationsOfOneDefinitionRule

class ViolationsOfOneDefinitionRuleMisraQuery extends ViolationsOfOneDefinitionRuleSharedQuery {
ViolationsOfOneDefinitionRuleMisraQuery() {
this = Linkage2Package::violationsOfOneDefinitionRuleMisraQuery()
}
}
Loading
Loading