]> granicus.if.org Git - clang/commitdiff
Excise <cctype> from Clang (except clang-tblgen) in favor of CharInfo.h.
authorJordan Rose <jordan_rose@apple.com>
Fri, 8 Feb 2013 22:30:41 +0000 (22:30 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 8 Feb 2013 22:30:41 +0000 (22:30 +0000)
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

31 files changed:
include/clang/AST/Expr.h
include/clang/Basic/CharInfo.h
include/clang/Lex/LiteralSupport.h
lib/AST/Expr.cpp
lib/AST/Stmt.cpp
lib/AST/TemplateBase.cpp
lib/Analysis/CocoaConventions.cpp
lib/Basic/Diagnostic.cpp
lib/Basic/IdentifierTable.cpp
lib/Basic/TargetInfo.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Driver/WindowsToolChain.cpp
lib/Edit/EditedSource.cpp
lib/Frontend/LayoutOverrideSource.cpp
lib/Frontend/PrintPreprocessedOutput.cpp
lib/Frontend/TextDiagnostic.cpp
lib/Frontend/VerifyDiagnosticConsumer.cpp
lib/Lex/HeaderMap.cpp
lib/Lex/LiteralSupport.cpp
lib/Lex/ModuleMap.cpp
lib/Lex/PPDirectives.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseObjc.cpp
lib/Rewrite/Frontend/RewriteModernObjC.cpp
lib/Rewrite/Frontend/RewriteObjC.cpp
lib/Sema/SemaChecking.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaPseudoObject.cpp
tools/driver/driver.cpp
unittests/Basic/CharInfoTest.cpp

index 598f18937f91b833a0d228216ba00528e75d4db9..11fa6cf6342f54cf875352bafacedd9e74bd3e92 100644 (file)
@@ -28,7 +28,6 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
-#include <cctype>
 
 namespace clang {
   class APValue;
index f9b7b7311d027e4d648097ee4a50036708ef8d8d..2522face65e439461a14ef1d1aff3a7ffbd8d9e1 100644 (file)
@@ -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
index 7ffa328651f2320fc1de7cc0945f5712543108cf..b1430cc805190f8b6acecc7d85af55ece5948f65 100644 (file)
 #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 <cctype>
 
 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;
   }
index 644fab9c8eb686ff54bfaa76b2aef97a68026d37..66980a9cd125cf333265f50838e4996440790291 100644 (file)
@@ -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 << '\\'
index 3214a2b23b970d36ffa19b1dd8839cd78bfdbb65..2ae5a1266c187d3602d79267190a77f908682f71 100644 (file)
@@ -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<AsmStringPiece>&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<AsmStringPiece>&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 =
index f5dda30deacc2dd40c01171b26f95b177ace4a2b..6519340c87dfa0c76bce26b14d2311b351fe6ead 100644 (file)
@@ -25,7 +25,6 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
-#include <cctype>
 
 using namespace clang;
 
index ac22671c53013def6c678f9707c5e640627c2399..0db3cac58b56dbad7a4f5ec97b3ec970ce6834b8 100644 (file)
@@ -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 <cctype>
 
 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
index 6627ad62f3d1f438032b3f210cc9b901c83a3eb7..2b448058a0fe527299c330357c8406d4be080d78 100644 (file)
@@ -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 <cctype>
 
 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';
index ecaaf036b01e5db00781c01672b4ae7e79edb0cd..b943472f335c402380347ad7d73c1e2ed7972d8d 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #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 <cctype>
 #include <cstdio>
 
 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) {
index fe68a9df6ad7941d79fcf7aa03c933ce7bf6bd27..70ea2351ec3529ed78328fd9c69e7a80b952efce 100644 (file)
 
 #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 <cctype>
 #include <cstdlib>
 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 &&
index 91f22b1cd6f7919d915f1b4c547afcd4f9319826..ff2656548ecedcac85c1b3722e9cdb58ce662882 100644 (file)
@@ -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);
index 323765adb0adc0063df6fd262f28db86c466479f..f640b17611546d4e57f64953390202ff97d83dbc 100644 (file)
@@ -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);
index 002776759fe03e299467329c3e85f1e1c31e2632..dd99ca9280193d68bc0400d42a0d729b9c9f3e92 100644 (file)
@@ -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 <cctype>
 
 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.
index 9309661972b25c1ba23acfb0d7c0f8cf85c6d552..924a64068fe4e9c46e0f66eccccbdda476b0a073 100644 (file)
@@ -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 <cctype>
 #include <fstream>
 #include <string>
 
@@ -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);
     }
   }
index e7b64973ad58ac5c29b2230c789660c71e46b270..40240931388eefd6f061424899b0b2e25d143478 100644 (file)
@@ -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 <cctype>
 #include <cstdio>
 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 << '\\'
index 28c2a3979689a54a68b14da5c92c0f6b969bbbae..c97246124195a969cd3ac59dea097e47a6e5b261 100644 (file)
@@ -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 <algorithm>
-#include <cctype>
 
 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<unsigned char>(CaretLine[CaretStart])))
+    if (!isWhitespace(CaretLine[CaretStart]))
       break;
 
   for (; CaretEnd != CaretStart; --CaretEnd)
-    if (!isspace(static_cast<unsigned char>(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<unsigned char>(FixItInsertionLine[FixItStart])))
+      if (!isWhitespace(FixItInsertionLine[FixItStart]))
         break;
 
     for (; FixItEnd != FixItStart; --FixItEnd)
-      if (!isspace(static_cast<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(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;
index b4b51f3d498e8e93dadabc93bbc1de734abba486..82f6e916e58d91e388b414610bc1065485c61577 100644 (file)
@@ -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 <cctype>
 
 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)
       ;
   }
 
index 7dc0491392ccb76721d26d1506f7085ce00858f5..9be7b033f7f63883cbe0bcdf12329e8da9e9291b 100644 (file)
@@ -18,7 +18,6 @@
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include <cctype>
 #include <cstdio>
 using namespace clang;
 
index b6cc5996fdfcaf6c871e6634af73372beadfc5a1..91da8223c184185af5de37ccb8a7bed1b3d69e90 100644 (file)
@@ -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;
index 2f40e24175cbfeea25b7189c4a8f1512f5828b39..1ceed54a0a7c410b00819ba6b1da1839a3b9cf0f 100644 (file)
@@ -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('_');
index 3356637b20c6dd171ee681c2c41bf6ed08d0241e..c8e1f4fc3e297927c6022e9aa52a513c8413b85b 100644 (file)
@@ -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();
index 14fd581ddcb11f561604df0832f0305767867a4b..c5e41445d8be057f4069e63e4481b744f4a65a02 100644 (file)
@@ -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;
   }
index 4956c1095c3f7168e1da81a059aab0134bc35abd..1a1eeb94029d7021deb8f8703c2bbb516d23671f 100644 (file)
@@ -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);
     }
index b331defaa398183e94f0f234a1139a1d146966e7..ec4fd821d937e82cd2c401b7072a12afd50136c0 100644 (file)
@@ -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();
index ba5d669f0835900e8fa98ad2fce06befcae5c5e4..34ffd227237b34b3c6a3bcd5b6b2790b4184cc5a 100644 (file)
@@ -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;
index 18b75758ab0c91e54ad386573378e5cfcf2a56f4..b5d9f0c8f4eca9eb115e8a2a5ea6723bbdab4dca 100644 (file)
@@ -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;
index 800f64cd5cdce71ff71b22a5b8a2060a248935c0..17ce614f7f3284e47733e187a566bd14f77b71f7 100644 (file)
@@ -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.
index 8aedaf7973e92f279b8afc444247122a34a19b97..4c8d098158eceab3aee17bf800370b273e896201 100644 (file)
@@ -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;
       }
index bf3b82bb8e34b08061c1d823b77b0b6fd3144ace..57706759f39abded905d825d874015c7c3beeea9 100644 (file)
@@ -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<ObjCInterfaceDecl>(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);
index 7ccf57a2428b5f49533681bacf2289e2378d61e2..ee2d5f596337836c6994892b0ec9d6111b7a23d8 100644 (file)
@@ -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 <cctype>
 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;
index 9b3d1b3b5f4e4204259c8f9881ca979fc609e191..348e6ffe2b7d1b84d725cb8d30c3f8b8811e14c6 100644 (file)
@@ -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_"));
 }