Skip to content

Commit 7f4ebd4

Browse files
committed
Add query files for Banned4
1 parent 4ae8c1d commit 7f4ebd4

File tree

9 files changed

+198
-0
lines changed

9 files changed

+198
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype Banned4Query = TUnnamedNamespacesInHeaderFilesQuery()
7+
8+
predicate isBanned4QueryMetadata(Query query, string queryId, string ruleId, string category) {
9+
query =
10+
// `Query` instance for the `unnamedNamespacesInHeaderFiles` query
11+
Banned4Package::unnamedNamespacesInHeaderFilesQuery() and
12+
queryId =
13+
// `@id` for the `unnamedNamespacesInHeaderFiles` query
14+
"cpp/misra/unnamed-namespaces-in-header-files" and
15+
ruleId = "RULE-10-3-1" and
16+
category = "advisory"
17+
}
18+
19+
module Banned4Package {
20+
Query unnamedNamespacesInHeaderFilesQuery() {
21+
//autogenerate `Query` type
22+
result =
23+
// `Query` type for `unnamedNamespacesInHeaderFiles` query
24+
TQueryCPP(TBanned4PackageQuery(TUnnamedNamespacesInHeaderFilesQuery()))
25+
}
26+
}

cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Allocations
66
import Banned1
77
import Banned2
88
import Banned3
9+
import Banned4
910
import BannedAPIs
1011
import BannedFunctions
1112
import BannedLibraries
@@ -96,6 +97,7 @@ newtype TCPPQuery =
9697
TBanned1PackageQuery(Banned1Query q) or
9798
TBanned2PackageQuery(Banned2Query q) or
9899
TBanned3PackageQuery(Banned3Query q) or
100+
TBanned4PackageQuery(Banned4Query q) or
99101
TBannedAPIsPackageQuery(BannedAPIsQuery q) or
100102
TBannedFunctionsPackageQuery(BannedFunctionsQuery q) or
101103
TBannedLibrariesPackageQuery(BannedLibrariesQuery q) or
@@ -186,6 +188,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
186188
isBanned1QueryMetadata(query, queryId, ruleId, category) or
187189
isBanned2QueryMetadata(query, queryId, ruleId, category) or
188190
isBanned3QueryMetadata(query, queryId, ruleId, category) or
191+
isBanned4QueryMetadata(query, queryId, ruleId, category) or
189192
isBannedAPIsQueryMetadata(query, queryId, ruleId, category) or
190193
isBannedFunctionsQueryMetadata(query, queryId, ruleId, category) or
191194
isBannedLibrariesQueryMetadata(query, queryId, ruleId, category) or
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @id cpp/misra/unnamed-namespaces-in-header-files
3+
* @name RULE-10-3-1: There should be no unnamed namespaces in header files
4+
* @description Anonymous namespaces in header files create separate entities in each translation
5+
* unit, which may not be consistent with developer expectations.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-10-3-1
10+
* scope/single-translation-unit
11+
* correctness
12+
* external/misra/enforcement/decidable
13+
* external/misra/obligation/advisory
14+
*/
15+
16+
import cpp
17+
import codingstandards.cpp.misra
18+
19+
from NamespaceDeclarationEntry namespaceDeclarationEntry, HeaderFile headerFile
20+
where
21+
not isExcluded(namespaceDeclarationEntry, Banned4Package::unnamedNamespacesInHeaderFilesQuery()) and
22+
namespaceDeclarationEntry.getNamespace().isAnonymous() and
23+
headerFile = namespaceDeclarationEntry.getFile()
24+
select namespaceDeclarationEntry, "Anonymous namespace declared in header file $@.", headerFile,
25+
headerFile.getBaseName()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.hpp:5:1:5:9 | (unnamed namespace) | Anonymous namespace declared in header file $@. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
2+
| test.hpp:32:1:32:9 | Outer::(unnamed namespace) | Anonymous namespace declared in header file $@. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
3+
| test.hpp:41:1:41:9 | (unnamed namespace) | Anonymous namespace declared in header file $@. | test.hpp:0:0:0:0 | test.hpp | test.hpp |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-10-3-1/UnnamedNamespacesInHeaderFiles.ql
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <cstdint>
2+
3+
/* ========== 1. Non-compliant: anonymous namespace in header ========== */
4+
5+
namespace { // NON_COMPLIANT: anonymous namespace in header file
6+
inline std::int32_t x = 0;
7+
8+
void helper() {}
9+
10+
class InternalClass {};
11+
} // namespace
12+
13+
/* ========== 2. Compliant: named namespace in header ========== */
14+
15+
namespace MyNamespace { // COMPLIANT: named namespace
16+
inline std::int32_t y = 0;
17+
18+
void publicHelper();
19+
20+
class PublicClass {};
21+
} // namespace MyNamespace
22+
23+
/* ========== 3. Compliant: no namespace ========== */
24+
25+
inline std::int32_t z = 0; // COMPLIANT: no anonymous namespace
26+
27+
void declaredFunction();
28+
29+
/* ========== 4. Non-compliant: nested anonymous namespace ========== */
30+
31+
namespace Outer {
32+
namespace { // NON_COMPLIANT: anonymous namespace in header file
33+
inline std::int32_t nested = 0;
34+
}
35+
} // namespace Outer
36+
37+
/* ========== 5. Non-compliant: anonymous namespace with extern "C" ==========
38+
*/
39+
40+
extern "C" {
41+
namespace { // NON_COMPLIANT: anonymous namespace in header file
42+
inline std::int32_t cStyleVar = 0;
43+
}
44+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "test.hpp"
2+
3+
/*
4+
* This file demonstrates that anonymous namespace variables
5+
* in headers create translation-unit-local copies.
6+
*/
7+
8+
void setValues() {
9+
x = 42; // Sets file1.cpp's copy of x
10+
MyNamespace::y = 42; // Sets the shared y
11+
z = 42; // Sets the shared z
12+
Outer::nested = 42; // Sets file1.cpp's copy of nested
13+
}
14+
15+
std::int32_t getX_File1() {
16+
return x; // Returns file1.cpp's copy of x
17+
}
18+
19+
std::int32_t getNested_File1() {
20+
return Outer::nested; // Returns file1.cpp's copy of nested
21+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "test.hpp"
2+
#include <cassert>
3+
4+
/*
5+
* This file demonstrates the mismatch in expectations.
6+
* After calling setValues() from file1.cpp:
7+
* - x is 0 here (different copy)
8+
* - MyNamespace::y is 42 (shared)
9+
* - z is 42 (shared)
10+
* - Outer::nested is 0 here (different copy)
11+
*/
12+
13+
extern void setValues();
14+
extern std::int32_t getX_File1();
15+
extern std::int32_t getNested_File1();
16+
17+
void checkMismatch() {
18+
setValues();
19+
20+
/*
21+
* These demonstrate the MISMATCH - anonymous namespace creates separate
22+
* copies.
23+
*/
24+
assert(x == 0); // file2.cpp's x was never set!
25+
assert(getX_File1() == 42); // file1.cpp's x was set
26+
27+
assert(Outer::nested == 0); // file2.cpp's nested was never set!
28+
assert(getNested_File1() == 42); // file1.cpp's nested was set
29+
30+
/* These demonstrate EXPECTED behavior - named namespace and global are shared
31+
*/
32+
assert(MyNamespace::y == 42); // Shared across TUs
33+
assert(z == 42); // Shared across TUs
34+
}
35+
36+
/* ========== 6. Compliant: anonymous namespace in .cpp file ========== */
37+
38+
namespace { // COMPLIANT: anonymous namespace in source file is fine
39+
std::int32_t localVar = 0;
40+
41+
void localHelper() {
42+
localVar = 100; // Only visible in this TU, as expected
43+
}
44+
} // namespace
45+
46+
int main() {
47+
checkMismatch();
48+
localHelper();
49+
return 0;
50+
}

rule_packages/cpp/Banned4.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"MISRA-C++-2023": {
3+
"RULE-10-3-1": {
4+
"properties": {
5+
"enforcement": "decidable",
6+
"obligation": "advisory"
7+
},
8+
"queries": [
9+
{
10+
"description": "Anonymous namespaces in header files create separate entities in each translation unit, which may not be consistent with developer expectations.",
11+
"kind": "problem",
12+
"name": "There should be no unnamed namespaces in header files",
13+
"precision": "very-high",
14+
"severity": "error",
15+
"short_name": "UnnamedNamespacesInHeaderFiles",
16+
"tags": [
17+
"scope/single-translation-unit",
18+
"correctness"
19+
]
20+
}
21+
],
22+
"title": "There should be no unnamed namespaces in header files"
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)