int parseIdentifier (CodeDocument::Iterator& source) noexcept { int tokenLength = 0; String::CharPointerType::CharType possibleIdentifier [100]; String::CharPointerType possible (possibleIdentifier); while (isIdentifierBody (source.peekNextChar())) { const juce_wchar c = source.nextChar(); if (tokenLength < 20) possible.write (c); ++tokenLength; } if (tokenLength > 1 && tokenLength <= 16) { possible.writeNull(); if (isReservedKeyword (String::CharPointerType (possibleIdentifier), tokenLength)) return CPlusPlusCodeTokeniser::tokenType_builtInKeyword; } return CPlusPlusCodeTokeniser::tokenType_identifier; }
static int parseIdentifier (CodeDocument::Iterator& source) throw() { static const tchar* keywords2Char[] = { T("if"), T("do"), T("or"), 0 }; static const tchar* keywords3Char[] = { T("for"), T("int"), T("new"), T("try"), T("xor"), T("and"), T("asm"), T("not"), 0 }; static const tchar* keywords4Char[] = { T("bool"), T("void"), T("this"), T("true"), T("long"), T("else"), T("char"), T("enum"), T("case"), T("goto"), T("auto"), 0 }; static const tchar* keywords5Char[] = { T("while"), T("bitor"), T("break"), T("catch"), T("class"), T("compl"), T("const"), T("false"), T("float"), T("short"), T("throw"), T("union"), T("using"), T("or_eq"), 0 }; static const tchar* keywords6Char[] = { T("return"), T("struct"), T("and_eq"), T("bitand"), T("delete"), T("double"), T("extern"), T("friend"), T("inline"), T("not_eq"), T("public"), T("sizeof"), T("static"), T("signed"), T("switch"), T("typeid"), T("wchar_t"), T("xor_eq"), 0}; static const tchar* keywordsOther[] = { T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"), T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"), T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"), T("@private"), T("@property"), T("@protected"), T("@class"), 0 }; int tokenLength = 0; tchar possibleIdentifier [19]; while (isIdentifierBody (source.peekNextChar())) { const tchar c = source.nextChar(); if (tokenLength < numElementsInArray (possibleIdentifier) - 1) possibleIdentifier [tokenLength] = c; ++tokenLength; } if (tokenLength > 1 && tokenLength <= 16) { possibleIdentifier [tokenLength] = 0; const tchar** k; switch (tokenLength) { case 2: k = keywords2Char; break; case 3: k = keywords3Char; break; case 4: k = keywords4Char; break; case 5: k = keywords5Char; break; case 6: k = keywords6Char; break; default: k = keywordsOther; break; } int i = 0; while (k[i] != 0) { if (k[i][0] == possibleIdentifier[0] && CharacterFunctions::compare (k[i], possibleIdentifier) == 0) return CPlusPlusCodeTokeniser::tokenType_builtInKeyword; ++i; } } return CPlusPlusCodeTokeniser::tokenType_identifier; }
void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl"); SourceLocation Loc = TL.getBeginLoc(); if (Loc.isInvalid() || Loc.isMacroID()) return; // Look through qualification. if (auto QualLoc = TL.getAs<QualifiedTypeLoc>()) TL = QualLoc.getUnqualifiedLoc(); auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>(); if (!BuiltinLoc) return; Token Tok = getTokenAtLoc(Loc, Result, *IdentTable); // Ensure the location actually points to one of the builting integral type // names we're interested in. Otherwise, we might be getting this match from // implicit code (e.g. an implicit assignment operator of a class containing // an array of non-POD types). if (!Tok.isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned, tok::kw_signed)) return; bool IsSigned; unsigned Width; const TargetInfo &TargetInfo = Result.Context->getTargetInfo(); // Look for uses of short, long, long long and their unsigned versions. switch (BuiltinLoc.getTypePtr()->getKind()) { case BuiltinType::Short: Width = TargetInfo.getShortWidth(); IsSigned = true; break; case BuiltinType::Long: Width = TargetInfo.getLongWidth(); IsSigned = true; break; case BuiltinType::LongLong: Width = TargetInfo.getLongLongWidth(); IsSigned = true; break; case BuiltinType::UShort: Width = TargetInfo.getShortWidth(); IsSigned = false; break; case BuiltinType::ULong: Width = TargetInfo.getLongWidth(); IsSigned = false; break; case BuiltinType::ULongLong: Width = TargetInfo.getLongLongWidth(); IsSigned = false; break; default: return; } // We allow "unsigned short port" as that's reasonably common and required by // the sockets API. const StringRef Port = "unsigned short port"; const char *Data = Result.SourceManager->getCharacterData(Loc); if (!std::strncmp(Data, Port.data(), Port.size()) && !isIdentifierBody(Data[Port.size()])) return; std::string Replacement = ((IsSigned ? SignedTypePrefix : UnsignedTypePrefix) + Twine(Width) + TypeSuffix) .str(); // We don't add a fix-it as changing the type can easily break code, // e.g. when a function requires a 'long' argument on all platforms. // QualTypes are printed with implicit quotes. diag(Loc, "consider replacing %0 with '%1'") << BuiltinLoc.getType() << Replacement; }