From 71dcef85b98dd5b863844dd2820d802de5a2d590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 4 Jun 2024 16:21:03 +0200 Subject: [PATCH] Fix #12807 (dump file: provide alignas expressions) (#6485) cherry pick b84bc8d4b93bf57f82db684e2731c64f94509c25 from main branch --- 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 11e815aae3a..ac50bbdc3f2 100644 --- a/lib/token.h +++ b/lib/token.h @@ -121,6 +121,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; @@ -533,6 +542,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 5c811e2d39b..840b3021c67 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6026,6 +6026,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()); @@ -9277,6 +9284,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 45ed4a20c1a..004058bf425 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -438,6 +438,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); @@ -7764,6 +7765,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();