Skip to content

Commit fc8c244

Browse files
authored
CI: Add selfcheck using Cppcheck Premium. Activates Misra C++ 2008 and Cert C++ 2016 checkers. (#5623)
1 parent 83ac6bf commit fc8c244

11 files changed

Lines changed: 268 additions & 30 deletions
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
name: cppcheck-premium
3+
4+
on:
5+
push:
6+
branches:
7+
- 'main'
8+
- 'releases/**'
9+
tags:
10+
- '2.*'
11+
pull_request:
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
18+
build:
19+
runs-on: ubuntu-22.04 # run on the latest image only
20+
21+
env:
22+
PREMIUM_VERSION: devdrop-20231105
23+
24+
steps:
25+
- uses: actions/checkout@v3
26+
27+
- name: Download cppcheckpremium
28+
run: |
29+
wget https://files.cppchecksolutions.com/cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
30+
tar xzf cppcheckpremium-${{ env.PREMIUM_VERSION }}-amd64.tar.gz
31+
32+
- name: Generate a license file
33+
run: |
34+
echo cppcheck > cppcheck.lic
35+
echo 231231 >> cppcheck.lic
36+
echo 80000 >> cppcheck.lic
37+
echo 57e08c39523ab54d >> cppcheck.lic
38+
echo path:lib >> cppcheck.lic
39+
40+
- name: Check
41+
run: |
42+
cppcheckpremium-${{ env.PREMIUM_VERSION }}/premiumaddon --check-loc-license cppcheck.lic > cppcheck-premium-loc
43+
cppcheckpremium-${{ env.PREMIUM_VERSION }}/cppcheck -j$(nproc) -D__GNUC__ -D__CPPCHECK__ --suppressions-list=cppcheckpremium-suppressions --platform=unix64 --enable=style --premium=misra-c++-2008 --premium=cert-c++-2016 --error-exitcode=1 lib

cppcheckpremium-suppressions

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
2+
# False positives
3+
premium-misra-cpp-2008-5-17-1
4+
premium-misra-cpp-2008-5-0-6
5+
premium-misra-cpp-2008-7-2-1
6+
premium-misra-cpp-2008-3-3-2
7+
8+
# open source warnings are handled by the selfcheck.yml
9+
noExplicitConstructor
10+
postfixOperator
11+
shadowFunction
12+
useStlAlgorithm
13+
14+
# we need to declare reserved identifier _CRTDBG_MAP_ALLOC
15+
premium-cert-dcl51-cpp
16+
17+
# TODO: Is there unsafe allocations, in case of exceptions) in cppcheck
18+
premium-cert-err58-cpp
19+
20+
# we have global objects
21+
premium-cert-err58-cpp
22+
23+
# TODO: Exception objects must be nothrow copy constructible.
24+
premium-cert-err60-cpp
25+
26+
# TODO should we throw Token?
27+
premium-cert-err61-cpp
28+
29+
# TODO: Detect errors when converting a string to a number. The library function 'atoi()' shall not be used.
30+
premium-cert-err62-cpp
31+
32+
# TODO: Can we reduce some const_cast?
33+
premium-cert-exp55-cpp
34+
35+
# sometimes a void function does not have side effects
36+
premium-misra-cpp-2008-0-1-8
37+
38+
# unused arguments, misra rules are too strict
39+
premium-misra-cpp-2008-0-1-11
40+
premium-misra-cpp-2008-0-1-12
41+
42+
# we sometimes don't care about return value from functions
43+
premium-misra-cpp-2008-0-1-7
44+
45+
# TODO: can we prevent commented out code?
46+
premium-misra-cpp-2008-2-7-2
47+
premium-misra-cpp-2008-2-7-3
48+
49+
# NA
50+
premium-misra-cpp-2008-2-10-1
51+
52+
# objects of a class often has the lowercase name of the class.
53+
premium-misra-cpp-2008-2-10-4
54+
55+
# flag |= ..
56+
premium-misra-cpp-2008-4-5-1
57+
58+
# Token/Variable flags are enum constants and we use those in bitwise operations by intention.
59+
premium-misra-cpp-2008-4-5-2
60+
61+
# intentional addition of char to string: const std::string end(':' + cfg + ':' + Path::simplifyPath(sourcefile));
62+
premium-misra-cpp-2008-4-5-3
63+
64+
# too strict operator precedence warnings
65+
premium-misra-cpp-2008-5-0-2
66+
67+
# we are less strict about signedness. what bug is there here: unsigned int col = 0
68+
premium-misra-cpp-2008-5-0-4
69+
70+
# intentional integral-to-float conversion
71+
premium-misra-cpp-2008-5-0-5
72+
73+
# intentional addition of char literal: c = 'a' + (temp - 10);
74+
premium-misra-cpp-2008-5-0-11
75+
76+
# conversion of char-to-int is intentional sometimes
77+
premium-misra-cpp-2008-5-0-12
78+
79+
# pointer-to-bool conversion is common
80+
premium-misra-cpp-2008-5-0-14
81+
82+
# pointer arithmetic is not uncommon in cppcheck code
83+
premium-misra-cpp-2008-5-0-15
84+
85+
# it's only a problem if signed expression is negative
86+
premium-misra-cpp-2008-5-0-21
87+
88+
# Intentional safe operands of &&: return !stdValue.empty() && str == getCPP();
89+
premium-misra-cpp-2008-5-2-1
90+
91+
# const_cast performs intentional const casting
92+
premium-misra-cpp-2008-5-2-5
93+
94+
# safe code: const char *next = static_cast<const char*>(std::memchr(pattern, ' ', pattern_len));
95+
premium-misra-cpp-2008-5-2-8
96+
97+
# we intentionally cast pointer to integer when creating id for dumpfile
98+
premium-misra-cpp-2008-5-2-9
99+
100+
# we intentionally mix increment with other operators in expressions
101+
premium-misra-cpp-2008-5-2-10
102+
103+
# intentional array-to-pointer decay
104+
premium-misra-cpp-2008-5-2-12
105+
106+
# we write !pointer by intention
107+
premium-misra-cpp-2008-5-3-1
108+
109+
# for (;;)
110+
premium-misra-cpp-2008-6-2-3
111+
112+
# it's not a bug to not put default at the end of a switch body
113+
premium-misra-cpp-2008-6-4-6
114+
115+
# looping linked list => not well formed for loop
116+
premium-misra-cpp-2008-6-5-1
117+
premium-misra-cpp-2008-6-5-2
118+
premium-misra-cpp-2008-6-5-3
119+
premium-misra-cpp-2008-6-5-4
120+
premium-misra-cpp-2008-6-5-5
121+
premium-misra-cpp-2008-6-5-6
122+
123+
# we like early returns
124+
premium-misra-cpp-2008-6-6-3
125+
premium-misra-cpp-2008-6-6-4
126+
premium-misra-cpp-2008-6-6-5
127+
128+
# we have local functions by intention
129+
premium-misra-cpp-2008-7-3-1
130+
131+
# intentional: return reference from method to non-const reference parameter
132+
premium-misra-cpp-2008-7-5-3
133+
134+
# intentional declaration of multiple variables
135+
premium-misra-cpp-2008-8-0-1
136+
137+
# we intentionally don't use & before function names
138+
premium-misra-cpp-2008-8-4-4
139+
140+
# cppcheck does not care about this enumerator rule
141+
premium-misra-cpp-2008-8-5-3
142+
143+
# TODO Fix these
144+
premium-misra-cpp-2008-9-3-1
145+
146+
# we use unions by intention sometimes
147+
premium-misra-cpp-2008-9-5-1
148+
149+
# overridden methods is safe
150+
premium-misra-cpp-2008-10-3-1
151+
152+
# some classes have public members by intention
153+
premium-misra-cpp-2008-11-0-1
154+
155+
# rule should not apply to deleted copy assignment operator
156+
premium-misra-cpp-2008-12-8-2
157+
158+
# TODO: this can be fixed by refactoring the code.
159+
premium-misra-cpp-2008-14-6-2
160+
161+
# function specializations: TODO check if we should refactor
162+
premium-misra-cpp-2008-14-8-2
163+
164+
# we use preprocessor when it makes sense
165+
premium-misra-cpp-2008-16-0-1
166+
premium-misra-cpp-2008-16-2-1
167+
premium-misra-cpp-2008-16-2-2
168+
premium-misra-cpp-2008-16-3-2
169+
170+
# TODO do we need to catch string conversion errors (using atoi)?
171+
premium-misra-cpp-2008-18-0-2
172+
173+
# what standard alternative is there for std::getenv
174+
premium-misra-cpp-2008-18-0-3
175+
176+
# <ctime> is used by intention
177+
premium-misra-cpp-2008-18-0-4
178+
179+
# code is safe. we use std::strcmp by intention
180+
premium-misra-cpp-2008-18-0-5
181+
182+
# we do avoid using new/delete
183+
premium-misra-cpp-2008-18-4-1
184+
185+
# <cstdio> is used by intention
186+
premium-misra-cpp-2008-27-0-1

lib/analyzer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ struct Analyzer {
3333
struct Action {
3434

3535
Action() = default;
36+
Action(const Action&) = default;
37+
Action& operator=(const Action& rhs) = default;
3638

3739
template<class T,
3840
REQUIRES("T must be convertible to unsigned int", std::is_convertible<T, unsigned int> ),

lib/astutils.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,7 +2241,7 @@ bool isScopeBracket(const Token* tok)
22412241
}
22422242

22432243
template<class T, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )>
2244-
T* getTokenArgumentFunctionImpl(T* tok, int& argn)
2244+
static T* getTokenArgumentFunctionImpl(T* tok, int& argn)
22452245
{
22462246
argn = -1;
22472247
{
@@ -2892,13 +2892,13 @@ const Token* findThisChanged(const Token* start, const Token* end, int indirect,
28922892
}
28932893

28942894
template<class Find>
2895-
const Token* findExpressionChangedImpl(const Token* expr,
2896-
const Token* start,
2897-
const Token* end,
2898-
const Settings* settings,
2899-
bool cpp,
2900-
int depth,
2901-
Find find)
2895+
static const Token* findExpressionChangedImpl(const Token* expr,
2896+
const Token* start,
2897+
const Token* end,
2898+
const Settings* settings,
2899+
bool cpp,
2900+
int depth,
2901+
Find find)
29022902
{
29032903
if (depth < 0)
29042904
return start;
@@ -3095,7 +3095,7 @@ const Token *findLambdaStartToken(const Token *last)
30953095
}
30963096

30973097
template<class T>
3098-
T* findLambdaEndTokenGeneric(T* first)
3098+
static T* findLambdaEndTokenGeneric(T* first)
30993099
{
31003100
auto maybeLambda = [](T* tok) -> bool {
31013101
while (Token::Match(tok, "*|%name%|::|>")) {

lib/checkcondition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ static bool checkFloatRelation(const std::string &op, const double value1, const
995995
}
996996

997997
template<class T>
998-
T getvalue3(const T value1, const T value2)
998+
static T getvalue3(const T value1, const T value2)
999999
{
10001000
const T min = std::min(value1, value2);
10011001
if (min== std::numeric_limits<T>::max())

lib/checkers.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19-
#pragma once
19+
#ifndef checkersH
20+
#define checkersH
2021

2122
#include <map>
2223
#include <string>
@@ -44,4 +45,4 @@ namespace checkers {
4445
extern CPPCHECKLIB const std::map<std::string, std::string> misraRuleSeverity;
4546
}
4647

47-
48+
#endif

lib/checkersreport.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19-
#pragma once
19+
#ifndef checkersReportH
20+
#define checkersReportH
2021

2122
#include "config.h"
2223

@@ -44,4 +45,4 @@ class CPPCHECKLIB CheckersReport {
4445
int mAllCheckersCount = 0;
4546
};
4647

47-
48+
#endif

lib/symboldatabase.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,10 @@ Variable& Variable::operator=(const Variable &var)
21782178
if (this == &var)
21792179
return *this;
21802180

2181+
ValueType* vt = nullptr;
2182+
if (var.mValueType)
2183+
vt = new ValueType(*var.mValueType);
2184+
21812185
mNameToken = var.mNameToken;
21822186
mTypeStartToken = var.mTypeStartToken;
21832187
mTypeEndToken = var.mTypeEndToken;
@@ -2188,9 +2192,7 @@ Variable& Variable::operator=(const Variable &var)
21882192
mScope = var.mScope;
21892193
mDimensions = var.mDimensions;
21902194
delete mValueType;
2191-
mValueType = nullptr;
2192-
if (var.mValueType)
2193-
mValueType = new ValueType(*var.mValueType);
2195+
mValueType = vt;
21942196

21952197
return *this;
21962198
}
@@ -2344,9 +2346,9 @@ void Variable::setValueType(const ValueType &valueType)
23442346
if (declType && !declType->next()->valueType())
23452347
return;
23462348
}
2349+
ValueType* vt = new ValueType(valueType);
23472350
delete mValueType;
2348-
mValueType = nullptr;
2349-
mValueType = new ValueType(valueType);
2351+
mValueType = vt;
23502352
if ((mValueType->pointer > 0) && (!isArray() || Token::Match(mNameToken->previous(), "( * %name% )")))
23512353
setFlag(fIsPointer, true);
23522354
setFlag(fIsConst, mValueType->constness & (1U << mValueType->pointer));
@@ -6359,7 +6361,7 @@ static void setAutoTokenProperties(Token * const autoTok)
63596361
autoTok->isStandardType(true);
63606362
}
63616363

6362-
bool isContainerYieldElement(Library::Container::Yield yield)
6364+
static bool isContainerYieldElement(Library::Container::Yield yield)
63636365
{
63646366
return yield == Library::Container::Yield::ITEM || yield == Library::Container::Yield::AT_INDEX ||
63656367
yield == Library::Container::Yield::BUFFER || yield == Library::Container::Yield::BUFFER_NT;

lib/tokenize.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,6 @@ namespace {
618618
std::pair<Token*, Token*> mRangeType;
619619
std::pair<Token*, Token*> mRangeTypeQualifiers;
620620
std::pair<Token*, Token*> mRangeAfterVar;
621-
std::string mTypedefName; // Name of typedef type
622621
Token* mNameToken{nullptr};
623622
bool mFail = false;
624623
bool mReplaceFailed = false;
@@ -643,7 +642,6 @@ namespace {
643642
if (Token::Match(nameToken, "%name% ;")) {
644643
mRangeType = rangeBefore;
645644
mRangeTypeQualifiers = rangeQualifiers;
646-
mTypedefName = nameToken->str();
647645
Token* typeName = rangeBefore.second->previous();
648646
if (typeName->isKeyword()) {
649647
(void)num;

0 commit comments

Comments
 (0)