From d1fe34e1677e63735e694152a5e863118e288d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 18 Jul 2021 21:18:07 +0200 Subject: [PATCH] misra; implement rule 8.10 --- addons/cppcheckdata.py | 16 ++++++++-------- addons/misra.py | 6 ++++++ addons/test/misra/misra-test.c | 2 ++ lib/symboldatabase.cpp | 8 ++++++++ lib/symboldatabase.h | 7 +++++++ lib/token.h | 18 +++++++++++++----- lib/tokenize.cpp | 5 ++++- test/testsymboldatabase.cpp | 10 ++++++++++ 8 files changed, 58 insertions(+), 14 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 540edf868..c583d7d57 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -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)) diff --git a/addons/misra.py b/addons/misra.py index 764c2e8ef..c03890a1f 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -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: diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 646f88b81..fc4001e46 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -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 diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 6d15983d2..14517d3d6 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 18f064533..5101d7325 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -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); }; diff --git a/lib/token.h b/lib/token.h index 751e1ae64..6667cb133 100644 --- a/lib/token.h +++ b/lib/token.h @@ -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_; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 443bde819..07dc51631 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -11174,8 +11174,11 @@ 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) { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 61fa1cc5c..a5401da65 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -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;