Skip to content

Commit 2f323fc

Browse files
committed
[lldb][NFC] Refactor and document ClangASTContext::IsOperator
Should make it clearer what actually is going on in there. llvm-svn: 370201
1 parent d1a24ba commit 2f323fc

File tree

2 files changed

+73
-210
lines changed

2 files changed

+73
-210
lines changed

lldb/include/lldb/Symbol/ClangASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ class ClangASTContext : public TypeSystem {
249249
&type_fields,
250250
bool packed = false);
251251

252-
static bool IsOperator(const char *name,
252+
static bool IsOperator(llvm::StringRef name,
253253
clang::OverloadedOperatorKind &op_kind);
254254

255255
// Structure, Unions, Classes

lldb/source/Symbol/ClangASTContext.cpp

Lines changed: 72 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -336,219 +336,82 @@ static ClangASTMap &GetASTMap() {
336336
return *g_map_ptr;
337337
}
338338

339-
bool ClangASTContext::IsOperator(const char *name,
339+
bool ClangASTContext::IsOperator(llvm::StringRef name,
340340
clang::OverloadedOperatorKind &op_kind) {
341-
if (name == nullptr || name[0] == '\0')
341+
// All operators have to start with "operator".
342+
if (!name.consume_front("operator"))
342343
return false;
343344

344-
#define OPERATOR_PREFIX "operator"
345-
#define OPERATOR_PREFIX_LENGTH (sizeof(OPERATOR_PREFIX) - 1)
346-
347-
const char *post_op_name = nullptr;
348-
349-
bool no_space = true;
350-
351-
if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH))
352-
return false;
353-
354-
post_op_name = name + OPERATOR_PREFIX_LENGTH;
355-
356-
if (post_op_name[0] == ' ') {
357-
post_op_name++;
358-
no_space = false;
359-
}
360-
361-
#undef OPERATOR_PREFIX
362-
#undef OPERATOR_PREFIX_LENGTH
363-
364-
// This is an operator, set the overloaded operator kind to invalid in case
365-
// this is a conversion operator...
366-
op_kind = clang::NUM_OVERLOADED_OPERATORS;
367-
368-
switch (post_op_name[0]) {
369-
default:
370-
if (no_space)
371-
return false;
372-
break;
373-
case 'n':
374-
if (no_space)
375-
return false;
376-
if (strcmp(post_op_name, "new") == 0)
377-
op_kind = clang::OO_New;
378-
else if (strcmp(post_op_name, "new[]") == 0)
379-
op_kind = clang::OO_Array_New;
380-
break;
381-
382-
case 'd':
383-
if (no_space)
384-
return false;
385-
if (strcmp(post_op_name, "delete") == 0)
386-
op_kind = clang::OO_Delete;
387-
else if (strcmp(post_op_name, "delete[]") == 0)
388-
op_kind = clang::OO_Array_Delete;
389-
break;
390-
391-
case '+':
392-
if (post_op_name[1] == '\0')
393-
op_kind = clang::OO_Plus;
394-
else if (post_op_name[2] == '\0') {
395-
if (post_op_name[1] == '=')
396-
op_kind = clang::OO_PlusEqual;
397-
else if (post_op_name[1] == '+')
398-
op_kind = clang::OO_PlusPlus;
399-
}
400-
break;
401-
402-
case '-':
403-
if (post_op_name[1] == '\0')
404-
op_kind = clang::OO_Minus;
405-
else if (post_op_name[2] == '\0') {
406-
switch (post_op_name[1]) {
407-
case '=':
408-
op_kind = clang::OO_MinusEqual;
409-
break;
410-
case '-':
411-
op_kind = clang::OO_MinusMinus;
412-
break;
413-
case '>':
414-
op_kind = clang::OO_Arrow;
415-
break;
416-
}
417-
} else if (post_op_name[3] == '\0') {
418-
if (post_op_name[2] == '*')
419-
op_kind = clang::OO_ArrowStar;
420-
break;
421-
}
422-
break;
423-
424-
case '*':
425-
if (post_op_name[1] == '\0')
426-
op_kind = clang::OO_Star;
427-
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
428-
op_kind = clang::OO_StarEqual;
429-
break;
430-
431-
case '/':
432-
if (post_op_name[1] == '\0')
433-
op_kind = clang::OO_Slash;
434-
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
435-
op_kind = clang::OO_SlashEqual;
436-
break;
437-
438-
case '%':
439-
if (post_op_name[1] == '\0')
440-
op_kind = clang::OO_Percent;
441-
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
442-
op_kind = clang::OO_PercentEqual;
443-
break;
444-
445-
case '^':
446-
if (post_op_name[1] == '\0')
447-
op_kind = clang::OO_Caret;
448-
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
449-
op_kind = clang::OO_CaretEqual;
450-
break;
451-
452-
case '&':
453-
if (post_op_name[1] == '\0')
454-
op_kind = clang::OO_Amp;
455-
else if (post_op_name[2] == '\0') {
456-
switch (post_op_name[1]) {
457-
case '=':
458-
op_kind = clang::OO_AmpEqual;
459-
break;
460-
case '&':
461-
op_kind = clang::OO_AmpAmp;
462-
break;
463-
}
464-
}
465-
break;
466-
467-
case '|':
468-
if (post_op_name[1] == '\0')
469-
op_kind = clang::OO_Pipe;
470-
else if (post_op_name[2] == '\0') {
471-
switch (post_op_name[1]) {
472-
case '=':
473-
op_kind = clang::OO_PipeEqual;
474-
break;
475-
case '|':
476-
op_kind = clang::OO_PipePipe;
477-
break;
478-
}
479-
}
480-
break;
481-
482-
case '~':
483-
if (post_op_name[1] == '\0')
484-
op_kind = clang::OO_Tilde;
485-
break;
486-
487-
case '!':
488-
if (post_op_name[1] == '\0')
489-
op_kind = clang::OO_Exclaim;
490-
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
491-
op_kind = clang::OO_ExclaimEqual;
492-
break;
493-
494-
case '=':
495-
if (post_op_name[1] == '\0')
496-
op_kind = clang::OO_Equal;
497-
else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
498-
op_kind = clang::OO_EqualEqual;
499-
break;
500-
501-
case '<':
502-
if (post_op_name[1] == '\0')
503-
op_kind = clang::OO_Less;
504-
else if (post_op_name[2] == '\0') {
505-
switch (post_op_name[1]) {
506-
case '<':
507-
op_kind = clang::OO_LessLess;
508-
break;
509-
case '=':
510-
op_kind = clang::OO_LessEqual;
511-
break;
512-
}
513-
} else if (post_op_name[3] == '\0') {
514-
if (post_op_name[2] == '=')
515-
op_kind = clang::OO_LessLessEqual;
516-
}
517-
break;
518-
519-
case '>':
520-
if (post_op_name[1] == '\0')
521-
op_kind = clang::OO_Greater;
522-
else if (post_op_name[2] == '\0') {
523-
switch (post_op_name[1]) {
524-
case '>':
525-
op_kind = clang::OO_GreaterGreater;
526-
break;
527-
case '=':
528-
op_kind = clang::OO_GreaterEqual;
529-
break;
530-
}
531-
} else if (post_op_name[1] == '>' && post_op_name[2] == '=' &&
532-
post_op_name[3] == '\0') {
533-
op_kind = clang::OO_GreaterGreaterEqual;
534-
}
535-
break;
536-
537-
case ',':
538-
if (post_op_name[1] == '\0')
539-
op_kind = clang::OO_Comma;
540-
break;
541-
542-
case '(':
543-
if (post_op_name[1] == ')' && post_op_name[2] == '\0')
544-
op_kind = clang::OO_Call;
545-
break;
345+
// Remember if there was a space after "operator". This is necessary to
346+
// check for collisions with strangely named functions like "operatorint()".
347+
bool space_after_operator = name.consume_front(" ");
348+
349+
op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
350+
.Case("+", clang::OO_Plus)
351+
.Case("+=", clang::OO_PlusEqual)
352+
.Case("++", clang::OO_PlusPlus)
353+
.Case("-", clang::OO_Minus)
354+
.Case("-=", clang::OO_MinusEqual)
355+
.Case("--", clang::OO_MinusMinus)
356+
.Case("->", clang::OO_Arrow)
357+
.Case("->*", clang::OO_ArrowStar)
358+
.Case("*", clang::OO_Star)
359+
.Case("*=", clang::OO_StarEqual)
360+
.Case("/", clang::OO_Slash)
361+
.Case("/=", clang::OO_SlashEqual)
362+
.Case("%", clang::OO_Percent)
363+
.Case("%=", clang::OO_PercentEqual)
364+
.Case("^", clang::OO_Caret)
365+
.Case("^=", clang::OO_CaretEqual)
366+
.Case("&", clang::OO_Amp)
367+
.Case("&=", clang::OO_AmpEqual)
368+
.Case("&&", clang::OO_AmpAmp)
369+
.Case("|", clang::OO_Pipe)
370+
.Case("|=", clang::OO_PipeEqual)
371+
.Case("||", clang::OO_PipePipe)
372+
.Case("~", clang::OO_Tilde)
373+
.Case("!", clang::OO_Exclaim)
374+
.Case("!=", clang::OO_ExclaimEqual)
375+
.Case("=", clang::OO_Equal)
376+
.Case("==", clang::OO_EqualEqual)
377+
.Case("<", clang::OO_Less)
378+
.Case("<<", clang::OO_LessLess)
379+
.Case("<<=", clang::OO_LessLessEqual)
380+
.Case("<=", clang::OO_LessEqual)
381+
.Case(">", clang::OO_Greater)
382+
.Case(">>", clang::OO_GreaterGreater)
383+
.Case(">>=", clang::OO_GreaterGreaterEqual)
384+
.Case(">=", clang::OO_GreaterEqual)
385+
.Case("()", clang::OO_Call)
386+
.Case("[]", clang::OO_Subscript)
387+
.Case(",", clang::OO_Comma)
388+
.Default(clang::NUM_OVERLOADED_OPERATORS);
389+
390+
// We found a fitting operator, so we can exit now.
391+
if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
392+
return true;
546393

547-
case '[':
548-
if (post_op_name[1] == ']' && post_op_name[2] == '\0')
549-
op_kind = clang::OO_Subscript;
550-
break;
551-
}
394+
// After the "operator " or "operator" part is something unknown. This means
395+
// it's either one of the named operators (new/delete), a conversion operator
396+
// (e.g. operator bool) or a function which name starts with "operator"
397+
// (e.g. void operatorbool).
398+
399+
// If it's a function that starts with operator it can't have a space after
400+
// "operator" because identifiers can't contain spaces.
401+
// E.g. "operator int" (conversion operator)
402+
// vs. "operatorint" (function with colliding name).
403+
if (!space_after_operator)
404+
return false; // not an operator.
405+
406+
// Now the operator is either one of the named operators or a conversion
407+
// operator.
408+
op_kind = StringSwitch<clang::OverloadedOperatorKind>(name)
409+
.Case("new", clang::OO_New)
410+
.Case("new[]", clang::OO_Array_New)
411+
.Case("delete", clang::OO_Delete)
412+
.Case("delete[]", clang::OO_Array_Delete)
413+
// conversion operators hit this case.
414+
.Default(clang::NUM_OVERLOADED_OPERATORS);
552415

553416
return true;
554417
}

0 commit comments

Comments
 (0)