misra; implement rule 8.10

This commit is contained in:
Daniel Marjamäki 2021-07-18 21:18:07 +02:00
parent f6efd8c6be
commit d1fe34e167
8 changed files with 58 additions and 14 deletions

View File

@ -471,7 +471,8 @@ class Function:
tokenDef Token in function definition
isVirtual Is this function is virtual
isImplicitlyVirtual Is this function is virtual this in the base classes
isStatic Is this function is static
isInlineKeyword Is inline keyword used
isStatic Is this function static?
"""
Id = None
@ -485,6 +486,7 @@ class Function:
type = None
isVirtual = None
isImplicitlyVirtual = None
isInlineKeyword = None
isStatic = None
nestedIn = None
@ -494,12 +496,10 @@ class Function:
self.tokenDefId = element.get('tokenDef')
self.name = element.get('name')
self.type = element.get('type')
isVirtual = element.get('isVirtual')
self.isVirtual = (isVirtual and isVirtual == 'true')
isImplicitlyVirtual = element.get('isImplicitlyVirtual')
self.isImplicitlyVirtual = (isImplicitlyVirtual and isImplicitlyVirtual == 'true')
isStatic = element.get('isStatic')
self.isStatic = (isStatic and isStatic == 'true')
self.isImplicitlyVirtual = element.get('isImplicitlyVirtual', 'false') == 'true'
self.isVirtual = element.get('isVirtual', 'false') == 'true'
self.isInlineKeyword = element.get('isInlineKeyword', 'false') == 'true'
self.isStatic = element.get('isStatic', 'false') == 'true'
self.nestedIn = nestedIn
self.argument = {}
@ -507,7 +507,7 @@ class Function:
def __repr__(self):
attrs = ["Id", "tokenId", "tokenDefId", "name", "type", "isVirtual",
"isImplicitlyVirtual", "isStatic", "argumentId"]
"isImplicitlyVirtual", "isInlineKeyword", "isStatic", "argumentId"]
return "{}({})".format(
"Function",
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))

View File

@ -1880,6 +1880,11 @@ class MisraChecker:
self.reportError(var.nameToken, 8, 9)
def misra_8_10(self, cfg):
for func in cfg.functions:
if func.isInlineKeyword and not func.isStatic:
self.reportError(func.tokenDef, 8, 10)
def misra_8_11(self, data):
for var in data.variables:
if var.isExtern and simpleMatch(var.nameToken.next, '[ ]') and var.nameToken.scope.type == 'Global':
@ -3602,6 +3607,7 @@ class MisraChecker:
self.executeCheck(807, self.misra_8_7, dumpfile, cfg)
self.executeCheck(808, self.misra_8_8, cfg)
self.executeCheck(809, self.misra_8_9, cfg)
self.executeCheck(810, self.misra_8_10, cfg)
self.executeCheck(811, self.misra_8_11, cfg)
self.executeCheck(812, self.misra_8_12, cfg)
if cfgNumber == 0:

View File

@ -379,6 +379,8 @@ extern int32_t misra_8_8; // 8.8 8.4
static int32_t misra_8_9_i; // 8.9
static int32_t misra_8_9_foo(void) { return misra_8_9_i++; }
inline int32_t misra_8_10_value(void) { return 123; } // 8.10 8.4
extern int a811[]; // 8.11 8.4
enum misra_8_12_a { misra_a1 = 1, misra_a2 = 2, misra_a3, misra_a4 = 3 }; //8.12

View File

@ -2268,10 +2268,16 @@ Function::Function(const Token *tokenDef, const std::string &clangType)
const Token *Function::setFlags(const Token *tok1, const Scope *scope)
{
if (tok1->isInline())
isInlineKeyword(true);
// look for end of previous statement
while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) {
tok1 = tok1->previous();
if (tok1->isInline())
isInlineKeyword(true);
// extern function
if (tok1->str() == "extern") {
isExtern(true);
@ -3721,6 +3727,8 @@ void SymbolDatabase::printXml(std::ostream &out) const
else if (function->isImplicitlyVirtual())
out << " isImplicitlyVirtual=\"true\"";
}
if (function->isInlineKeyword())
out << " isInlineKeyword=\"true\"";
if (function->isStatic())
out << " isStatic=\"true\"";
if (function->argCount() == 0U)

View File

@ -722,6 +722,7 @@ class CPPCHECKLIB Function {
fIsVolatile = (1 << 20), ///< @brief is volatile
fHasTrailingReturnType = (1 << 21), ///< @brief has trailing return type
fIsEscapeFunction = (1 << 22), ///< @brief Function throws or exits
fIsInlineKeyword = (1 << 23), ///< @brief Function has "inline" keyword
};
/**
@ -878,6 +879,9 @@ public:
void hasBody(bool state) {
setFlag(fHasBody, state);
}
bool isInlineKeyword() const {
return getFlag(fIsInlineKeyword);
}
bool isEscapeFunction() const {
return getFlag(fIsEscapeFunction);
@ -991,6 +995,9 @@ private:
void hasTrailingReturnType(bool state) {
return setFlag(fHasTrailingReturnType, state);
}
void isInlineKeyword(bool state) {
setFlag(fIsInlineKeyword, state);
}
const Token *setFlags(const Token *tok1, const Scope *scope);
};

View File

@ -634,6 +634,13 @@ public:
setFlag(fIsImplicitInt, b);
}
bool isInline() const {
return getFlag(fIsInline);
}
void isInline(bool b) {
setFlag(fIsInline, b);
}
bool isBitfield() const {
return mImpl->mBits > 0;
}
@ -1197,7 +1204,7 @@ private:
Token *mPrevious;
Token *mLink;
enum : uint32_t {
enum : uint64_t {
fIsUnsigned = (1 << 0),
fIsSigned = (1 << 1),
fIsPointerCompare = (1 << 2),
@ -1229,12 +1236,13 @@ private:
fExternC = (1 << 28),
fIsSplitVarDeclComma = (1 << 29), // set to true when variable declarations are split up ('int a,b;' => 'int a; int b;')
fIsSplitVarDeclEq = (1 << 30), // set to true when variable declaration with initialization is split up ('int a=5;' => 'int a; a=5;')
fIsImplicitInt = (1U << 31) // Is "int" token implicitly added?
fIsImplicitInt = (1U << 31), // Is "int" token implicitly added?
fIsInline = (1ULL << 32) // Is this a inline type
};
Token::Type mTokType;
unsigned int mFlags;
uint64_t mFlags;
TokenImpl *mImpl;
@ -1243,7 +1251,7 @@ private:
* @param flag_ flag to get state of
* @return true if flag set or false in flag not set
*/
bool getFlag(unsigned int flag_) const {
bool getFlag(uint64_t flag_) const {
return ((mFlags & flag_) != 0);
}
@ -1252,7 +1260,7 @@ private:
* @param flag_ flag to set state
* @param state_ new state of flag
*/
void setFlag(unsigned int flag_, bool state_) {
void setFlag(uint64_t flag_, bool state_) {
mFlags = state_ ? mFlags | flag_ : mFlags & ~flag_;
}

View File

@ -11174,9 +11174,12 @@ void Tokenizer::simplifyKeyword()
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (keywords.find(tok->str()) != keywords.end()) {
// Don't remove struct members
if (!Token::simpleMatch(tok->previous(), "."))
if (!Token::simpleMatch(tok->previous(), ".")) {
if (tok->str().find("inline") != std::string::npos && Token::Match(tok->next(), "%name%"))
tok->next()->isInline(true);
tok->deleteThis(); // Simplify..
}
}
if (isC() || mSettings->standards.cpp == Standards::CPP03) {
if (tok->str() == "auto")

View File

@ -247,6 +247,8 @@ private:
TEST_CASE(functionImplicitlyVirtual);
TEST_CASE(functionIsInlineKeyword);
TEST_CASE(functionStatic);
TEST_CASE(functionReturnsReference); // Function::returnsReference
@ -2464,6 +2466,14 @@ private:
ASSERT_EQUALS(true, function && function->isImplicitlyVirtual(false));
}
void functionIsInlineKeyword() {
GET_SYMBOL_DB("inline void fs() {}");
(void)db;
const Function *func = db->scopeList.back().function;
ASSERT(func);
ASSERT(func->isInlineKeyword());
}
void functionStatic() {
GET_SYMBOL_DB("static void fs() { }");
(void)db;