From b84bc8d4b93bf57f82db684e2731c64f94509c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 4 Jun 2024 15:50:53 +0200 Subject: [PATCH] Fix #12807 (dump file: provide alignas expressions) (#6483) --- lib/token.h | 18 ++++++++++++++++++ lib/tokenize.cpp | 22 ++++++++++++++++++++++ test/testtokenize.cpp | 12 ++++++++++++ 3 files changed, 52 insertions(+) diff --git a/lib/token.h b/lib/token.h index 2f054d96946..4e8efeeec71 100644 --- a/lib/token.h +++ b/lib/token.h @@ -122,6 +122,15 @@ struct TokenImpl { }; CppcheckAttributes* mCppcheckAttributes{}; + // alignas expressions + 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; @@ -545,6 +554,15 @@ class CPPCHECKLIB Token { void isAttributeMaybeUnused(const bool value) { setFlag(fIsAttributeMaybeUnused, value); } + std::vector getAttributeAlignas() const { + return mImpl->mAttributeAlignas ? *mImpl->mAttributeAlignas : std::vector(); + } + bool hasAttributeAlignas() const { + return !!mImpl->mAttributeAlignas; + } + void addAttributeAlignas(const std::string& a) { + mImpl->addAttributeAlignas(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 6f1618a527f..f0b056fa1e5 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6044,6 +6044,13 @@ 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) + // we could write all alignas expressions but currently we only need 2 + outs += " alignas2=\"" + ErrorLogger::toxml(a[1]) + "\""; + } if (tok->link()) { outs += " link=\""; outs += id_string(tok->link()); @@ -9353,6 +9360,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 } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 5e1322ba958..635886e5992 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();