* [PATCH] implement support for "enum class" @ 2014-03-27 20:12 Tom Tromey 2014-03-28 11:21 ` Mark Wielaard 0 siblings, 1 reply; 8+ messages in thread From: Tom Tromey @ 2014-03-27 20:12 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey This adds support for the C++11 "enum class" feature. This is PR c++/15246. I chose to use the existing TYPE_DECLARED_CLASS rather than introduce a new type code. This seemed both simple and clear to me. I made overloading support for the new enum types strict. This is how it works in C++; and it didn't seem like an undue burden to keep this, particularly because enum constants are printed symbolically by gdb. Built and regtested on x86-64 Fedora 20. 2014-03-27 Tom Tromey <tromey@redhat.com> PR c++/15246: * c-exp.y (type_aggregate_p): New function. (qualified_name, classify_inner_name): Use it. * c-typeprint.c (c_type_print_base): Handle TYPE_DECLARED_CLASS and TYPE_TARGET_TYPE of an enum type. * dwarf2read.c (read_enumeration_type): Set TYPE_DECLARED_CLASS on an enum type. (determine_prefix) <case DW_TAG_enumeration_type>: New case; handle TYPE_DECLARED_CLASS. * gdbtypes.c (rank_one_type): Handle TYPE_DECLARED_CLASS on enum types. * gdbtypes.h (TYPE_DECLARED_CLASS): Update comment. * valops.c (enum_constant_from_type): New function. (value_aggregate_elt): Use it. * cp-namespace.c (cp_lookup_nested_symbol): Handle TYPE_CODE_ENUM. 2014-03-27 Tom Tromey <tromey@redhat.com> * gdb.cp/enumclass.exp: New file. * gdb.cp/enumclass.cc: New file. --- gdb/ChangeLog | 19 +++++++++++++++ gdb/c-exp.y | 26 ++++++++++++++------- gdb/c-typeprint.c | 10 ++++++++ gdb/cp-namespace.c | 1 + gdb/dwarf2read.c | 11 +++++++++ gdb/gdbtypes.c | 6 +++++ gdb/gdbtypes.h | 6 +++-- gdb/testsuite/ChangeLog | 5 ++++ gdb/testsuite/gdb.cp/enumclass.cc | 46 ++++++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/enumclass.exp | 48 ++++++++++++++++++++++++++++++++++++++ gdb/valops.c | 40 +++++++++++++++++++++++++++++++ 11 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/enumclass.cc create mode 100644 gdb/testsuite/gdb.cp/enumclass.exp diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 11631ba..53af59b 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -124,6 +124,8 @@ static int yylex (void); void yyerror (char *); +static int type_aggregate_p (struct type *); + %} /* Although the yacc "value" of an expression is not used, @@ -957,9 +959,7 @@ qualified_name: TYPENAME COLONCOLON name { struct type *type = $1.type; CHECK_TYPEDEF (type); - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION - && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + if (!type_aggregate_p (type)) error (_("`%s' is not defined as an aggregate type."), TYPE_SAFE_NAME (type)); @@ -975,9 +975,7 @@ qualified_name: TYPENAME COLONCOLON name char *buf; CHECK_TYPEDEF (type); - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION - && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + if (!type_aggregate_p (type)) error (_("`%s' is not defined as an aggregate type."), TYPE_SAFE_NAME (type)); buf = alloca ($4.length + 2); @@ -1668,6 +1666,18 @@ operator_stoken (const char *op) return st; }; +/* Return true if the type is aggregate-like. */ + +static int +type_aggregate_p (struct type *type) +{ + return (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE + || (TYPE_CODE (type) == TYPE_CODE_ENUM + && TYPE_DECLARED_CLASS (type))); +} + /* Validate a parameter typelist. */ static void @@ -2955,9 +2965,7 @@ classify_inner_name (const struct block *block, struct type *context) return classify_name (block, 0); type = check_typedef (context); - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION - && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + if (!type_aggregate_p (type)) return ERROR; copy = copy_name (yylval.ssym.stoken); diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 4edc9ec..04b6d7b 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -1324,6 +1324,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, case TYPE_CODE_ENUM: c_type_print_modifier (type, stream, 0, 1); fprintf_filtered (stream, "enum "); + if (TYPE_DECLARED_CLASS (type)) + fprintf_filtered (stream, "class "); /* Print the tag name if it exists. The aCC compiler emits a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}" @@ -1349,6 +1351,14 @@ c_type_print_base (struct type *type, struct ui_file *stream, { LONGEST lastval = 0; + if (TYPE_TARGET_TYPE (type) != NULL) + { + struct type *underlying = check_typedef (TYPE_TARGET_TYPE (type)); + + if (TYPE_NAME (underlying) != NULL) + fprintf_filtered (stream, ": %s ", TYPE_NAME (underlying)); + } + fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); for (i = 0; i < len; i++) diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 74ccd45..03eb6a9 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -812,6 +812,7 @@ cp_lookup_nested_symbol (struct type *parent_type, case TYPE_CODE_STRUCT: case TYPE_CODE_NAMESPACE: case TYPE_CODE_UNION: + case TYPE_CODE_ENUM: /* NOTE: Handle modules here as well, because Fortran is re-using the C++ specific code to lookup nested symbols in modules, by calling the function pointer la_lookup_symbol_nonlocal, which ends up here. */ diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index cc50f63..83c403a 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -13269,6 +13269,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type)); } + TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu); + return set_die_type (die, type, cu); } @@ -18611,6 +18613,15 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) return name; } return ""; + case DW_TAG_enumeration_type: + parent_type = read_type_die (parent, cu); + if (TYPE_DECLARED_CLASS (parent_type)) + { + if (TYPE_TAG_NAME (parent_type) != NULL) + return TYPE_TAG_NAME (parent_type); + return ""; + } + /* Fall through. */ default: return determine_prefix (parent, cu); } diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 98cb873..8feb745 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2947,6 +2947,8 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value) case TYPE_CODE_CHAR: case TYPE_CODE_RANGE: case TYPE_CODE_BOOL: + if (TYPE_DECLARED_CLASS (arg)) + return INCOMPATIBLE_TYPE_BADNESS; return INTEGER_PROMOTION_BADNESS; case TYPE_CODE_FLT: return INT_FLOAT_CONVERSION_BADNESS; @@ -2964,6 +2966,8 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value) case TYPE_CODE_RANGE: case TYPE_CODE_BOOL: case TYPE_CODE_ENUM: + if (TYPE_DECLARED_CLASS (parm) || TYPE_DECLARED_CLASS (arg)) + return INCOMPATIBLE_TYPE_BADNESS; return INTEGER_CONVERSION_BADNESS; case TYPE_CODE_FLT: return INT_FLOAT_CONVERSION_BADNESS; @@ -2977,6 +2981,8 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value) case TYPE_CODE_RANGE: case TYPE_CODE_BOOL: case TYPE_CODE_ENUM: + if (TYPE_DECLARED_CLASS (arg)) + return INCOMPATIBLE_TYPE_BADNESS; return INTEGER_CONVERSION_BADNESS; case TYPE_CODE_FLT: return INT_FLOAT_CONVERSION_BADNESS; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index c6943ef..9599e1c 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -330,8 +330,10 @@ enum type_instance_flag_value #define TYPE_OBJFILE(t) (TYPE_OBJFILE_OWNED(t)? TYPE_OWNER(t).objfile : NULL) /* * True if this type was declared using the "class" keyword. This is - only valid for C++ structure types, and only used for displaying - the type. If false, the structure was declared as a "struct". */ + only valid for C++ structure and enum types. If false, a structure + was declared as a "struct"; if true it was declared "class". For + enum types, this is true when "enum class" or "enum struct" was + used to declare the type.. */ #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class) diff --git a/gdb/testsuite/gdb.cp/enumclass.cc b/gdb/testsuite/gdb.cp/enumclass.cc new file mode 100644 index 0000000..bddfbbb --- /dev/null +++ b/gdb/testsuite/gdb.cp/enumclass.cc @@ -0,0 +1,46 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +enum class E1 { + HI = 7, THERE +}; + +enum class E2 { + HI = 23, THERE +}; + +// overload1(E1::HI) is ok. +// overload1(77) is ok. +int overload1 (int v) { return 0; } +int overload1 (E1 v) { return static_cast<int> (v); } +int overload1 (E2 v) { return - static_cast<int> (v); } + +// overload2(E1::HI) is ok. +// overload1(77) fails. +int overload2 (E1 v) { return static_cast<int> (v); } +int overload2 (E2 v) { return - static_cast<int> (v); } + +// overload3(E1::HI) fails. +// overload1(77) is ok. +int overload3 (int v) { return 0; } +int overload3 (E2 v) { return static_cast<int> (v); } + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.cp/enumclass.exp b/gdb/testsuite/gdb.cp/enumclass.exp new file mode 100644 index 0000000..eed06ec --- /dev/null +++ b/gdb/testsuite/gdb.cp/enumclass.exp @@ -0,0 +1,48 @@ +# Copyright 2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite + +if {[skip_cplus_tests]} { continue } + +standard_testfile .cc + +if {[prepare_for_testing $testfile.exp $testfile $srcfile \ + {debug c++ additional_flags=-std=c++11}]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +gdb_test "ptype E1" \ + "type = enum class E1 {E1::HI = 7, E1::THERE}" + +gdb_test "print E1::HI" " = E1::HI" +gdb_test "print (int) E1::HI" " = 7" +gdb_test "print (int) E2::HI" " = 23" +gdb_test "print HI" "No symbol .HI.*" + +gdb_test "print overload1(E1::THERE)" " = 8" +gdb_test "print overload1(77)" " = 0" + +gdb_test "print overload2(E1::THERE)" " = 8" +gdb_test "print overload2(77)" \ + "Cannot resolve function overload2 to any overloaded instance" + +gdb_test "print overload3(E1::THERE)" \ + "Cannot resolve function overload3 to any overloaded instance" +gdb_test "print overload3(77)" " = 0" diff --git a/gdb/valops.c b/gdb/valops.c index a10dbd6..e59e075 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -3007,6 +3007,42 @@ destructor_name_p (const char *name, struct type *type) return 0; } +/* Find an enum constant named NAME in TYPE. TYPE must be an "enum + class". If the name is found, return a value representing it; + otherwise throw an exception. */ + +static struct value * +enum_constant_from_type (struct type *type, const char *name) +{ + int i; + int name_len = strlen (name); + + gdb_assert (TYPE_CODE (type) == TYPE_CODE_ENUM + && TYPE_DECLARED_CLASS (type)); + + for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); ++i) + { + const char *fname = TYPE_FIELD_NAME (type, i); + int len; + + if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_ENUMVAL + || fname == NULL) + continue; + + /* Look for the trailing "::NAME", since enum class constant + names are qualified here. */ + len = strlen (fname); + if (len + 2 >= name_len + && fname[len - name_len - 2] == ':' + && fname[len - name_len - 1] == ':' + && strcmp (&fname[len - name_len], name) == 0) + return value_from_longest (type, TYPE_FIELD_ENUMVAL (type, i)); + } + + error (_("no constant named \"%s\" in enum \"%s\""), + name, TYPE_TAG_NAME (type)); +} + /* C++: Given an aggregate type CURTYPE, and a member name NAME, return the appropriate member (or the address of the member, if WANT_ADDRESS). This function is used to resolve user expressions @@ -3028,6 +3064,10 @@ value_aggregate_elt (struct type *curtype, const char *name, case TYPE_CODE_NAMESPACE: return value_namespace_elt (curtype, name, want_address, noside); + + case TYPE_CODE_ENUM: + return enum_constant_from_type (curtype, name); + default: internal_error (__FILE__, __LINE__, _("non-aggregate type in value_aggregate_elt")); -- 1.8.5.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-03-27 20:12 [PATCH] implement support for "enum class" Tom Tromey @ 2014-03-28 11:21 ` Mark Wielaard 2014-03-31 4:38 ` Tom Tromey 0 siblings, 1 reply; 8+ messages in thread From: Mark Wielaard @ 2014-03-28 11:21 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Thu, 2014-03-27 at 14:11 -0600, Tom Tromey wrote: > This adds support for the C++11 "enum class" feature. This is > PR c++/15246. > > I chose to use the existing TYPE_DECLARED_CLASS rather than introduce > a new type code. This seemed both simple and clear to me. > > I made overloading support for the new enum types strict. This is how > it works in C++; and it didn't seem like an undue burden to keep this, > particularly because enum constants are printed symbolically by gdb. > > Built and regtested on x86-64 Fedora 20. > [...] > +gdb_test "ptype E1" \ > + "type = enum class E1 {E1::HI = 7, E1::THERE}" This FAILs for me with gcc plus http://gcc.gnu.org/ml/gcc-patches/2014-03/msg01448.html because it will derive: Breakpoint 1, main () at /home/mark/src/binutils-gdb/gdb/testsuite/gdb.cp/enumclass.cc:45 45 return 0; (gdb) ptype E1 type = enum class E1 : int {E1::HI = 7, E1::THERE} Note the : int. I think this comes from: diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c > index 4edc9ec..04b6d7b 100644 > --- a/gdb/c-typeprint.c > +++ b/gdb/c-typeprint.c > [...] > @@ -1349,6 +1351,14 @@ c_type_print_base (struct type *type, struct ui_file *stream, > { > LONGEST lastval = 0; > > + if (TYPE_TARGET_TYPE (type) != NULL) > + { > + struct type *underlying = check_typedef (TYPE_TARGET_TYPE (type)); > + > + if (TYPE_NAME (underlying) != NULL) > + fprintf_filtered (stream, ": %s ", TYPE_NAME (underlying)); > + } > + > fprintf_filtered (stream, "{"); > len = TYPE_NFIELDS (type); > for (i = 0; i < len; i++) If the test is right then I think you don't want to print the underlying type if DW_AT_enum_class is set and the enum has type safe semantics? Maybe: diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 04b6d7b..299d859 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -1351,7 +1351,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, { LONGEST lastval = 0; - if (TYPE_TARGET_TYPE (type) != NULL) + if (TYPE_TARGET_TYPE (type) != NULL && ! TYPE_DECLARED_CLASS (type)) { struct type *underlying = check_typedef (TYPE_TARGET_TYPE (type)); Cheers, Mark ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-03-28 11:21 ` Mark Wielaard @ 2014-03-31 4:38 ` Tom Tromey 2014-03-31 7:16 ` Mark Wielaard 0 siblings, 1 reply; 8+ messages in thread From: Tom Tromey @ 2014-03-31 4:38 UTC (permalink / raw) To: Mark Wielaard; +Cc: gdb-patches >>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes: >> +gdb_test "ptype E1" \ >> + "type = enum class E1 {E1::HI = 7, E1::THERE}" Mark> This FAILs for me with gcc plus Mark> http://gcc.gnu.org/ml/gcc-patches/2014-03/msg01448.html Thanks Mark. Mark> (gdb) ptype E1 Mark> type = enum class E1 : int {E1::HI = 7, E1::THERE} Mark> Note the : int. [...] Mark> If the test is right then I think you don't want to print the underlying Mark> type if DW_AT_enum_class is set and the enum has type safe semantics? I'm not totally sure what to do. It seems that without extra information there is no perfect answer. At least this code should (most likely) only print the ": type" part for C++, not for C. That was an oversight in the original patch. This may omit some information from the C case, but on the other hand at least the output won't be gratuitously non-C. I was anticipating that GCC would emit an unnamed type for the underlying type in the case where the underlying type is not specified in the source. However I can see why it would not necessarily do this, and certainly there's no requirement in DWARF along these lines. One option might be to have the DWARF reader omit the underlying type when the type it guessed from the enum values agreed with the type specified in DW_AT_type. Of course that's just a heuristic. It's perhaps better, I think, to just always emit the bits even if they are in some sense redundant. In C++11, whether an underlying type is specified is orthogonal to whether the enum is an "enum class". "enum x : short" is perfectly ok. Tom ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-03-31 4:38 ` Tom Tromey @ 2014-03-31 7:16 ` Mark Wielaard 2014-03-31 18:19 ` Tom Tromey 0 siblings, 1 reply; 8+ messages in thread From: Mark Wielaard @ 2014-03-31 7:16 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches Hi Tom, On Sun, 2014-03-30 at 22:38 -0600, Tom Tromey wrote: > >>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes: > Mark> If the test is right then I think you don't want to print the underlying > Mark> type if DW_AT_enum_class is set and the enum has type safe semantics? > > I'm not totally sure what to do. It seems that without extra > information there is no perfect answer. > > At least this code should (most likely) only print the ": type" part for > C++, not for C. That was an oversight in the original patch. This may > omit some information from the C case, but on the other hand at least > the output won't be gratuitously non-C. Yes, that seems to be the right way, if you want to print the type as something that is a valid expression. Note that the underlying type in C is almost always just "int", except when using -fshort-enums then GCC uses the smallest representation like C++. > I was anticipating that GCC would emit an unnamed type for the > underlying type in the case where the underlying type is not specified > in the source. However I can see why it would not necessarily do this, > and certainly there's no requirement in DWARF along these lines. Funny. You pointed out my original patch accidentally did this sometimes. Causing lots of extra base type DIEs. I indeed fixed this to emit the already known base type in the CU (which often is the named int base type) to reduce duplication. I think this is the correct thing to do. > One option might be to have the DWARF reader omit the underlying type > when the type it guessed from the enum values agreed with the type > specified in DW_AT_type. Of course that's just a heuristic. It's > perhaps better, I think, to just always emit the bits even if they are > in some sense redundant. > > In C++11, whether an underlying type is specified is orthogonal to > whether the enum is an "enum class". "enum x : short" is perfectly ok. Aha, you are right. And there is no way to know from the DWARF whether the compiler derived the underlying type or the user explicitly defined it. I am also not sure what the right thing to do is here. But I think it makes sense to make printing it depend on the language used and always print it when the language supports "derived enums" whether the user explicitly defined it or it was guessed by the compiler. It is an valid expression in any case and the GDB user might appreciate the extra info (in the case of C++). Cheers, Mark ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-03-31 7:16 ` Mark Wielaard @ 2014-03-31 18:19 ` Tom Tromey 2014-04-14 18:07 ` Tom Tromey 2014-05-21 14:04 ` Mark Wielaard 0 siblings, 2 replies; 8+ messages in thread From: Tom Tromey @ 2014-03-31 18:19 UTC (permalink / raw) To: Mark Wielaard; +Cc: gdb-patches Tom> I was anticipating that GCC would emit an unnamed type for the Tom> underlying type in the case where the underlying type is not specified Tom> in the source. However I can see why it would not necessarily do this, Tom> and certainly there's no requirement in DWARF along these lines. Mark> Funny. You pointed out my original patch accidentally did this Mark> sometimes. Causing lots of extra base type DIEs. I indeed fixed this to Mark> emit the already known base type in the CU (which often is the named int Mark> base type) to reduce duplication. I think this is the correct thing to Mark> do. Yeah, I didn't realize that the fix would cause this. Actually at the time the duplicated DIEs were all nameless, so adding a name is a further wrinkle; but not invalid. Mark> I am also not sure what the right thing to do is here. But I think it Mark> makes sense to make printing it depend on the language used and always Mark> print it when the language supports "derived enums" whether the user Mark> explicitly defined it or it was guessed by the compiler. It is an valid Mark> expression in any case and the GDB user might appreciate the extra info Mark> (in the case of C++). I went this route. Here's a new patch, this one regtested on x86-64 Fedora 20 against both the system compiler and a GCC with your enum patches applied. I had to update gdb.cp/classes.exp and I added a new test as well. Tom diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e4e5db8..00b1231 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2014-03-31 Tom Tromey <tromey@redhat.com> + + PR c++/15246: + * c-exp.y (type_aggregate_p): New function. + (qualified_name, classify_inner_name): Use it. + * c-typeprint.c (c_type_print_base): Handle TYPE_DECLARED_CLASS + and TYPE_TARGET_TYPE of an enum type. + * dwarf2read.c (read_enumeration_type): Set TYPE_DECLARED_CLASS on + an enum type. + (determine_prefix) <case DW_TAG_enumeration_type>: New case; + handle TYPE_DECLARED_CLASS. + * gdbtypes.c (rank_one_type): Handle TYPE_DECLARED_CLASS on enum + types. + * gdbtypes.h (TYPE_DECLARED_CLASS): Update comment. + * valops.c (enum_constant_from_type): New function. + (value_aggregate_elt): Use it. + * cp-namespace.c (cp_lookup_nested_symbol): Handle + TYPE_CODE_ENUM. + 2014-03-27 Tom Tromey <tromey@redhat.com> * valops.c (value_aggregate_elt, value_struct_elt_for_reference) diff --git a/gdb/c-exp.y b/gdb/c-exp.y index fc79807..01af9dd 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -129,6 +129,8 @@ static int yylex (void); void yyerror (char *); +static int type_aggregate_p (struct type *); + %} /* Although the yacc "value" of an expression is not used, @@ -978,9 +980,7 @@ qualified_name: TYPENAME COLONCOLON name { struct type *type = $1.type; CHECK_TYPEDEF (type); - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION - && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + if (!type_aggregate_p (type)) error (_("`%s' is not defined as an aggregate type."), TYPE_SAFE_NAME (type)); @@ -996,9 +996,7 @@ qualified_name: TYPENAME COLONCOLON name char *buf; CHECK_TYPEDEF (type); - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION - && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + if (!type_aggregate_p (type)) error (_("`%s' is not defined as an aggregate type."), TYPE_SAFE_NAME (type)); buf = alloca ($4.length + 2); @@ -1693,6 +1691,18 @@ operator_stoken (const char *op) return st; }; +/* Return true if the type is aggregate-like. */ + +static int +type_aggregate_p (struct type *type) +{ + return (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE + || (TYPE_CODE (type) == TYPE_CODE_ENUM + && TYPE_DECLARED_CLASS (type))); +} + /* Validate a parameter typelist. */ static void @@ -2992,9 +3002,7 @@ classify_inner_name (struct parser_state *par_state, return classify_name (par_state, block, 0); type = check_typedef (context); - if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION - && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + if (!type_aggregate_p (type)) return ERROR; copy = copy_name (yylval.ssym.stoken); diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 4edc9ec..3d647da 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -1324,6 +1324,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, case TYPE_CODE_ENUM: c_type_print_modifier (type, stream, 0, 1); fprintf_filtered (stream, "enum "); + if (TYPE_DECLARED_CLASS (type)) + fprintf_filtered (stream, "class "); /* Print the tag name if it exists. The aCC compiler emits a spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}" @@ -1349,6 +1351,23 @@ c_type_print_base (struct type *type, struct ui_file *stream, { LONGEST lastval = 0; + /* We can't handle this case perfectly, as DWARF does not + tell us whether or not the underlying type was specified + in the source (and other debug formats don't provide this + at all). We choose to print the underlying type, if it + has a name, when in C++ on the theory that it's better to + print too much than too little; but conversely not to + print something egregiously outside the current + language's syntax. */ + if (current_language->la_language == language_cplus + && TYPE_TARGET_TYPE (type) != NULL) + { + struct type *underlying = check_typedef (TYPE_TARGET_TYPE (type)); + + if (TYPE_NAME (underlying) != NULL) + fprintf_filtered (stream, ": %s ", TYPE_NAME (underlying)); + } + fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); for (i = 0; i < len; i++) diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 74ccd45..03eb6a9 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -812,6 +812,7 @@ cp_lookup_nested_symbol (struct type *parent_type, case TYPE_CODE_STRUCT: case TYPE_CODE_NAMESPACE: case TYPE_CODE_UNION: + case TYPE_CODE_ENUM: /* NOTE: Handle modules here as well, because Fortran is re-using the C++ specific code to lookup nested symbols in modules, by calling the function pointer la_lookup_symbol_nonlocal, which ends up here. */ diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 964c956..ccbd55f 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -13269,6 +13269,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type)); } + TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu); + return set_die_type (die, type, cu); } @@ -18611,6 +18613,15 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) return name; } return ""; + case DW_TAG_enumeration_type: + parent_type = read_type_die (parent, cu); + if (TYPE_DECLARED_CLASS (parent_type)) + { + if (TYPE_TAG_NAME (parent_type) != NULL) + return TYPE_TAG_NAME (parent_type); + return ""; + } + /* Fall through. */ default: return determine_prefix (parent, cu); } diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 98cb873..8feb745 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2947,6 +2947,8 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value) case TYPE_CODE_CHAR: case TYPE_CODE_RANGE: case TYPE_CODE_BOOL: + if (TYPE_DECLARED_CLASS (arg)) + return INCOMPATIBLE_TYPE_BADNESS; return INTEGER_PROMOTION_BADNESS; case TYPE_CODE_FLT: return INT_FLOAT_CONVERSION_BADNESS; @@ -2964,6 +2966,8 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value) case TYPE_CODE_RANGE: case TYPE_CODE_BOOL: case TYPE_CODE_ENUM: + if (TYPE_DECLARED_CLASS (parm) || TYPE_DECLARED_CLASS (arg)) + return INCOMPATIBLE_TYPE_BADNESS; return INTEGER_CONVERSION_BADNESS; case TYPE_CODE_FLT: return INT_FLOAT_CONVERSION_BADNESS; @@ -2977,6 +2981,8 @@ rank_one_type (struct type *parm, struct type *arg, struct value *value) case TYPE_CODE_RANGE: case TYPE_CODE_BOOL: case TYPE_CODE_ENUM: + if (TYPE_DECLARED_CLASS (arg)) + return INCOMPATIBLE_TYPE_BADNESS; return INTEGER_CONVERSION_BADNESS; case TYPE_CODE_FLT: return INT_FLOAT_CONVERSION_BADNESS; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index c6943ef..9599e1c 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -330,8 +330,10 @@ enum type_instance_flag_value #define TYPE_OBJFILE(t) (TYPE_OBJFILE_OWNED(t)? TYPE_OWNER(t).objfile : NULL) /* * True if this type was declared using the "class" keyword. This is - only valid for C++ structure types, and only used for displaying - the type. If false, the structure was declared as a "struct". */ + only valid for C++ structure and enum types. If false, a structure + was declared as a "struct"; if true it was declared "class". For + enum types, this is true when "enum class" or "enum struct" was + used to declare the type.. */ #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 0711f14..b8de0e3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,13 @@ 2014-03-31 Tom Tromey <tromey@redhat.com> + * gdb.cp/classes.exp (test_enums): Handle underlying type. + * gdb.dwarf2/enum-type.exp: Add test for enum with underlying + type. + * gdb.cp/enum-class.exp: New file. + * gdb.cp/enum-class.cc: New file. + +2014-03-31 Tom Tromey <tromey@redhat.com> + * gdb.dwarf2/enum-type.exp: New file. 2014-03-31 Yao Qi <yao@codesourcery.com> diff --git a/gdb/testsuite/gdb.cp/classes.exp b/gdb/testsuite/gdb.cp/classes.exp index 7c1a5d1..0141e3a 100644 --- a/gdb/testsuite/gdb.cp/classes.exp +++ b/gdb/testsuite/gdb.cp/classes.exp @@ -410,7 +410,7 @@ proc test_enums {} { # ptype on the enum member gdb_test_multiple "ptype obj_with_enum.priv_enum" "ptype obj_with_enum.priv_enum" { - -re "type = enum ClassWithEnum::PrivEnum \{ ?(ClassWithEnum::)?red, (ClassWithEnum::)?green, (ClassWithEnum::)?blue, (ClassWithEnum::)?yellow = 42 ?\}$nl$gdb_prompt $" { + -re "type = enum ClassWithEnum::PrivEnum (: unsigned int )?\{ ?(ClassWithEnum::)?red, (ClassWithEnum::)?green, (ClassWithEnum::)?blue, (ClassWithEnum::)?yellow = 42 ?\}$nl$gdb_prompt $" { pass "ptype obj_with_enum.priv_enum" } -re "type = enum PrivEnum \{ ?(ClassWithEnum::)?red, (ClassWithEnum::)?green, (ClassWithEnum::)?blue, (ClassWithEnum::)?yellow = 42 ?\}$nl$gdb_prompt $" { diff --git a/gdb/testsuite/gdb.cp/enum-class.cc b/gdb/testsuite/gdb.cp/enum-class.cc new file mode 100644 index 0000000..bddfbbb --- /dev/null +++ b/gdb/testsuite/gdb.cp/enum-class.cc @@ -0,0 +1,46 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +enum class E1 { + HI = 7, THERE +}; + +enum class E2 { + HI = 23, THERE +}; + +// overload1(E1::HI) is ok. +// overload1(77) is ok. +int overload1 (int v) { return 0; } +int overload1 (E1 v) { return static_cast<int> (v); } +int overload1 (E2 v) { return - static_cast<int> (v); } + +// overload2(E1::HI) is ok. +// overload1(77) fails. +int overload2 (E1 v) { return static_cast<int> (v); } +int overload2 (E2 v) { return - static_cast<int> (v); } + +// overload3(E1::HI) fails. +// overload1(77) is ok. +int overload3 (int v) { return 0; } +int overload3 (E2 v) { return static_cast<int> (v); } + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.cp/enum-class.exp b/gdb/testsuite/gdb.cp/enum-class.exp new file mode 100644 index 0000000..2246f50 --- /dev/null +++ b/gdb/testsuite/gdb.cp/enum-class.exp @@ -0,0 +1,48 @@ +# Copyright 2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file is part of the gdb testsuite + +if {[skip_cplus_tests]} { continue } + +standard_testfile .cc + +if {[prepare_for_testing $testfile.exp $testfile $srcfile \ + {debug c++ additional_flags=-std=c++11}]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +gdb_test "ptype E1" \ + "type = enum class E1 (: int )?{E1::HI = 7, E1::THERE}" + +gdb_test "print E1::HI" " = E1::HI" +gdb_test "print (int) E1::HI" " = 7" +gdb_test "print (int) E2::HI" " = 23" +gdb_test "print HI" "No symbol .HI.*" + +gdb_test "print overload1(E1::THERE)" " = 8" +gdb_test "print overload1(77)" " = 0" + +gdb_test "print overload2(E1::THERE)" " = 8" +gdb_test "print overload2(77)" \ + "Cannot resolve function overload2 to any overloaded instance" + +gdb_test "print overload3(E1::THERE)" \ + "Cannot resolve function overload3 to any overloaded instance" +gdb_test "print overload3(77)" " = 0" diff --git a/gdb/testsuite/gdb.dwarf2/enum-type.exp b/gdb/testsuite/gdb.dwarf2/enum-type.exp index 60457a6..a4825ec 100644 --- a/gdb/testsuite/gdb.dwarf2/enum-type.exp +++ b/gdb/testsuite/gdb.dwarf2/enum-type.exp @@ -30,8 +30,7 @@ Dwarf::assemble $asm_file { {DW_AT_name enum-type-dw.c} {DW_AT_comp_dir /tmp} } { - declare_labels integer_label array_elt_label array_label \ - big_array_label + declare_labels integer_label uinteger_label integer_label: DW_TAG_base_type { {DW_AT_byte_size 4 DW_FORM_sdata} @@ -39,6 +38,12 @@ Dwarf::assemble $asm_file { {DW_AT_name integer} } + uinteger_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_unsigned} + {DW_AT_name {unsigned integer}} + } + DW_TAG_enumeration_type { {DW_AT_name E} {DW_AT_type :$integer_label} @@ -48,6 +53,16 @@ Dwarf::assemble $asm_file { {DW_AT_const_value 1} } } + + DW_TAG_enumeration_type { + {DW_AT_name EU} + {DW_AT_type :$uinteger_label} + } { + DW_TAG_enumerator { + {DW_AT_name TWO} + {DW_AT_const_value 2 DW_FORM_sdata} + } + } } } } @@ -58,3 +73,9 @@ if { [prepare_for_testing ${testfile}.exp ${testfile} \ } gdb_test "print sizeof(enum E)" " = 4" + +gdb_test "ptype enum EU" "type = enum EU {TWO = 2}" \ + "ptype EU in enum C" +gdb_test_no_output "set lang c++" +gdb_test "ptype enum EU" "type = enum EU : unsigned integer {TWO = 2}" \ + "ptype EU in C++" diff --git a/gdb/valops.c b/gdb/valops.c index a10dbd6..e59e075 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -3007,6 +3007,42 @@ destructor_name_p (const char *name, struct type *type) return 0; } +/* Find an enum constant named NAME in TYPE. TYPE must be an "enum + class". If the name is found, return a value representing it; + otherwise throw an exception. */ + +static struct value * +enum_constant_from_type (struct type *type, const char *name) +{ + int i; + int name_len = strlen (name); + + gdb_assert (TYPE_CODE (type) == TYPE_CODE_ENUM + && TYPE_DECLARED_CLASS (type)); + + for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); ++i) + { + const char *fname = TYPE_FIELD_NAME (type, i); + int len; + + if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_ENUMVAL + || fname == NULL) + continue; + + /* Look for the trailing "::NAME", since enum class constant + names are qualified here. */ + len = strlen (fname); + if (len + 2 >= name_len + && fname[len - name_len - 2] == ':' + && fname[len - name_len - 1] == ':' + && strcmp (&fname[len - name_len], name) == 0) + return value_from_longest (type, TYPE_FIELD_ENUMVAL (type, i)); + } + + error (_("no constant named \"%s\" in enum \"%s\""), + name, TYPE_TAG_NAME (type)); +} + /* C++: Given an aggregate type CURTYPE, and a member name NAME, return the appropriate member (or the address of the member, if WANT_ADDRESS). This function is used to resolve user expressions @@ -3028,6 +3064,10 @@ value_aggregate_elt (struct type *curtype, const char *name, case TYPE_CODE_NAMESPACE: return value_namespace_elt (curtype, name, want_address, noside); + + case TYPE_CODE_ENUM: + return enum_constant_from_type (curtype, name); + default: internal_error (__FILE__, __LINE__, _("non-aggregate type in value_aggregate_elt")); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-03-31 18:19 ` Tom Tromey @ 2014-04-14 18:07 ` Tom Tromey 2014-05-21 14:04 ` Mark Wielaard 1 sibling, 0 replies; 8+ messages in thread From: Tom Tromey @ 2014-04-14 18:07 UTC (permalink / raw) To: Mark Wielaard; +Cc: gdb-patches Tom> +2014-03-31 Tom Tromey <tromey@redhat.com> Tom> + Tom> + PR c++/15246: Tom> + * c-exp.y (type_aggregate_p): New function. Tom> + (qualified_name, classify_inner_name): Use it. [...] I'm checking this in now. Tom ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-03-31 18:19 ` Tom Tromey 2014-04-14 18:07 ` Tom Tromey @ 2014-05-21 14:04 ` Mark Wielaard 2014-05-21 14:25 ` Tom Tromey 1 sibling, 1 reply; 8+ messages in thread From: Mark Wielaard @ 2014-05-21 14:04 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1532 bytes --] Hi Tom, On Mon, 2014-03-31 at 12:19 -0600, Tom Tromey wrote: > Mark> I am also not sure what the right thing to do is here. But I think it > Mark> makes sense to make printing it depend on the language used and always > Mark> print it when the language supports "derived enums" whether the user > Mark> explicitly defined it or it was guessed by the compiler. It is an valid > Mark> expression in any case and the GDB user might appreciate the extra info > Mark> (in the case of C++). > > I went this route. > > Here's a new patch, this one regtested on x86-64 Fedora 20 against both > the system compiler and a GCC with your enum patches applied. I had to > update gdb.cp/classes.exp and I added a new test as well. The gcc patch is almost in... (I hope). While testing it I found one more testcase that should get the same treatment as gdb.cp/classes.exp to optionally accept a underlying type in the case of C++. With the gcc patch you'll get the following 9 failures otherwise: FAIL: gdb.cp/var-tag.exp: before start: c++: ptype E FAIL: gdb.cp/var-tag.exp: before start: c++: ptype ee FAIL: gdb.cp/var-tag.exp: before start: c++: ptype EE FAIL: gdb.cp/var-tag.exp: in main: c++: ptype E FAIL: gdb.cp/var-tag.exp: in main: c++: ptype ee FAIL: gdb.cp/var-tag.exp: in main: c++: ptype EE FAIL: gdb.cp/var-tag.exp: in C::f: c++: ptype E FAIL: gdb.cp/var-tag.exp: in C::f: c++: ptype ee FAIL: gdb.cp/var-tag.exp: in C::f: c++: ptype EE With the testsuite tweak all these PASS. Does this look OK to check in? Thanks, Mark [-- Attachment #2: 0001-gdb-testsuite-Handle-underlying-type-in-gdb.cp-var-t.patch --] [-- Type: text/x-patch, Size: 2365 bytes --] From 0458987f529e6451a83aa10c5107ae4b9fa7fa50 Mon Sep 17 00:00:00 2001 From: Mark Wielaard <mjw@redhat.com> Date: Wed, 21 May 2014 16:00:05 +0200 Subject: [PATCH] gdb/testsuite: Handle underlying type in gdb.cp/var-tag.exp. * gdb.cp/var-tag.exp (do_global_tests): Handle underlying type. --- gdb/testsuite/ChangeLog | 4 ++++ gdb/testsuite/gdb.cp/var-tag.exp | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index be0bdf3..1afc9d5 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-05-21 Mark Wielaard <mjw@redhat.com> + + * gdb.cp/var-tag.exp (do_global_tests): Handle underlying type. + 2014-05-20 Pedro Alves <palves@redhat.com> * gdb.base/compare-sections.c: New file. diff --git a/gdb/testsuite/gdb.cp/var-tag.exp b/gdb/testsuite/gdb.cp/var-tag.exp index 7869fa2..9e46282 100644 --- a/gdb/testsuite/gdb.cp/var-tag.exp +++ b/gdb/testsuite/gdb.cp/var-tag.exp @@ -26,19 +26,25 @@ if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { } proc do_global_tests {lang} { + if {$lang == "c++"} { + set opt_underlying "(: unsigned int )?" + } else { + set opt_underlying "" + } + if {$lang == "c"} { set invalid_print "No symbol \"%s\" in current context." set ptypefmt $invalid_print } else { set invalid_print "Attempt to use a type name as an expression" - set ptypefmt "type = (class|enum|union|struct) %s {.*}" + set ptypefmt "type = (class|enum|union|struct) %s $opt_underlying{.*}" } with_test_prefix $lang { gdb_test_no_output "set language $lang" gdb_test "ptype C" "type = class C {.*}" gdb_test "print E" "= a" - gdb_test "ptype E" "type = enum E {.*}" + gdb_test "ptype E" "type = enum E $opt_underlying{.*}" gdb_test "print S" "= {<No data fields>}" gdb_test "ptype S" "type = struct S {.*}" gdb_test "print U" "= {.*}" @@ -52,7 +58,7 @@ proc do_global_tests {lang} { gdb_test "print SS" [format $invalid_print "SS"] gdb_test "ptype SS" [format $ptypefmt "SS"] gdb_test "print ee" "= .*" - gdb_test "ptype ee" "type = enum EE {.*}" + gdb_test "ptype ee" "type = enum EE $opt_underlying{.*}" gdb_test "print EE" [format $invalid_print "EE"] gdb_test "ptype EE" [format $ptypefmt "EE"] gdb_test "print uu" "= {.*}" -- 1.7.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] implement support for "enum class" 2014-05-21 14:04 ` Mark Wielaard @ 2014-05-21 14:25 ` Tom Tromey 0 siblings, 0 replies; 8+ messages in thread From: Tom Tromey @ 2014-05-21 14:25 UTC (permalink / raw) To: Mark Wielaard; +Cc: gdb-patches >>>>> "Mark" == Mark Wielaard <mjw@redhat.com> writes: Mark> * gdb.cp/var-tag.exp (do_global_tests): Handle underlying type. Thanks, Mark. This is ok. Tom ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-05-21 14:25 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-03-27 20:12 [PATCH] implement support for "enum class" Tom Tromey 2014-03-28 11:21 ` Mark Wielaard 2014-03-31 4:38 ` Tom Tromey 2014-03-31 7:16 ` Mark Wielaard 2014-03-31 18:19 ` Tom Tromey 2014-04-14 18:07 ` Tom Tromey 2014-05-21 14:04 ` Mark Wielaard 2014-05-21 14:25 ` Tom Tromey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox