| 9693 | } |
| 9694 | |
| 9695 | void Tokenizer::simplifyCPPAttribute() |
| 9696 | { |
| 9697 | // According to cppreference alignas is a c21 feature however the macro is often available when compiling c11 |
| 9698 | const bool hasAlignas = ((isCPP() && mSettings.standards.cpp >= Standards::CPP11) || (isC() && mSettings.standards.c >= Standards::C11)); |
| 9699 | const bool hasCppAttribute = ((isCPP() && mSettings.standards.cpp >= Standards::CPP11) || (isC() && mSettings.standards.c >= Standards::C23)); |
| 9700 | const bool hasMaybeUnused =((isCPP() && mSettings.standards.cpp >= Standards::CPP17) || (isC() && mSettings.standards.c >= Standards::C23)); |
| 9701 | const bool hasMaybeUnusedUnderscores = (isC() && mSettings.standards.c >= Standards::C23); |
| 9702 | |
| 9703 | if (!hasAlignas && !hasCppAttribute) |
| 9704 | return; |
| 9705 | |
| 9706 | for (Token *tok = list.front(); tok;) { |
| 9707 | if (!isCPPAttribute(tok) && !isAlignAttribute(tok)) { |
| 9708 | tok = tok->next(); |
| 9709 | continue; |
| 9710 | } |
| 9711 | if (isCPPAttribute(tok)) { |
| 9712 | if (!hasCppAttribute) { |
| 9713 | tok = skipCPPOrAlignAttribute(tok)->next(); |
| 9714 | continue; |
| 9715 | } |
| 9716 | if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) { |
| 9717 | Token * head = skipCPPOrAlignAttribute(tok)->next(); |
| 9718 | while (isCPPAttribute(head) || isAlignAttribute(head)) |
| 9719 | head = skipCPPOrAlignAttribute(head)->next(); |
| 9720 | while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type |
| 9721 | head = head->next(); |
| 9722 | if (head && head->str() == "(" && (TokenList::isFunctionHead(head, "{;") || Token::simpleMatch(head->link(), ") __attribute__"))) { |
| 9723 | head->previous()->isAttributeNoreturn(true); |
| 9724 | } |
| 9725 | } else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) { |
| 9726 | Token * head = skipCPPOrAlignAttribute(tok)->next(); |
| 9727 | while (isCPPAttribute(head) || isAlignAttribute(head)) |
| 9728 | head = skipCPPOrAlignAttribute(head)->next(); |
| 9729 | while (Token::Match(head, "%name%|::|*|&|<|>|,")) |
| 9730 | head = head->next(); |
| 9731 | if (head && head->str() == "(" && TokenList::isFunctionHead(head, "{;")) { |
| 9732 | head->previous()->isAttributeNodiscard(true); |
| 9733 | } |
| 9734 | } else if (Token::findsimplematch(tok->tokAt(2), "fallthrough", tok->link()) || Token::findsimplematch(tok->tokAt(2), "__fallthrough__", tok->link())) { |
| 9735 | Token * head = skipCPPOrAlignAttribute(tok)->next(); |
| 9736 | while (isCPPAttribute(head) || isAlignAttribute(head)) |
| 9737 | head = skipCPPOrAlignAttribute(head)->next(); |
| 9738 | while (head && head->str() == ";") // we have semicollon after the attribute which would be removed in 'removeRedundantSemicolons()' so we skip it |
| 9739 | head = head->next(); |
| 9740 | if (head) |
| 9741 | head->isAttributeFallthrough(true); |
| 9742 | } else if ((hasMaybeUnusedUnderscores && Token::findsimplematch(tok->tokAt(2), "__maybe_unused__", tok->link())) |
| 9743 | || (hasMaybeUnused && Token::findsimplematch(tok->tokAt(2), "maybe_unused", tok->link()))) { |
| 9744 | Token* head = skipCPPOrAlignAttribute(tok)->next(); |
| 9745 | while (isCPPAttribute(head) || isAlignAttribute(head)) |
| 9746 | head = skipCPPOrAlignAttribute(head)->next(); |
| 9747 | |
| 9748 | if (!head) |
| 9749 | syntaxError(tok); |
| 9750 | |
| 9751 | if (Token::simpleMatch(head, ";")) { |
| 9752 | Token *backTok = tok; |
nothing calls this directly
no test coverage detected