X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fc-exp.y;h=50a2eef98b58614bf41cafada3359167e92bae8f;hb=3293bbaffac9a22fc6d1a08ac6602a4a63b5e68b;hp=627ea1f3baeb4f15ebb585961f0ea13857f3b679;hpb=dac43e327d002107f6bc9481749de039f410df73;p=binutils-gdb.git diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 627ea1f3bae..50a2eef98b5 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -1,5 +1,5 @@ /* YACC parser for C expressions, for GDB. - Copyright (C) 1986-2019 Free Software Foundation, Inc. + Copyright (C) 1986-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -237,6 +237,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); /* Special type cases, put in to allow the parser to distinguish different legal basetypes. */ %token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD +%token RESTRICT ATOMIC %token DOLLAR_VARIABLE @@ -474,14 +475,15 @@ exp : OBJC_LBRAC TYPENAME { CORE_ADDR theclass; + std::string copy = copy_name ($2.stoken); theclass = lookup_objc_class (pstate->gdbarch (), - copy_name ($2.stoken)); + copy.c_str ()); if (theclass == 0) error (_("%s is not an ObjC Class"), - copy_name ($2.stoken)); + copy.c_str ()); write_exp_elt_opcode (pstate, OP_LONG); write_exp_elt_type (pstate, - parse_type (pstate)->builtin_int); + parse_type (pstate)->builtin_int); write_exp_elt_longcst (pstate, (LONGEST) theclass); write_exp_elt_opcode (pstate, OP_LONG); start_msglist(); @@ -823,7 +825,6 @@ exp : SIZEOF '(' type ')' %prec UNARY write_exp_elt_opcode (pstate, OP_LONG); write_exp_elt_type (pstate, lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "int")); type = check_typedef (type); @@ -959,7 +960,7 @@ block : BLOCKNAME $$ = SYMBOL_BLOCK_VALUE ($1.sym.symbol); else error (_("No file or function \"%s\"."), - copy_name ($1.stoken)); + copy_name ($1.stoken).c_str ()); } | FILENAME { @@ -968,13 +969,15 @@ block : BLOCKNAME ; block : block COLONCOLON name - { struct symbol *tem - = lookup_symbol (copy_name ($3), $1, + { + std::string copy = copy_name ($3); + struct symbol *tem + = lookup_symbol (copy.c_str (), $1, VAR_DOMAIN, NULL).symbol; if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) error (_("No function \"%s\" in specified context."), - copy_name ($3)); + copy.c_str ()); $$ = SYMBOL_BLOCK_VALUE (tem); } ; @@ -985,7 +988,7 @@ variable: name_not_typename ENTRY || !symbol_read_needs_frame (sym)) error (_("@entry can be used only for function " "parameters, not for \"%s\""), - copy_name ($1.stoken)); + copy_name ($1.stoken).c_str ()); write_exp_elt_opcode (pstate, OP_VAR_ENTRY_VALUE); write_exp_elt_sym (pstate, sym); @@ -994,16 +997,17 @@ variable: name_not_typename ENTRY ; variable: block COLONCOLON name - { struct block_symbol sym - = lookup_symbol (copy_name ($3), $1, + { + std::string copy = copy_name ($3); + struct block_symbol sym + = lookup_symbol (copy.c_str (), $1, VAR_DOMAIN, NULL); if (sym.symbol == 0) error (_("No symbol \"%s\" in specified context."), - copy_name ($3)); + copy.c_str ()); if (symbol_read_needs_frame (sym.symbol)) - - innermost_block.update (sym); + pstate->block_tracker->update (sym); write_exp_elt_opcode (pstate, OP_VAR_VALUE); write_exp_elt_block (pstate, sym.block); @@ -1050,22 +1054,23 @@ qualified_name: TYPENAME COLONCOLON name } | TYPENAME COLONCOLON name COLONCOLON name { - char *copy = copy_name ($3); + std::string copy = copy_name ($3); error (_("No type \"%s\" within class " "or namespace \"%s\"."), - copy, TYPE_SAFE_NAME ($1.type)); + copy.c_str (), TYPE_SAFE_NAME ($1.type)); } ; variable: qualified_name | COLONCOLON name_not_typename { - char *name = copy_name ($2.stoken); + std::string name = copy_name ($2.stoken); struct symbol *sym; struct bound_minimal_symbol msymbol; sym - = lookup_symbol (name, (const struct block *) NULL, + = lookup_symbol (name.c_str (), + (const struct block *) NULL, VAR_DOMAIN, NULL).symbol; if (sym) { @@ -1076,13 +1081,14 @@ variable: qualified_name break; } - msymbol = lookup_bound_minimal_symbol (name); + msymbol = lookup_bound_minimal_symbol (name.c_str ()); if (msymbol.minsym != NULL) write_exp_msymbol (pstate, msymbol); else if (!have_full_symbols () && !have_partial_symbols ()) error (_("No symbol table is loaded. Use the \"file\" command.")); else - error (_("No symbol \"%s\" in current context."), name); + error (_("No symbol \"%s\" in current context."), + name.c_str ()); } ; @@ -1092,7 +1098,7 @@ variable: name_not_typename if (sym.symbol) { if (symbol_read_needs_frame (sym.symbol)) - innermost_block.update (sym); + pstate->block_tracker->update (sym); /* If we found a function, see if it's an ifunc resolver that has the same @@ -1116,7 +1122,7 @@ variable: name_not_typename /* C++: it hangs off of `this'. Must not inadvertently convert from a method call to data ref. */ - innermost_block.update (sym); + pstate->block_tracker->update (sym); write_exp_elt_opcode (pstate, OP_THIS); write_exp_elt_opcode (pstate, OP_THIS); write_exp_elt_opcode (pstate, STRUCTOP_PTR); @@ -1125,17 +1131,17 @@ variable: name_not_typename } else { - char *arg = copy_name ($1.stoken); + std::string arg = copy_name ($1.stoken); bound_minimal_symbol msymbol - = lookup_bound_minimal_symbol (arg); + = lookup_bound_minimal_symbol (arg.c_str ()); if (msymbol.minsym == NULL) { if (!have_full_symbols () && !have_partial_symbols ()) error (_("No symbol table is loaded. Use the \"file\" command.")); else error (_("No symbol \"%s\" in current context."), - copy_name ($1.stoken)); + arg.c_str ()); } /* This minsym might be an alias for @@ -1164,35 +1170,43 @@ variable: name_not_typename } ; -space_identifier : '@' NAME - { - cpstate->type_stack.insert (pstate, copy_name ($2.stoken)); - } - ; - const_or_volatile: const_or_volatile_noopt | ; -cv_with_space_id : const_or_volatile space_identifier const_or_volatile +single_qualifier: + CONST_KEYWORD + { cpstate->type_stack.insert (tp_const); } + | VOLATILE_KEYWORD + { cpstate->type_stack.insert (tp_volatile); } + | ATOMIC + { cpstate->type_stack.insert (tp_atomic); } + | RESTRICT + { cpstate->type_stack.insert (tp_restrict); } + | '@' NAME + { + cpstate->type_stack.insert (pstate, + copy_name ($2.stoken).c_str ()); + } ; -const_or_volatile_or_space_identifier_noopt: cv_with_space_id - | const_or_volatile_noopt +qualifier_seq_noopt: + single_qualifier + | qualifier_seq single_qualifier ; -const_or_volatile_or_space_identifier: - const_or_volatile_or_space_identifier_noopt +qualifier_seq: + qualifier_seq_noopt | ; ptr_operator: ptr_operator '*' { cpstate->type_stack.insert (tp_pointer); } - const_or_volatile_or_space_identifier + qualifier_seq | '*' { cpstate->type_stack.insert (tp_pointer); } - const_or_volatile_or_space_identifier + qualifier_seq | '&' { cpstate->type_stack.insert (tp_reference); } | '&' ptr_operator @@ -1294,123 +1308,95 @@ typebase { $$ = $1.type; } | INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "int"); } | LONG { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | SHORT { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG SIGNED_KEYWORD INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | SIGNED_KEYWORD LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | UNSIGNED LONG INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG UNSIGNED INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long"); } | LONG LONG { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG SIGNED_KEYWORD INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | SIGNED_KEYWORD LONG LONG { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | SIGNED_KEYWORD LONG LONG INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | UNSIGNED LONG LONG { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | UNSIGNED LONG LONG INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | LONG LONG UNSIGNED INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "long long"); } | SHORT INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT SIGNED_KEYWORD INT_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } | UNSIGNED SHORT INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "short"); } | SHORT UNSIGNED INT_KEYWORD { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "short"); } | DOUBLE_KEYWORD { $$ = lookup_typename (pstate->language (), - pstate->gdbarch (), "double", NULL, 0); } | LONG DOUBLE_KEYWORD { $$ = lookup_typename (pstate->language (), - pstate->gdbarch (), "long double", NULL, 0); } | STRUCT name { $$ - = lookup_struct (copy_name ($2), + = lookup_struct (copy_name ($2).c_str (), pstate->expression_context_block); } | STRUCT COMPLETE @@ -1427,7 +1413,8 @@ typebase } | CLASS name { $$ = lookup_struct - (copy_name ($2), pstate->expression_context_block); + (copy_name ($2).c_str (), + pstate->expression_context_block); } | CLASS COMPLETE { @@ -1443,7 +1430,7 @@ typebase } | UNION name { $$ - = lookup_union (copy_name ($2), + = lookup_union (copy_name ($2).c_str (), pstate->expression_context_block); } | UNION COMPLETE @@ -1459,7 +1446,7 @@ typebase $$ = NULL; } | ENUM name - { $$ = lookup_enum (copy_name ($2), + { $$ = lookup_enum (copy_name ($2).c_str (), pstate->expression_context_block); } | ENUM COMPLETE @@ -1475,31 +1462,27 @@ typebase } | UNSIGNED type_name { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), TYPE_NAME($2.type)); } | UNSIGNED { $$ = lookup_unsigned_typename (pstate->language (), - pstate->gdbarch (), "int"); } | SIGNED_KEYWORD type_name { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), TYPE_NAME($2.type)); } | SIGNED_KEYWORD { $$ = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "int"); } /* It appears that this rule for templates is never reduced; template recognition happens by lookahead in the token processing code in yylex. */ | TEMPLATE name '<' type '>' { $$ = lookup_template_type - (copy_name($2), $4, + (copy_name($2).c_str (), $4, pstate->expression_context_block); } - | const_or_volatile_or_space_identifier_noopt typebase + | qualifier_seq_noopt typebase { $$ = cpstate->type_stack.follow_types ($2); } - | typebase const_or_volatile_or_space_identifier_noopt + | typebase qualifier_seq_noopt { $$ = cpstate->type_stack.follow_types ($1); } ; @@ -1509,7 +1492,6 @@ type_name: TYPENAME $$.stoken.ptr = "int"; $$.stoken.length = 3; $$.type = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "int"); } | LONG @@ -1517,7 +1499,6 @@ type_name: TYPENAME $$.stoken.ptr = "long"; $$.stoken.length = 4; $$.type = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "long"); } | SHORT @@ -1525,7 +1506,6 @@ type_name: TYPENAME $$.stoken.ptr = "short"; $$.stoken.length = 5; $$.type = lookup_signed_typename (pstate->language (), - pstate->gdbarch (), "short"); } ; @@ -2373,11 +2353,15 @@ enum token_flag FLAG_CXX = 1, + /* If this bit is set, the token is C-only. */ + + FLAG_C = 2, + /* If this bit is set, the token is conditional: if there is a symbol of the same name, then the token is a symbol; otherwise, the token is a keyword. */ - FLAG_SHADOW = 2 + FLAG_SHADOW = 4 }; DEF_ENUM_FLAGS_TYPE (enum token_flag, token_flags); @@ -2444,6 +2428,10 @@ static const struct token ident_tokens[] = {"union", UNION, OP_NULL, 0}, {"short", SHORT, OP_NULL, 0}, {"const", CONST_KEYWORD, OP_NULL, 0}, + {"restrict", RESTRICT, OP_NULL, FLAG_C | FLAG_SHADOW}, + {"__restrict__", RESTRICT, OP_NULL, 0}, + {"__restrict", RESTRICT, OP_NULL, 0}, + {"_Atomic", ATOMIC, OP_NULL, 0}, {"enum", ENUM, OP_NULL, 0}, {"long", LONG, OP_NULL, 0}, {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX}, @@ -2482,15 +2470,14 @@ static const struct token ident_tokens[] = static void scan_macro_expansion (char *expansion) { - char *copy; + const char *copy; /* We'd better not be trying to push the stack twice. */ gdb_assert (! cpstate->macro_original_text); /* Copy to the obstack, and then free the intermediate expansion. */ - copy = (char *) obstack_copy0 (&cpstate->expansion_obstack, expansion, - strlen (expansion)); + copy = obstack_strdup (&cpstate->expansion_obstack, expansion); xfree (expansion); /* Save the old lexptr value, so we can return to it when we're done @@ -2552,7 +2539,6 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) unsigned int i; const char *tokstart; bool saw_structop = last_was_structop; - char *copy; last_was_structop = false; *is_quoted_name = false; @@ -2580,6 +2566,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if ((tokentab3[i].flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + gdb_assert ((tokentab3[i].flags & FLAG_C) == 0); pstate->lexptr += 3; yylval.opcode = tokentab3[i].opcode; @@ -2593,6 +2580,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if ((tokentab2[i].flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + gdb_assert ((tokentab3[i].flags & FLAG_C) == 0); pstate->lexptr += 2; yylval.opcode = tokentab2[i].opcode; @@ -2880,19 +2868,23 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) yylval.sval.length = namelen; /* Catch specific keywords. */ - copy = copy_name (yylval.sval); + std::string copy = copy_name (yylval.sval); for (i = 0; i < sizeof ident_tokens / sizeof ident_tokens[0]; i++) - if (strcmp (copy, ident_tokens[i].oper) == 0) + if (copy == ident_tokens[i].oper) { if ((ident_tokens[i].flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + if ((ident_tokens[i].flags & FLAG_C) != 0 + && par_state->language ()->la_language != language_c + && par_state->language ()->la_language != language_objc) + break; if ((ident_tokens[i].flags & FLAG_SHADOW) != 0) { struct field_of_this_result is_a_field_of_this; - if (lookup_symbol (copy, + if (lookup_symbol (copy.c_str (), pstate->expression_context_block, VAR_DOMAIN, (par_state->language ()->la_language @@ -2954,16 +2946,15 @@ classify_name (struct parser_state *par_state, const struct block *block, bool is_quoted_name, bool is_after_structop) { struct block_symbol bsym; - char *copy; struct field_of_this_result is_a_field_of_this; - copy = copy_name (yylval.sval); + std::string copy = copy_name (yylval.sval); /* Initialize this in case we *don't* use it in this call; that way we can refer to it unconditionally below. */ memset (&is_a_field_of_this, 0, sizeof (is_a_field_of_this)); - bsym = lookup_symbol (copy, block, VAR_DOMAIN, + bsym = lookup_symbol (copy.c_str (), block, VAR_DOMAIN, par_state->language ()->la_name_of_this ? &is_a_field_of_this : NULL); @@ -2986,7 +2977,7 @@ classify_name (struct parser_state *par_state, const struct block *block, { struct field_of_this_result inner_is_a_field_of_this; - bsym = lookup_symbol (copy, block, STRUCT_DOMAIN, + bsym = lookup_symbol (copy.c_str (), block, STRUCT_DOMAIN, &inner_is_a_field_of_this); if (bsym.symbol != NULL) { @@ -3006,7 +2997,7 @@ classify_name (struct parser_state *par_state, const struct block *block, /* See if it's a file name. */ struct symtab *symtab; - symtab = lookup_symtab (copy); + symtab = lookup_symtab (copy.c_str ()); if (symtab) { yylval.bval = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), @@ -3025,13 +3016,14 @@ classify_name (struct parser_state *par_state, const struct block *block, /* See if it's an ObjC classname. */ if (par_state->language ()->la_language == language_objc && !bsym.symbol) { - CORE_ADDR Class = lookup_objc_class (par_state->gdbarch (), copy); + CORE_ADDR Class = lookup_objc_class (par_state->gdbarch (), + copy.c_str ()); if (Class) { struct symbol *sym; yylval.theclass.theclass = Class; - sym = lookup_struct_typedef (copy, + sym = lookup_struct_typedef (copy.c_str (), par_state->expression_context_block, 1); if (sym) yylval.theclass.type = SYMBOL_TYPE (sym); @@ -3047,7 +3039,7 @@ classify_name (struct parser_state *par_state, const struct block *block, || (copy[0] >= 'A' && copy[0] < 'A' + input_radix - 10))) { YYSTYPE newlval; /* Its value is ignored. */ - int hextype = parse_number (par_state, copy, yylval.sval.length, + int hextype = parse_number (par_state, copy.c_str (), yylval.sval.length, 0, &newlval); if (hextype == INT) @@ -3065,7 +3057,7 @@ classify_name (struct parser_state *par_state, const struct block *block, if (bsym.symbol == NULL && par_state->language ()->la_language == language_cplus && is_a_field_of_this.type == NULL - && lookup_minimal_symbol (copy, NULL, NULL).minsym == NULL) + && lookup_minimal_symbol (copy.c_str (), NULL, NULL).minsym == NULL) return UNKNOWN_CPP_NAME; return NAME; @@ -3080,7 +3072,6 @@ classify_inner_name (struct parser_state *par_state, const struct block *block, struct type *context) { struct type *type; - char *copy; if (context == NULL) return classify_name (par_state, block, false, false); @@ -3089,16 +3080,18 @@ classify_inner_name (struct parser_state *par_state, if (!type_aggregate_p (type)) return ERROR; - copy = copy_name (yylval.ssym.stoken); + std::string copy = copy_name (yylval.ssym.stoken); /* N.B. We assume the symbol can only be in VAR_DOMAIN. */ - yylval.ssym.sym = cp_lookup_nested_symbol (type, copy, block, VAR_DOMAIN); + yylval.ssym.sym = cp_lookup_nested_symbol (type, copy.c_str (), block, + VAR_DOMAIN); /* If no symbol was found, search for a matching base class named COPY. This will allow users to enter qualified names of class members relative to the `this' pointer. */ if (yylval.ssym.sym.symbol == NULL) { - struct type *base_type = cp_find_type_baseclass_by_name (type, copy); + struct type *base_type = cp_find_type_baseclass_by_name (type, + copy.c_str ()); if (base_type != NULL) { @@ -3117,7 +3110,8 @@ classify_inner_name (struct parser_state *par_state, named COPY when we really wanted a base class of the same name. Double-check this case by looking for a base class. */ { - struct type *base_type = cp_find_type_baseclass_by_name (type, copy); + struct type *base_type + = cp_find_type_baseclass_by_name (type, copy.c_str ()); if (base_type != NULL) { @@ -3283,9 +3277,9 @@ yylex (void) if (checkpoint > 0) { current.value.sval.ptr - = (const char *) obstack_copy0 (&cpstate->expansion_obstack, - current.value.sval.ptr, - current.value.sval.length); + = obstack_strndup (&cpstate->expansion_obstack, + current.value.sval.ptr, + current.value.sval.length); token_fifo[0] = current; if (checkpoint > 1) @@ -3369,13 +3363,13 @@ c_print_token (FILE *file, int type, YYSTYPE value) case NSSTRING: case DOLLAR_VARIABLE: - parser_fprintf (file, "sval<%s>", copy_name (value.sval)); + parser_fprintf (file, "sval<%s>", copy_name (value.sval).c_str ()); break; case TYPENAME: parser_fprintf (file, "tsym", TYPE_SAFE_NAME (value.tsym.type), - copy_name (value.tsym.stoken)); + copy_name (value.tsym.stoken).c_str ()); break; case NAME: @@ -3383,9 +3377,9 @@ c_print_token (FILE *file, int type, YYSTYPE value) case NAME_OR_INT: case BLOCKNAME: parser_fprintf (file, "ssym", - copy_name (value.ssym.stoken), + copy_name (value.ssym.stoken).c_str (), (value.ssym.sym.symbol == NULL - ? "(null)" : SYMBOL_PRINT_NAME (value.ssym.sym.symbol)), + ? "(null)" : value.ssym.sym.symbol->print_name ()), value.ssym.is_a_field_of_this); break;