From 3f6f51e28231f65de9c2dd150a2d757b2162cfa3 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Fri, 8 Feb 2013 22:30:41 +0000 Subject: [PATCH] Excise from Clang (except clang-tblgen) in favor of CharInfo.h. Nearly all of these changes are one-to-one replacements; the few that aren't have to do with custom identifier validation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174768 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 1 - include/clang/Basic/CharInfo.h | 37 +++++++ include/clang/Lex/LiteralSupport.h | 6 +- lib/AST/Expr.cpp | 3 +- lib/AST/Stmt.cpp | 7 +- lib/AST/TemplateBase.cpp | 1 - lib/Analysis/CocoaConventions.cpp | 6 +- lib/Basic/Diagnostic.cpp | 14 +-- lib/Basic/IdentifierTable.cpp | 7 +- lib/Basic/TargetInfo.cpp | 6 +- lib/CodeGen/CodeGenModule.cpp | 3 +- lib/Driver/WindowsToolChain.cpp | 5 +- lib/Edit/EditedSource.cpp | 14 +-- lib/Frontend/LayoutOverrideSource.cpp | 17 +-- lib/Frontend/PrintPreprocessedOutput.cpp | 6 +- lib/Frontend/TextDiagnostic.cpp | 27 ++--- lib/Frontend/VerifyDiagnosticConsumer.cpp | 6 +- lib/Lex/HeaderMap.cpp | 1 - lib/Lex/LiteralSupport.cpp | 20 ++-- lib/Lex/ModuleMap.cpp | 18 +-- lib/Lex/PPDirectives.cpp | 2 +- lib/Parse/ParseDecl.cpp | 7 +- lib/Parse/ParseDeclCXX.cpp | 3 +- lib/Parse/ParseObjc.cpp | 3 +- lib/Rewrite/Frontend/RewriteModernObjC.cpp | 3 +- lib/Rewrite/Frontend/RewriteObjC.cpp | 3 +- lib/Sema/SemaChecking.cpp | 3 +- lib/Sema/SemaDeclAttr.cpp | 3 +- lib/Sema/SemaPseudoObject.cpp | 4 +- tools/driver/driver.cpp | 6 +- unittests/Basic/CharInfoTest.cpp | 122 +++++++++++++++++++++ 31 files changed, 258 insertions(+), 106 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 598f18937f..11fa6cf634 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -28,7 +28,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" -#include namespace clang { class APValue; diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h index f9b7b7311d..2522face65 100644 --- a/include/clang/Basic/CharInfo.h +++ b/include/clang/Basic/CharInfo.h @@ -10,6 +10,8 @@ #ifndef CLANG_BASIC_CHARINFO_H #define CLANG_BASIC_CHARINFO_H +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -157,6 +159,41 @@ LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) { CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0; } + +/// Converts the given ASCII character to its lowercase equivalent. +/// +/// If the character is not an uppercase character, it is returned as is. +LLVM_READONLY static inline char toLowercase(char c) { + if (isUppercase(c)) + return c + 'a' - 'A'; + return c; +} + +/// Converts the given ASCII character to its uppercase equivalent. +/// +/// If the character is not a lowercase character, it is returned as is. +LLVM_READONLY static inline char toUppercase(char c) { + if (isLowercase(c)) + return c + 'A' - 'a'; + return c; +} + + +/// Return true if this is a valid ASCII identifier. +/// +/// Note that this is a very simple check; it does not accept '$' or UCNs as +/// valid identifier characters. +LLVM_READONLY static inline bool isValidIdentifier(StringRef S) { + if (S.empty() || !isIdentifierHead(S[0])) + return false; + + for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) + if (!isIdentifierBody(*I)) + return false; + + return true; +} + } // end namespace clang #endif diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 7ffa328651..b1430cc805 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -15,13 +15,13 @@ #ifndef CLANG_LITERALSUPPORT_H #define CLANG_LITERALSUPPORT_H +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" -#include namespace clang { @@ -101,7 +101,7 @@ private: /// SkipHexDigits - Read and skip over any hex digits, up to End. /// Return a pointer to the first non-hex digit or End. const char *SkipHexDigits(const char *ptr) { - while (ptr != ThisTokEnd && isxdigit(*ptr)) + while (ptr != ThisTokEnd && isHexDigit(*ptr)) ptr++; return ptr; } @@ -117,7 +117,7 @@ private: /// SkipDigits - Read and skip over any digits, up to End. /// Return a pointer to the first non-hex digit or End. const char *SkipDigits(const char *ptr) { - while (ptr != ThisTokEnd && isdigit(*ptr)) + while (ptr != ThisTokEnd && isDigit(*ptr)) ptr++; return ptr; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 644fab9c8e..66980a9cd1 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -23,6 +23,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Lexer.h" @@ -844,7 +845,7 @@ void StringLiteral::outputString(raw_ostream &OS) const { assert(Char <= 0xff && "Characters above 0xff should already have been handled."); - if (isprint(Char)) + if (isPrintable(Char)) OS << (char)Char; else // Output anything hard as an octal escape. OS << '\\' diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 3214a2b23b..2ae5a1266c 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -19,6 +19,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/Type.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Token.h" #include "llvm/ADT/StringExtras.h" @@ -539,7 +540,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, // Handle %x4 and %x[foo] by capturing x as the modifier character. char Modifier = '\0'; - if (isalpha(EscapedChar)) { + if (isLetter(EscapedChar)) { if (CurPtr == StrEnd) { // Premature end. DiagOffs = CurPtr-StrStart-1; return diag::err_asm_invalid_escape; @@ -548,12 +549,12 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, EscapedChar = *CurPtr++; } - if (isdigit(EscapedChar)) { + if (isDigit(EscapedChar)) { // %n - Assembler operand n unsigned N = 0; --CurPtr; - while (CurPtr != StrEnd && isdigit(*CurPtr)) + while (CurPtr != StrEnd && isDigit(*CurPtr)) N = N*10 + ((*CurPtr++)-'0'); unsigned NumOperands = diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index f5dda30dea..6519340c87 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -25,7 +25,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include -#include using namespace clang; diff --git a/lib/Analysis/CocoaConventions.cpp b/lib/Analysis/CocoaConventions.cpp index ac22671c53..0db3cac58b 100644 --- a/lib/Analysis/CocoaConventions.cpp +++ b/lib/Analysis/CocoaConventions.cpp @@ -15,9 +15,9 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Type.h" +#include "clang/Basic/CharInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" -#include using namespace clang; using namespace ento; @@ -106,7 +106,7 @@ bool coreFoundation::followsCreateRule(const FunctionDecl *fn) { char ch = *it; if (ch == 'C' || ch == 'c') { // Make sure this isn't something like 'recreate' or 'Scopy'. - if (ch == 'c' && it != start && isalpha(*(it - 1))) + if (ch == 'c' && it != start && isLetter(*(it - 1))) continue; ++it; @@ -131,7 +131,7 @@ bool coreFoundation::followsCreateRule(const FunctionDecl *fn) { continue; } - if (it == endI || !islower(*it)) + if (it == endI || !isLowercase(*it)) return true; // If we matched a lowercase character, it isn't the end of the diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 6627ad62f3..2b448058a0 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/IdentifierTable.h" @@ -19,7 +20,6 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/raw_ostream.h" -#include using namespace clang; @@ -457,8 +457,8 @@ static const char *ScanFormat(const char *I, const char *E, char Target) { // Escaped characters get implicitly skipped here. // Format specifier. - if (!isdigit(*I) && !ispunct(*I)) { - for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ; + if (!isDigit(*I) && !isPunctuation(*I)) { + for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ; if (I == E) break; if (*I == '{') Depth++; @@ -682,7 +682,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, OutStr.append(DiagStr, StrEnd); DiagStr = StrEnd; continue; - } else if (ispunct(DiagStr[1])) { + } else if (isPunctuation(DiagStr[1])) { OutStr.push_back(DiagStr[1]); // %% -> %. DiagStr += 2; continue; @@ -700,7 +700,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, unsigned ModifierLen = 0, ArgumentLen = 0; // Check to see if we have a modifier. If so eat it. - if (!isdigit(DiagStr[0])) { + if (!isDigit(DiagStr[0])) { Modifier = DiagStr; while (DiagStr[0] == '-' || (DiagStr[0] >= 'a' && DiagStr[0] <= 'z')) @@ -719,7 +719,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, } } - assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); + assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic"); unsigned ArgNo = *DiagStr++ - '0'; // Only used for type diffing. @@ -727,7 +727,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo); if (ModifierIs(Modifier, ModifierLen, "diff")) { - assert(*DiagStr == ',' && isdigit(*(DiagStr + 1)) && + assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) && "Invalid format for diff modifier"); ++DiagStr; // Comma. ArgNo2 = *DiagStr++ - '0'; diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index ecaaf036b0..b943472f33 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -13,13 +13,13 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include #include using namespace clang; @@ -404,9 +404,8 @@ std::string Selector::getAsString() const { /// given "word", which is assumed to end in a lowercase letter. static bool startsWithWord(StringRef name, StringRef word) { if (name.size() < word.size()) return false; - return ((name.size() == word.size() || - !islower(name[word.size()])) - && name.startswith(word)); + return ((name.size() == word.size() || !isLowercase(name[word.size()])) && + name.startswith(word)); } ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) { diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index fe68a9df6a..70ea2351ec 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -13,11 +13,11 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" -#include #include using namespace clang; @@ -223,7 +223,7 @@ bool TargetInfo::isValidGCCRegisterName(StringRef Name) const { getGCCRegNames(Names, NumNames); // If we have a number it maps to an entry in the register name array. - if (isdigit(Name[0])) { + if (isDigit(Name[0])) { int n; if (!Name.getAsInteger(0, n)) return n >= 0 && (unsigned)n < NumNames; @@ -279,7 +279,7 @@ TargetInfo::getNormalizedGCCRegisterName(StringRef Name) const { getGCCRegNames(Names, NumNames); // First, check if we have a number. - if (isdigit(Name[0])) { + if (isDigit(Name[0])) { int n; if (!Name.getAsInteger(0, n)) { assert(n >= 0 && (unsigned)n < NumNames && diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 91f22b1cd6..ff2656548e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -30,6 +30,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" @@ -2936,7 +2937,7 @@ llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid, const char *Uuidstr = Uuid.data(); for (int i = 0; i < 36; ++i) { if (i == 8 || i == 13 || i == 18 || i == 23) assert(Uuidstr[i] == '-'); - else assert(isxdigit(Uuidstr[i])); + else assert(isHexDigit(Uuidstr[i])); } llvm::APInt Field0(32, StringRef(Uuidstr , 8), 16); diff --git a/lib/Driver/WindowsToolChain.cpp b/lib/Driver/WindowsToolChain.cpp index 323765adb0..f640b17611 100644 --- a/lib/Driver/WindowsToolChain.cpp +++ b/lib/Driver/WindowsToolChain.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "ToolChains.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Version.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" @@ -158,12 +159,12 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; index++) { const char *sp = keyName; - while (*sp && !isdigit(*sp)) + while (*sp && !isDigit(*sp)) sp++; if (!*sp) continue; const char *ep = sp + 1; - while (*ep && (isdigit(*ep) || (*ep == '.'))) + while (*ep && (isDigit(*ep) || (*ep == '.'))) ep++; char numBuf[32]; strncpy(numBuf, sp, sizeof(numBuf) - 1); diff --git a/lib/Edit/EditedSource.cpp b/lib/Edit/EditedSource.cpp index 002776759f..dd99ca9280 100644 --- a/lib/Edit/EditedSource.cpp +++ b/lib/Edit/EditedSource.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "clang/Edit/EditedSource.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Edit/Commit.h" #include "clang/Edit/EditsReceiver.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" -#include using namespace clang; using namespace edit; @@ -240,16 +240,12 @@ bool EditedSource::commit(const Commit &commit) { return true; } -static inline bool isIdentifierChar(char c, const LangOptions &LangOpts) { - return std::isalnum(c) || c == '_' || (c == '$' && LangOpts.DollarIdents); -} - // \brief Returns true if it is ok to make the two given characters adjacent. static bool canBeJoined(char left, char right, const LangOptions &LangOpts) { - // FIXME: Should use the Lexer to make sure we don't allow stuff like + // FIXME: Should use TokenConcatenation to make sure we don't allow stuff like // making two '<' adjacent. - return !(isIdentifierChar(left, LangOpts) && - isIdentifierChar(right, LangOpts)); + return !(Lexer::isIdentifierBodyChar(left, LangOpts) && + Lexer::isIdentifierBodyChar(right, LangOpts)); } /// \brief Returns true if it is ok to eliminate the trailing whitespace between @@ -258,7 +254,7 @@ static bool canRemoveWhitespace(char left, char beforeWSpace, char right, const LangOptions &LangOpts) { if (!canBeJoined(left, right, LangOpts)) return false; - if (std::isspace(left) || std::isspace(right)) + if (isWhitespace(left) || isWhitespace(right)) return true; if (canBeJoined(beforeWSpace, right, LangOpts)) return false; // the whitespace was intentional, keep it. diff --git a/lib/Frontend/LayoutOverrideSource.cpp b/lib/Frontend/LayoutOverrideSource.cpp index 9309661972..924a64068f 100644 --- a/lib/Frontend/LayoutOverrideSource.cpp +++ b/lib/Frontend/LayoutOverrideSource.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/LayoutOverrideSource.h" #include "clang/AST/Decl.h" +#include "clang/Basic/CharInfo.h" #include "llvm/Support/raw_ostream.h" -#include #include #include @@ -17,10 +17,11 @@ using namespace clang; /// \brief Parse a simple identifier. static std::string parseName(StringRef S) { - unsigned Offset = 0; - while (Offset < S.size() && - (isalpha(S[Offset]) || S[Offset] == '_' || - (Offset > 0 && isdigit(S[Offset])))) + if (S.empty() || !isIdentifierHead(S[0])) + return ""; + + unsigned Offset = 1; + while (Offset < S.size() && isIdentifierBody(S[Offset])) ++Offset; return S.substr(0, Offset).str(); @@ -128,10 +129,10 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) { continue; LineStr = LineStr.substr(Pos + strlen("FieldOffsets: [")); - while (!LineStr.empty() && isdigit(LineStr[0])) { + while (!LineStr.empty() && isDigit(LineStr[0])) { // Parse this offset. unsigned Idx = 1; - while (Idx < LineStr.size() && isdigit(LineStr[Idx])) + while (Idx < LineStr.size() && isDigit(LineStr[Idx])) ++Idx; unsigned long long Offset = 0; @@ -141,7 +142,7 @@ LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) { // Skip over this offset, the following comma, and any spaces. LineStr = LineStr.substr(Idx + 1); - while (!LineStr.empty() && isspace(LineStr[0])) + while (!LineStr.empty() && isWhitespace(LineStr[0])) LineStr = LineStr.substr(1); } } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index e7b64973ad..4024093138 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/Utils.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/PreprocessorOutputOptions.h" @@ -26,7 +27,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include #include using namespace clang; @@ -350,7 +350,7 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, for (unsigned i = 0, e = Str.size(); i != e; ++i) { unsigned char Char = Str[i]; - if (isprint(Char) && Char != '\\' && Char != '"') + if (isPrintable(Char) && Char != '\\' && Char != '"') OS << (char)Char; else // Output anything hard as an octal escape. OS << '\\' @@ -375,7 +375,7 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, for (unsigned i = 0, e = Str.size(); i != e; ++i) { unsigned char Char = Str[i]; - if (isprint(Char) && Char != '\\' && Char != '"') + if (isPrintable(Char) && Char != '\\' && Char != '"') OS << (char)Char; else // Output anything hard as an octal escape. OS << '\\' diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 28c2a39796..c972461241 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/TextDiagnostic.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -20,7 +21,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include -#include using namespace clang; @@ -348,11 +348,11 @@ static void selectInterestingSourceRegion(std::string &SourceLine, // correctly. unsigned CaretStart = 0, CaretEnd = CaretLine.size(); for (; CaretStart != CaretEnd; ++CaretStart) - if (!isspace(static_cast(CaretLine[CaretStart]))) + if (!isWhitespace(CaretLine[CaretStart])) break; for (; CaretEnd != CaretStart; --CaretEnd) - if (!isspace(static_cast(CaretLine[CaretEnd - 1]))) + if (!isWhitespace(CaretLine[CaretEnd - 1])) break; // caret has already been inserted into CaretLine so the above whitespace @@ -363,11 +363,11 @@ static void selectInterestingSourceRegion(std::string &SourceLine, if (!FixItInsertionLine.empty()) { unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size(); for (; FixItStart != FixItEnd; ++FixItStart) - if (!isspace(static_cast(FixItInsertionLine[FixItStart]))) + if (!isWhitespace(FixItInsertionLine[FixItStart])) break; for (; FixItEnd != FixItStart; --FixItEnd) - if (!isspace(static_cast(FixItInsertionLine[FixItEnd - 1]))) + if (!isWhitespace(FixItInsertionLine[FixItEnd - 1])) break; CaretStart = std::min(FixItStart, CaretStart); @@ -423,14 +423,13 @@ static void selectInterestingSourceRegion(std::string &SourceLine, // Skip over any whitespace we see here; we're looking for // another bit of interesting text. // FIXME: Detect non-ASCII whitespace characters too. - while (NewStart && - isspace(static_cast(SourceLine[NewStart]))) + while (NewStart && isWhitespace(SourceLine[NewStart])) NewStart = map.startOfPreviousColumn(NewStart); // Skip over this bit of "interesting" text. while (NewStart) { unsigned Prev = map.startOfPreviousColumn(NewStart); - if (isspace(static_cast(SourceLine[Prev]))) + if (isWhitespace(SourceLine[Prev])) break; NewStart = Prev; } @@ -450,13 +449,11 @@ static void selectInterestingSourceRegion(std::string &SourceLine, // Skip over any whitespace we see here; we're looking for // another bit of interesting text. // FIXME: Detect non-ASCII whitespace characters too. - while (NewEnd < SourceLine.size() && - isspace(static_cast(SourceLine[NewEnd]))) + while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd])) NewEnd = map.startOfNextColumn(NewEnd); // Skip over this bit of "interesting" text. - while (NewEnd < SourceLine.size() && - !isspace(static_cast(SourceLine[NewEnd]))) + while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd])) NewEnd = map.startOfNextColumn(NewEnd); assert(map.byteToColumn(NewEnd) != -1); @@ -517,7 +514,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine, /// greater than or equal to Idx or, if no such character exists, /// returns the end of the string. static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) { - while (Idx < Length && isspace(Str[Idx])) + while (Idx < Length && isWhitespace(Str[Idx])) ++Idx; return Idx; } @@ -562,7 +559,7 @@ static unsigned findEndOfWord(unsigned Start, StringRef Str, char EndPunct = findMatchingPunctuation(Str[Start]); if (!EndPunct) { // This is a normal word. Just find the first space character. - while (End < Length && !isspace(Str[End])) + while (End < Length && !isWhitespace(Str[End])) ++End; return End; } @@ -581,7 +578,7 @@ static unsigned findEndOfWord(unsigned Start, StringRef Str, } // Find the first space character after the punctuation ended. - while (End < Length && !isspace(Str[End])) + while (End < Length && !isWhitespace(Str[End])) ++End; unsigned PunctWordLength = End - Start; diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index b4b51f3d49..82f6e916e5 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/VerifyDiagnosticConsumer.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticBuffer.h" @@ -20,7 +21,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" -#include using namespace clang; typedef VerifyDiagnosticConsumer::Directive Directive; @@ -234,7 +234,7 @@ public: break; if (!EnsureStartOfWord // Check if string literal starts a new word. - || P == Begin || isspace(P[-1]) + || P == Begin || isWhitespace(P[-1]) // Or it could be preceeded by the start of a comment. || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*') && P[-2] == '/')) @@ -253,7 +253,7 @@ public: // Skip zero or more whitespace. void SkipWhitespace() { - for (; C < End && isspace(*C); ++C) + for (; C < End && isWhitespace(*C); ++C) ; } diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index 7dc0491392..9be7b033f7 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -18,7 +18,6 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" -#include #include using namespace clang; diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp index b6cc5996fd..91da8223c1 100644 --- a/lib/Lex/LiteralSupport.cpp +++ b/lib/Lex/LiteralSupport.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/LiteralSupport.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/Preprocessor.h" @@ -128,7 +129,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, break; case 'x': { // Hex escape. ResultChar = 0; - if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { + if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) { if (Diags) Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, diag::err_hex_escape_no_digits) << "x"; @@ -197,7 +198,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, if (Diags == 0) break; - if (isgraph(ResultChar)) + if (isPrintable(ResultChar)) Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, diag::ext_unknown_escape) << std::string(1, ResultChar); @@ -224,7 +225,7 @@ static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, // Skip the '\u' char's. ThisTokBuf += 2; - if (ThisTokBuf == ThisTokEnd || !isxdigit(*ThisTokBuf)) { + if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) { if (Diags) Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf, diag::err_hex_escape_no_digits) << StringRef(&ThisTokBuf[-1], 1); @@ -459,8 +460,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // and FP constants (specifically, the 'pp-number' regex), and assumes that // the byte at "*end" is both valid and not part of the regex. Because of // this, it doesn't have to check for 'overscan' in various places. - assert(!isalnum(*ThisTokEnd) && *ThisTokEnd != '.' && *ThisTokEnd != '_' && - "Lexer didn't maximally munch?"); + assert(!isPreprocessingNumberBody(*ThisTokEnd) && "didn't maximally munch?"); s = DigitsBegin = ThisTokBegin; saw_exponent = false; @@ -483,7 +483,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, s = SkipDigits(s); if (s == ThisTokEnd) { // Done. - } else if (isxdigit(*s) && !(*s == 'e' || *s == 'E')) { + } else if (isHexDigit(*s) && !(*s == 'e' || *s == 'E')) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), diag::err_invalid_decimal_digit) << StringRef(s, 1); hadError = true; @@ -635,7 +635,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { s++; // Handle a hex number like 0x1234. - if ((*s == 'x' || *s == 'X') && (isxdigit(s[1]) || s[1] == '.')) { + if ((*s == 'x' || *s == 'X') && (isHexDigit(s[1]) || s[1] == '.')) { s++; radix = 16; DigitsBegin = s; @@ -694,7 +694,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { s = SkipBinaryDigits(s); if (s == ThisTokEnd) { // Done. - } else if (isxdigit(*s)) { + } else if (isHexDigit(*s)) { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diag::err_invalid_binary_digit) << StringRef(s, 1); hadError = true; @@ -714,7 +714,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { // If we have some other non-octal digit that *is* a decimal digit, see if // this is part of a floating point number like 094.123 or 09e1. - if (isdigit(*s)) { + if (isDigit(*s)) { const char *EndDecimal = SkipDigits(s); if (EndDecimal[0] == '.' || EndDecimal[0] == 'e' || EndDecimal[0] == 'E') { s = EndDecimal; @@ -724,7 +724,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { // If we have a hex digit other than 'e' (which denotes a FP exponent) then // the code is using an incorrect base. - if (isxdigit(*s) && *s != 'e' && *s != 'E') { + if (isHexDigit(*s) && *s != 'e' && *s != 'E') { PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), diag::err_invalid_octal_digit) << StringRef(s, 1); hadError = true; diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 2f40e24175..1ceed54a0a 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Lex/ModuleMap.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" @@ -107,26 +108,15 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, if (Name.empty()) return Name; - // Check whether the filename is already an identifier; this is the common - // case. - bool isIdentifier = true; - for (unsigned I = 0, N = Name.size(); I != N; ++I) { - if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0)) - continue; - - isIdentifier = false; - break; - } - - if (!isIdentifier) { + if (!isValidIdentifier(Name)) { // If we don't already have something with the form of an identifier, // create a buffer with the sanitized name. Buffer.clear(); - if (isdigit(Name[0])) + if (isDigit(Name[0])) Buffer.push_back('_'); Buffer.reserve(Buffer.size() + Name.size()); for (unsigned I = 0, N = Name.size(); I != N; ++I) { - if (isalnum(Name[I]) || isspace(Name[I])) + if (isIdentifierBody(Name[I])) Buffer.push_back(Name[I]); else Buffer.push_back('_'); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 3356637b20..c8e1f4fc3e 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -790,7 +790,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val, // here. Val = 0; for (unsigned i = 0; i != ActualLength; ++i) { - if (!isdigit(DigitTokBegin[i])) { + if (!isDigit(DigitTokBegin[i])) { PP.Diag(PP.AdvanceToTokenCharacter(DigitTok.getLocation(), i), diag::err_pp_line_digit_sequence); PP.DiscardUntilEndOfDirective(); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 14fd581ddc..c5e41445d8 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/OpenCL.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/Lookup.h" @@ -570,7 +571,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { // Parse the major version. unsigned AfterMajor = 0; unsigned Major = 0; - while (AfterMajor < ActualLength && isdigit(ThisTokBegin[AfterMajor])) { + while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) { Major = Major * 10 + ThisTokBegin[AfterMajor] - '0'; ++AfterMajor; } @@ -602,7 +603,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { // Parse the minor version. unsigned AfterMinor = AfterMajor + 1; unsigned Minor = 0; - while (AfterMinor < ActualLength && isdigit(ThisTokBegin[AfterMinor])) { + while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) { Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0'; ++AfterMinor; } @@ -629,7 +630,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { // Parse the subminor version. unsigned AfterSubminor = AfterMinor + 1; unsigned Subminor = 0; - while (AfterSubminor < ActualLength && isdigit(ThisTokBegin[AfterSubminor])) { + while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) { Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0'; ++AfterSubminor; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 4956c1095c..1a1eeb9402 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" @@ -3032,7 +3033,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { // starts with an alphabetical character. SmallString<8> SpellingBuf; StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf); - if (std::isalpha(Spelling[0])) { + if (isLetter(Spelling[0])) { Loc = ConsumeToken(); return &PP.getIdentifierTable().get(Spelling); } diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index b331defaa3..ec4fd821d9 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/Basic/CharInfo.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" @@ -690,7 +691,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { case tok::caret: case tok::caretequal: { std::string ThisTok(PP.getSpelling(Tok)); - if (isalpha(ThisTok[0])) { + if (isLetter(ThisTok[0])) { IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data()); Tok.setKind(tok::identifier); SelectorLoc = ConsumeToken(); diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp index ba5d669f08..34ffd22723 100644 --- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp +++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/Attr.h" #include "clang/AST/ParentMap.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" @@ -2608,7 +2609,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { for (i=0; i < tmpName.length(); i++) { char c = tmpName.at(i); // replace any non alphanumeric characters with '_'. - if (!isalpha(c) && (c < '0' || c > '9')) + if (!isAlphanumeric(c)) tmpName[i] = '_'; } S += tmpName; diff --git a/lib/Rewrite/Frontend/RewriteObjC.cpp b/lib/Rewrite/Frontend/RewriteObjC.cpp index 18b75758ab..b5d9f0c8f4 100644 --- a/lib/Rewrite/Frontend/RewriteObjC.cpp +++ b/lib/Rewrite/Frontend/RewriteObjC.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/Attr.h" #include "clang/AST/ParentMap.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" @@ -2529,7 +2530,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { for (i=0; i < tmpName.length(); i++) { char c = tmpName.at(i); // replace any non alphanumeric characters with '_'. - if (!isalpha(c) && (c < '0' || c > '9')) + if (!isAlphanumeric(c)) tmpName[i] = '_'; } S += tmpName; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 800f64cd5c..17ce614f7f 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -24,6 +24,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/Analysis/Analyses/FormatString.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -6172,7 +6173,7 @@ static bool isSetterLikeSelector(Selector sel) { return false; if (str.empty()) return true; - return !islower(str.front()); + return !isLowercase(str.front()); } /// Check a message send to see if it's likely to cause a retain cycle. diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 8aedaf7973..4c8d098158 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" @@ -4478,7 +4479,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); return; } - } else if (!isxdigit(*I)) { + } else if (!isHexDigit(*I)) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); return; } diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index bf3b82bb8e..57706759f3 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -32,6 +32,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/AST/ExprObjC.h" +#include "clang/Basic/CharInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/ScopeInfo.h" @@ -562,8 +563,9 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) { if (const ObjCInterfaceDecl *IFace = dyn_cast(setter->getDeclContext())) { const StringRef thisPropertyName(prop->getName()); + // Try flipping the case of the first character. char front = thisPropertyName.front(); - front = islower(front) ? toupper(front) : tolower(front); + front = isLowercase(front) ? toUppercase(front) : toLowercase(front); SmallString<100> PropertyName = thisPropertyName; PropertyName[0] = front; IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index 7ccf57a242..ee2d5f5963 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/CharInfo.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" @@ -42,7 +43,6 @@ #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" -#include using namespace clang; using namespace clang::driver; @@ -202,7 +202,7 @@ static void ExpandArgsFromBuf(const char *Arg, std::string CurArg; for (const char *P = Buf; ; ++P) { - if (*P == '\0' || (isspace(*P) && InQuote == ' ')) { + if (*P == '\0' || (isWhitespace(*P) && InQuote == ' ')) { if (!CurArg.empty()) { if (CurArg[0] != '@') { @@ -219,7 +219,7 @@ static void ExpandArgsFromBuf(const char *Arg, continue; } - if (isspace(*P)) { + if (isWhitespace(*P)) { if (InQuote != ' ') CurArg.push_back(*P); continue; diff --git a/unittests/Basic/CharInfoTest.cpp b/unittests/Basic/CharInfoTest.cpp index 9b3d1b3b5f..348e6ffe2b 100644 --- a/unittests/Basic/CharInfoTest.cpp +++ b/unittests/Basic/CharInfoTest.cpp @@ -374,4 +374,126 @@ TEST(CharInfoTest, isRawStringDelimBody) { EXPECT_TRUE(isRawStringDelimBody('/')); EXPECT_FALSE(isRawStringDelimBody('(')); EXPECT_FALSE(isRawStringDelimBody('\0')); + + EXPECT_FALSE(isRawStringDelimBody('\x80')); + EXPECT_FALSE(isRawStringDelimBody('\xc2')); + EXPECT_FALSE(isRawStringDelimBody('\xff')); +} + +TEST(CharInfoTest, toLowercase) { + EXPECT_EQ('0', toLowercase('0')); + EXPECT_EQ('9', toLowercase('9')); + + EXPECT_EQ('a', toLowercase('a')); + EXPECT_EQ('a', toLowercase('A')); + + EXPECT_EQ('z', toLowercase('z')); + EXPECT_EQ('z', toLowercase('Z')); + + EXPECT_EQ('.', toLowercase('.')); + EXPECT_EQ('_', toLowercase('_')); + + EXPECT_EQ('/', toLowercase('/')); + EXPECT_EQ('\0', toLowercase('\0')); +} + +TEST(CharInfoTest, toUppercase) { + EXPECT_EQ('0', toUppercase('0')); + EXPECT_EQ('9', toUppercase('9')); + + EXPECT_EQ('A', toUppercase('a')); + EXPECT_EQ('A', toUppercase('A')); + + EXPECT_EQ('Z', toUppercase('z')); + EXPECT_EQ('Z', toUppercase('Z')); + + EXPECT_EQ('.', toUppercase('.')); + EXPECT_EQ('_', toUppercase('_')); + + EXPECT_EQ('/', toUppercase('/')); + EXPECT_EQ('\0', toUppercase('\0')); +} + +TEST(CharInfoTest, isValidIdentifier) { + EXPECT_FALSE(isValidIdentifier("")); + + // 1 character + EXPECT_FALSE(isValidIdentifier(".")); + EXPECT_FALSE(isValidIdentifier("\n")); + EXPECT_FALSE(isValidIdentifier(" ")); + EXPECT_FALSE(isValidIdentifier("\x80")); + EXPECT_FALSE(isValidIdentifier("\xc2")); + EXPECT_FALSE(isValidIdentifier("\xff")); + EXPECT_FALSE(isValidIdentifier("$")); + EXPECT_FALSE(isValidIdentifier("1")); + + EXPECT_TRUE(isValidIdentifier("_")); + EXPECT_TRUE(isValidIdentifier("a")); + EXPECT_TRUE(isValidIdentifier("z")); + EXPECT_TRUE(isValidIdentifier("A")); + EXPECT_TRUE(isValidIdentifier("Z")); + + // 2 characters, '_' suffix + EXPECT_FALSE(isValidIdentifier("._")); + EXPECT_FALSE(isValidIdentifier("\n_")); + EXPECT_FALSE(isValidIdentifier(" _")); + EXPECT_FALSE(isValidIdentifier("\x80_")); + EXPECT_FALSE(isValidIdentifier("\xc2_")); + EXPECT_FALSE(isValidIdentifier("\xff_")); + EXPECT_FALSE(isValidIdentifier("$_")); + EXPECT_FALSE(isValidIdentifier("1_")); + + EXPECT_TRUE(isValidIdentifier("__")); + EXPECT_TRUE(isValidIdentifier("a_")); + EXPECT_TRUE(isValidIdentifier("z_")); + EXPECT_TRUE(isValidIdentifier("A_")); + EXPECT_TRUE(isValidIdentifier("Z_")); + + // 2 characters, '_' prefix + EXPECT_FALSE(isValidIdentifier("_.")); + EXPECT_FALSE(isValidIdentifier("_\n")); + EXPECT_FALSE(isValidIdentifier("_ ")); + EXPECT_FALSE(isValidIdentifier("_\x80")); + EXPECT_FALSE(isValidIdentifier("_\xc2")); + EXPECT_FALSE(isValidIdentifier("_\xff")); + EXPECT_FALSE(isValidIdentifier("_$")); + EXPECT_TRUE(isValidIdentifier("_1")); + + EXPECT_TRUE(isValidIdentifier("__")); + EXPECT_TRUE(isValidIdentifier("_a")); + EXPECT_TRUE(isValidIdentifier("_z")); + EXPECT_TRUE(isValidIdentifier("_A")); + EXPECT_TRUE(isValidIdentifier("_Z")); + + // 3 characters, '__' prefix + EXPECT_FALSE(isValidIdentifier("__.")); + EXPECT_FALSE(isValidIdentifier("__\n")); + EXPECT_FALSE(isValidIdentifier("__ ")); + EXPECT_FALSE(isValidIdentifier("__\x80")); + EXPECT_FALSE(isValidIdentifier("__\xc2")); + EXPECT_FALSE(isValidIdentifier("__\xff")); + EXPECT_FALSE(isValidIdentifier("__$")); + EXPECT_TRUE(isValidIdentifier("__1")); + + EXPECT_TRUE(isValidIdentifier("___")); + EXPECT_TRUE(isValidIdentifier("__a")); + EXPECT_TRUE(isValidIdentifier("__z")); + EXPECT_TRUE(isValidIdentifier("__A")); + EXPECT_TRUE(isValidIdentifier("__Z")); + + // 3 characters, '_' prefix and suffix + EXPECT_FALSE(isValidIdentifier("_._")); + EXPECT_FALSE(isValidIdentifier("_\n_")); + EXPECT_FALSE(isValidIdentifier("_ _")); + EXPECT_FALSE(isValidIdentifier("_\x80_")); + EXPECT_FALSE(isValidIdentifier("_\xc2_")); + EXPECT_FALSE(isValidIdentifier("_\xff_")); + EXPECT_FALSE(isValidIdentifier("_$_")); + EXPECT_TRUE(isValidIdentifier("_1_")); + + EXPECT_TRUE(isValidIdentifier("___")); + EXPECT_TRUE(isValidIdentifier("_a_")); + EXPECT_TRUE(isValidIdentifier("_z_")); + EXPECT_TRUE(isValidIdentifier("_A_")); + EXPECT_TRUE(isValidIdentifier("_Z_")); } -- 2.40.0