@@ -2077,6 +2077,45 @@ bool TokenList::validateToken(const Token* tok) const
20772077 return false ;
20782078}
20792079
2080+ /* * Return whether tok is the "{" that starts an enumerator list */
2081+ static bool isEnumStart (const Token* tok)
2082+ {
2083+ if (!Token::simpleMatch (tok, " {" ))
2084+ return false ;
2085+ tok = tok->previous ();
2086+ while (tok && (!tok->isKeyword () || Token::isStandardType (tok->str ())) && Token::Match (tok, " %name%|::|:" ))
2087+ tok = tok->previous ();
2088+ if (Token::simpleMatch (tok, " class" ))
2089+ tok = tok->previous ();
2090+ return Token::simpleMatch (tok, " enum" );
2091+ }
2092+
2093+ // Collect the tokens that are enumerator names being declared in some enum's member list,
2094+ // e.g. the HANDLE in "enum E { HANDLE, ... };". Each enum body is scanned once, jumping over
2095+ // nested brackets in constant-expressions via link(), so the total cost is bounded by the
2096+ // combined size of all enum bodies -- not by unrelated code elsewhere in the file.
2097+ static std::unordered_set<const Token*> findEnumeratorNames (const Token* front)
2098+ {
2099+ std::unordered_set<const Token*> result;
2100+ for (const Token* tok = front; tok; tok = tok->next ()) {
2101+ if (!isEnumStart (tok))
2102+ continue ;
2103+ const Token* const bodyEnd = tok->link ();
2104+ for (const Token* nameTok = tok->next (); nameTok && nameTok != bodyEnd;) {
2105+ if (nameTok->isName ())
2106+ result.insert (nameTok);
2107+ while (nameTok != bodyEnd && nameTok->str () != " ," ) {
2108+ if (Token::Match (nameTok, " (|[|{" ))
2109+ nameTok = nameTok->link ();
2110+ nameTok = nameTok->next ();
2111+ }
2112+ if (nameTok != bodyEnd) // skip the ","
2113+ nameTok = nameTok->next ();
2114+ }
2115+ }
2116+ return result;
2117+ }
2118+
20802119void TokenList::simplifyPlatformTypes ()
20812120{
20822121 const bool isCPP11 = isCPP () && (mSettings .standards .cpp >= Standards::CPP11 );
@@ -2143,6 +2182,7 @@ void TokenList::simplifyPlatformTypes()
21432182 }
21442183
21452184 const std::string platform_type (mSettings .platform .toString ());
2185+ const std::unordered_set<const Token*> enumeratorNames = findEnumeratorNames (front ());
21462186
21472187 for (Token *tok = front (); tok; tok = tok->next ()) {
21482188 if (tok->tokType () != Token::eType && tok->tokType () != Token::eName)
@@ -2151,6 +2191,9 @@ void TokenList::simplifyPlatformTypes()
21512191 const Library::PlatformType * const platformtype = mSettings .library .platform_type (tok->str (), platform_type);
21522192
21532193 if (platformtype) {
2194+ if (enumeratorNames.count (tok) != 0 ) // don't replace an enumerator's name, e.g. HANDLE in "enum E { HANDLE, ... };"
2195+ continue ;
2196+
21542197 // check for namespace
21552198 if (tok->strAt (-1 ) == " ::" ) {
21562199 const Token * tok1 = tok->tokAt (-2 );
0 commit comments