From c23f1a203de87e372d029941a16658fc37179687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 3 Jun 2024 21:00:46 +0200 Subject: [PATCH 1/3] Fix #12807 (dump file: provide alignas expressions) --- lib/token.h | 22 ++++++++++++++++++++++ lib/tokenize.cpp | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/lib/token.h b/lib/token.h index 2f054d96946..3ff331b57d1 100644 --- a/lib/token.h +++ b/lib/token.h @@ -122,6 +122,9 @@ struct TokenImpl { }; CppcheckAttributes* mCppcheckAttributes{}; + // alignas expressions + std::string mAttributeAlignas; + // For memoization, to speed up parsing of huge arrays #8897 enum class Cpp11init { UNKNOWN, CPP11INIT, NOINIT } mCpp11init = Cpp11init::UNKNOWN; @@ -545,6 +548,25 @@ class CPPCHECKLIB Token { void isAttributeMaybeUnused(const bool value) { setFlag(fIsAttributeMaybeUnused, value); } + std::vector getAttributeAlignas() const { + if (mImpl->mAttributeAlignas.empty()) + return {}; + const std::string::size_type pos = mImpl->mAttributeAlignas.find('\n'); + if (pos == std::string::npos) + return {mImpl->mAttributeAlignas}; + return {mImpl->mAttributeAlignas.substr(0, pos), + mImpl->mAttributeAlignas.substr(pos + 1)}; + } + bool hasAttributeAlignas() const { + return !mImpl->mAttributeAlignas.empty(); + } + void addAttributeAlignas(const std::string& a) { + if (mImpl->mAttributeAlignas.empty()) + mImpl->mAttributeAlignas = a; + else if (a != mImpl->mAttributeAlignas && mImpl->mAttributeAlignas.find('\n') == std::string::npos) + // mismatching alignas expressions, add both + mImpl->mAttributeAlignas += '\n' + a; + } void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) { mImpl->setCppcheckAttribute(type, value); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 2ca6189c205..11448f50b18 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6044,6 +6044,12 @@ void Tokenizer::dump(std::ostream &out) const outs += " isAttributeMaybeUnused=\"true\""; if (tok->isAttributeUnused()) outs += " isAttributeUnused=\"true\""; + if (tok->hasAttributeAlignas()) { + const std::vector& a = tok->getAttributeAlignas(); + outs += " alignas=\"" + ErrorLogger::toxml(a[0]) + "\""; + if (a.size() > 1) + outs += " alignas2=\"" + ErrorLogger::toxml(a[1]) + "\""; + } if (tok->link()) { outs += " link=\""; outs += id_string(tok->link()); @@ -9353,6 +9359,21 @@ void Tokenizer::simplifyCPPAttribute() } } else { if (Token::simpleMatch(tok, "alignas (")) { + Token* atok = nullptr; + if (Token::Match(tok->previous(), "%name%")) + atok = tok->previous(); + else { + atok = tok; + while (isCPPAttribute(atok) || isAlignAttribute(atok)) + atok = skipCPPOrAlignAttribute(atok)->next(); + } + if (atok) { + std::string a; + for (const Token* t = tok->tokAt(2); t && t->str() != ")"; t = t->next()) + a += " " + t->str(); + if (a.size() > 1) + atok->addAttributeAlignas(a.substr(1)); + } // alignment requirements could be checked here } } From bbb50993590bda65f78467c90d6df431284a02cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 4 Jun 2024 12:01:40 +0200 Subject: [PATCH 2/3] refactor --- lib/token.h | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/token.h b/lib/token.h index 3ff331b57d1..82b463ae586 100644 --- a/lib/token.h +++ b/lib/token.h @@ -123,7 +123,13 @@ struct TokenImpl { CppcheckAttributes* mCppcheckAttributes{}; // alignas expressions - std::string mAttributeAlignas; + std::unique_ptr> mAttributeAlignas; + void addAttributeAlignas(const std::string& a) { + if (!mAttributeAlignas) + mAttributeAlignas = std::unique_ptr>(new std::vector()); + if (std::find(mAttributeAlignas->cbegin(), mAttributeAlignas->cend(), a) == mAttributeAlignas->cend()) + mAttributeAlignas->push_back(a); + } // For memoization, to speed up parsing of huge arrays #8897 enum class Cpp11init { UNKNOWN, CPP11INIT, NOINIT } mCpp11init = Cpp11init::UNKNOWN; @@ -549,23 +555,13 @@ class CPPCHECKLIB Token { setFlag(fIsAttributeMaybeUnused, value); } std::vector getAttributeAlignas() const { - if (mImpl->mAttributeAlignas.empty()) - return {}; - const std::string::size_type pos = mImpl->mAttributeAlignas.find('\n'); - if (pos == std::string::npos) - return {mImpl->mAttributeAlignas}; - return {mImpl->mAttributeAlignas.substr(0, pos), - mImpl->mAttributeAlignas.substr(pos + 1)}; + return !mImpl->mAttributeAlignas ? std::vector() : *mImpl->mAttributeAlignas; } bool hasAttributeAlignas() const { - return !mImpl->mAttributeAlignas.empty(); + return !!mImpl->mAttributeAlignas; } void addAttributeAlignas(const std::string& a) { - if (mImpl->mAttributeAlignas.empty()) - mImpl->mAttributeAlignas = a; - else if (a != mImpl->mAttributeAlignas && mImpl->mAttributeAlignas.find('\n') == std::string::npos) - // mismatching alignas expressions, add both - mImpl->mAttributeAlignas += '\n' + a; + mImpl->addAttributeAlignas(a); } void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) { mImpl->setCppcheckAttribute(type, value); From 6df8a7f15bce51d1fe71dd54aa2cc2fc4c16ca0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 4 Jun 2024 14:18:13 +0200 Subject: [PATCH 3/3] add test, fix review comments --- lib/token.h | 2 +- lib/tokenize.cpp | 1 + test/testtokenize.cpp | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/token.h b/lib/token.h index 82b463ae586..4e8efeeec71 100644 --- a/lib/token.h +++ b/lib/token.h @@ -555,7 +555,7 @@ class CPPCHECKLIB Token { setFlag(fIsAttributeMaybeUnused, value); } std::vector getAttributeAlignas() const { - return !mImpl->mAttributeAlignas ? std::vector() : *mImpl->mAttributeAlignas; + return mImpl->mAttributeAlignas ? *mImpl->mAttributeAlignas : std::vector(); } bool hasAttributeAlignas() const { return !!mImpl->mAttributeAlignas; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 11448f50b18..91c1b6626c4 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6048,6 +6048,7 @@ void Tokenizer::dump(std::ostream &out) const const std::vector& a = tok->getAttributeAlignas(); outs += " alignas=\"" + ErrorLogger::toxml(a[0]) + "\""; if (a.size() > 1) + // we could write all alignas expressions but currently we only need 2 outs += " alignas2=\"" + ErrorLogger::toxml(a[1]) + "\""; } if (tok->link()) { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index d530d416692..c01be008480 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -439,6 +439,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(removeAlignas1); TEST_CASE(removeAlignas2); // Do not remove alignof in the same way + TEST_CASE(dumpAlignas); TEST_CASE(simplifyCoroutines); @@ -7850,6 +7851,17 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } + void dumpAlignas() { + Settings settings; + SimpleTokenizer tokenizer(settings, *this); + tokenizer.tokenize("int alignas(8) alignas(16) x;", false); + ASSERT(Token::simpleMatch(tokenizer.tokens(), "int x ;")); + std::ostringstream ostr; + tokenizer.dump(ostr); + const std::string dump = ostr.str(); + ASSERT(dump.find(" alignas=\"8\" alignas2=\"16\"") != std::string::npos); + } + void simplifyCoroutines() { const Settings settings = settingsBuilder().cpp(Standards::CPP20).build();