From 2f323fc790c4a7fa23ef3a66d7c9147a8b9476e1 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Wed, 28 Aug 2019 13:46:01 +0000 Subject: [PATCH] [lldb][NFC] Refactor and document ClangASTContext::IsOperator Should make it clearer what actually is going on in there. llvm-svn: 370201 --- lldb/include/lldb/Symbol/ClangASTContext.h | 2 +- lldb/source/Symbol/ClangASTContext.cpp | 273 +++++---------------- 2 files changed, 69 insertions(+), 206 deletions(-) diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index 6536c432f410..a64e8f1ac245 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -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 diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 367008468029..3df9ccd16646 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -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) + // 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(" "); - const char *post_op_name = nullptr; + op_kind = StringSwitch(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); - bool no_space = true; + // We found a fitting operator, so we can exit now. + if (op_kind != clang::NUM_OVERLOADED_OPERATORS) + return true; - if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) - return false; + // 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). - post_op_name = name + OPERATOR_PREFIX_LENGTH; + // 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. - 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; - } + // Now the operator is either one of the named operators or a conversion + // operator. + op_kind = StringSwitch(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; }