[Lldb-commits] [lldb] r370201 - [lldb][NFC] Refactor and document ClangASTContext::IsOperator

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 28 06:46:01 PDT 2019


Author: teemperor
Date: Wed Aug 28 06:46:01 2019
New Revision: 370201

URL: http://llvm.org/viewvc/llvm-project?rev=370201&view=rev
Log:
[lldb][NFC] Refactor and document ClangASTContext::IsOperator

Should make it clearer what actually is going on in there.

Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/source/Symbol/ClangASTContext.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=370201&r1=370200&r2=370201&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Wed Aug 28 06:46:01 2019
@@ -249,7 +249,7 @@ public:
           &type_fields,
       bool packed = false);
 
-  static bool IsOperator(const char *name,
+  static bool IsOperator(llvm::StringRef name,
                          clang::OverloadedOperatorKind &op_kind);
 
   // Structure, Unions, Classes

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=370201&r1=370200&r2=370201&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Wed Aug 28 06:46:01 2019
@@ -336,219 +336,82 @@ static ClangASTMap &GetASTMap() {
   return *g_map_ptr;
 }
 
-bool ClangASTContext::IsOperator(const char *name,
+bool ClangASTContext::IsOperator(llvm::StringRef name,
                                  clang::OverloadedOperatorKind &op_kind) {
-  if (name == nullptr || name[0] == '\0')
+  // All operators have to start with "operator".
+  if (!name.consume_front("operator"))
     return false;
 
-#define OPERATOR_PREFIX "operator"
-#define OPERATOR_PREFIX_LENGTH (sizeof(OPERATOR_PREFIX) - 1)
-
-  const char *post_op_name = nullptr;
-
-  bool no_space = true;
-
-  if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH))
-    return false;
-
-  post_op_name = name + OPERATOR_PREFIX_LENGTH;
-
-  if (post_op_name[0] == ' ') {
-    post_op_name++;
-    no_space = false;
-  }
-
-#undef OPERATOR_PREFIX
-#undef OPERATOR_PREFIX_LENGTH
-
-  // This is an operator, set the overloaded operator kind to invalid in case
-  // this is a conversion operator...
-  op_kind = clang::NUM_OVERLOADED_OPERATORS;
-
-  switch (post_op_name[0]) {
-  default:
-    if (no_space)
-      return false;
-    break;
-  case 'n':
-    if (no_space)
-      return false;
-    if (strcmp(post_op_name, "new") == 0)
-      op_kind = clang::OO_New;
-    else if (strcmp(post_op_name, "new[]") == 0)
-      op_kind = clang::OO_Array_New;
-    break;
-
-  case 'd':
-    if (no_space)
-      return false;
-    if (strcmp(post_op_name, "delete") == 0)
-      op_kind = clang::OO_Delete;
-    else if (strcmp(post_op_name, "delete[]") == 0)
-      op_kind = clang::OO_Array_Delete;
-    break;
-
-  case '+':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Plus;
-    else if (post_op_name[2] == '\0') {
-      if (post_op_name[1] == '=')
-        op_kind = clang::OO_PlusEqual;
-      else if (post_op_name[1] == '+')
-        op_kind = clang::OO_PlusPlus;
-    }
-    break;
-
-  case '-':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Minus;
-    else if (post_op_name[2] == '\0') {
-      switch (post_op_name[1]) {
-      case '=':
-        op_kind = clang::OO_MinusEqual;
-        break;
-      case '-':
-        op_kind = clang::OO_MinusMinus;
-        break;
-      case '>':
-        op_kind = clang::OO_Arrow;
-        break;
-      }
-    } else if (post_op_name[3] == '\0') {
-      if (post_op_name[2] == '*')
-        op_kind = clang::OO_ArrowStar;
-      break;
-    }
-    break;
-
-  case '*':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Star;
-    else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
-      op_kind = clang::OO_StarEqual;
-    break;
-
-  case '/':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Slash;
-    else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
-      op_kind = clang::OO_SlashEqual;
-    break;
-
-  case '%':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Percent;
-    else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
-      op_kind = clang::OO_PercentEqual;
-    break;
-
-  case '^':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Caret;
-    else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
-      op_kind = clang::OO_CaretEqual;
-    break;
-
-  case '&':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Amp;
-    else if (post_op_name[2] == '\0') {
-      switch (post_op_name[1]) {
-      case '=':
-        op_kind = clang::OO_AmpEqual;
-        break;
-      case '&':
-        op_kind = clang::OO_AmpAmp;
-        break;
-      }
-    }
-    break;
-
-  case '|':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Pipe;
-    else if (post_op_name[2] == '\0') {
-      switch (post_op_name[1]) {
-      case '=':
-        op_kind = clang::OO_PipeEqual;
-        break;
-      case '|':
-        op_kind = clang::OO_PipePipe;
-        break;
-      }
-    }
-    break;
-
-  case '~':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Tilde;
-    break;
-
-  case '!':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Exclaim;
-    else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
-      op_kind = clang::OO_ExclaimEqual;
-    break;
-
-  case '=':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Equal;
-    else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
-      op_kind = clang::OO_EqualEqual;
-    break;
-
-  case '<':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Less;
-    else if (post_op_name[2] == '\0') {
-      switch (post_op_name[1]) {
-      case '<':
-        op_kind = clang::OO_LessLess;
-        break;
-      case '=':
-        op_kind = clang::OO_LessEqual;
-        break;
-      }
-    } else if (post_op_name[3] == '\0') {
-      if (post_op_name[2] == '=')
-        op_kind = clang::OO_LessLessEqual;
-    }
-    break;
-
-  case '>':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Greater;
-    else if (post_op_name[2] == '\0') {
-      switch (post_op_name[1]) {
-      case '>':
-        op_kind = clang::OO_GreaterGreater;
-        break;
-      case '=':
-        op_kind = clang::OO_GreaterEqual;
-        break;
-      }
-    } else if (post_op_name[1] == '>' && post_op_name[2] == '=' &&
-               post_op_name[3] == '\0') {
-      op_kind = clang::OO_GreaterGreaterEqual;
-    }
-    break;
-
-  case ',':
-    if (post_op_name[1] == '\0')
-      op_kind = clang::OO_Comma;
-    break;
-
-  case '(':
-    if (post_op_name[1] == ')' && post_op_name[2] == '\0')
-      op_kind = clang::OO_Call;
-    break;
-
-  case '[':
-    if (post_op_name[1] == ']' && post_op_name[2] == '\0')
-      op_kind = clang::OO_Subscript;
-    break;
-  }
+  // Remember if there was a space after "operator". This is necessary to
+  // check for collisions with strangely named functions like "operatorint()".
+  bool space_after_operator = name.consume_front(" ");
+
+  op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
+                .Case("+", clang::OO_Plus)
+                .Case("+=", clang::OO_PlusEqual)
+                .Case("++", clang::OO_PlusPlus)
+                .Case("-", clang::OO_Minus)
+                .Case("-=", clang::OO_MinusEqual)
+                .Case("--", clang::OO_MinusMinus)
+                .Case("->", clang::OO_Arrow)
+                .Case("->*", clang::OO_ArrowStar)
+                .Case("*", clang::OO_Star)
+                .Case("*=", clang::OO_StarEqual)
+                .Case("/", clang::OO_Slash)
+                .Case("/=", clang::OO_SlashEqual)
+                .Case("%", clang::OO_Percent)
+                .Case("%=", clang::OO_PercentEqual)
+                .Case("^", clang::OO_Caret)
+                .Case("^=", clang::OO_CaretEqual)
+                .Case("&", clang::OO_Amp)
+                .Case("&=", clang::OO_AmpEqual)
+                .Case("&&", clang::OO_AmpAmp)
+                .Case("|", clang::OO_Pipe)
+                .Case("|=", clang::OO_PipeEqual)
+                .Case("||", clang::OO_PipePipe)
+                .Case("~", clang::OO_Tilde)
+                .Case("!", clang::OO_Exclaim)
+                .Case("!=", clang::OO_ExclaimEqual)
+                .Case("=", clang::OO_Equal)
+                .Case("==", clang::OO_EqualEqual)
+                .Case("<", clang::OO_Less)
+                .Case("<<", clang::OO_LessLess)
+                .Case("<<=", clang::OO_LessLessEqual)
+                .Case("<=", clang::OO_LessEqual)
+                .Case(">", clang::OO_Greater)
+                .Case(">>", clang::OO_GreaterGreater)
+                .Case(">>=", clang::OO_GreaterGreaterEqual)
+                .Case(">=", clang::OO_GreaterEqual)
+                .Case("()", clang::OO_Call)
+                .Case("[]", clang::OO_Subscript)
+                .Case(",", clang::OO_Comma)
+                .Default(clang::NUM_OVERLOADED_OPERATORS);
+
+  // We found a fitting operator, so we can exit now.
+  if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
+    return true;
+
+  // After the "operator " or "operator" part is something unknown. This means
+  // it's either one of the named operators (new/delete), a conversion operator
+  // (e.g. operator bool) or a function which name starts with "operator"
+  // (e.g. void operatorbool).
+
+  // If it's a function that starts with operator it can't have a space after
+  // "operator" because identifiers can't contain spaces.
+  // E.g. "operator int" (conversion operator)
+  //  vs. "operatorint" (function with colliding name).
+  if (!space_after_operator)
+    return false; // not an operator.
+
+  // Now the operator is either one of the named operators or a conversion
+  // operator.
+  op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
+                .Case("new", clang::OO_New)
+                .Case("new[]", clang::OO_Array_New)
+                .Case("delete", clang::OO_Delete)
+                .Case("delete[]", clang::OO_Array_Delete)
+                // conversion operators hit this case.
+                .Default(clang::NUM_OVERLOADED_OPERATORS);
 
   return true;
 }




More information about the lldb-commits mailing list