From 078a020797210f4d8f9491bbfe16ec31e9efb652 Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Wed, 29 Aug 2018 15:12:24 -0700 Subject: C++ compile support This patch adds *basic* support for C++ to the compile feature. It does most simple type conversions, including everything that C compile does and your basic "with-classes" type of C++. I've written a new compile-support.exp support file which adds a new test facility for automating and simplifying "compile print" vs "compile code" testing. See testsuite/lib/compile-support.exp and CompileExpression for more on that. The tests use this facility extensively. This initial support has several glaring omissions: - No template support at all I have follow-on patches for this, but they add much complexity to this "basic" support. Consequently, they will be submitted separately. - Cannot print functions The code template needs tweaking, and I simply haven't gotten to it yet. - So-called "special function" support is not included Using constructors, destructors, operators, etc will not work. I have follow-on patches for that, but they require some work because of the recent churn in symbol searching. - There are several test suite references to "compile/1234" bugs. I will file bugs and update the test suite's bug references before pushing these patches. The test suite started as a copy of the original C-language support, but I have written tests to exercise the basic functionality of the plug-in. I've added a new option for outputting debug messages for C++ type-conversion ("debug compile-cplus-types"). gdb/ChangeLog: * Makefile.in (SUBDIR_GCC_COMPILE_SRCS): Add compile-cplus-symbols.c and compile-cplus-types.c. (HFILES_NO_SRCDIR): Add gcc-cp-plugin.h. * c-lang.c (cplus_language_defn): Set C++ compile functions. * c-lang.h (cplus_get_compile_context, cplus_compute_program): Declare. * compile/compile-c-support.c: Include compile-cplus.h. (load_libcompile): Templatize. (get_compile_context): "New" function. (c_get_compile_context): Use get_compile_context. (cplus_get_compile_context): New function. (cplus_push_user_expression, cplus_pop_user_expression) (cplus_add_code_header, cplus_add_input, cplus_compile_program) (cplus_compute_program): Define new structs/functions. * compile/compile-cplus-symmbols.c: New file. * compile/compile-cplus-types.c: New file. * compile/compile-cplus.h: New file. * compile/compile-internal.h (debug_compile_oracle, GCC_TYPE_NONE): Declare. * compile/compile-object-load.c (get_out_value_type): Use strncmp_iw when comparing symbol names. (compile_object_load): Add mst_bss and mst_data. * compile/compile.c (_initialize_compile): Remove -Wno-implicit-function-declaration from `compile_args'. * compile/gcc-cp-plugin.h: New file. * NEWS: Mention C++ compile support and new debug options. gdb/testsuite/ChangeLog: * gdb.compile/compile-cplus-anonymous.cc: New file. * gdb.compile/compile-cplus-anonymous.exp: New file. * gdb.compile/compile-cplus-array-decay.cc: New file. * gdb.compile/compile-cplus-array-decay.exp: New file. * gdb.compile/compile-cplus-inherit.cc: New file. * gdb.compile/compile-cplus-inherit.exp: New file. * gdb.compile/compile-cplus-member.cc: New file. * gdb.compile/compile-cplus-member.exp: New file. * gdb.compile/compile-cplus-method.cc: New file. * gdb.compile/compile-cplus-method.exp: New file. * gdb.compile/compile-cplus-mod.c: "New" file. * gdb.compile/compile-cplus-namespace.cc: New file. * gdb.compile/compile-cplus-namespace.exp: New file. * gdb.compile/compile-cplus-nested.cc: New file. * gdb.compile/compile-cplus-nested.exp: New file. * gdb.compile/compile-cplus-print.c: "New" file. * gdb.compile/compile-cplus-print.exp: "New" file. * gdb.compile/compile-cplus-virtual.cc: New file. * gdb.compile/compile-cplus-virtual.exp: New file. * gdb.compile/compile-cplus.c: "New" file. * gdb.compile/compile-cplus.exp: "New" file. * lib/compile-support.exp: New file. doc/ChangeLog: * gdb.texinfo (Compiling and injecting code in GDB): Document set/show "compile-oracle" and "compile-cplus-types" commands. --- gdb/testsuite/lib/compile-support.exp | 227 ++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 gdb/testsuite/lib/compile-support.exp (limited to 'gdb/testsuite/lib') diff --git a/gdb/testsuite/lib/compile-support.exp b/gdb/testsuite/lib/compile-support.exp new file mode 100644 index 0000000..b784c35 --- /dev/null +++ b/gdb/testsuite/lib/compile-support.exp @@ -0,0 +1,227 @@ +# Copyright 2015-2018 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 . + +# Generic/oft used support routines for testing GDB's compile feature. + +# Return 1 if we should skip tests of the "compile" feature. +# This must be invoked after the inferior has been started. + +proc skip_compile_feature_tests {} { + global gdb_prompt + + set result 0 + gdb_test_multiple "compile code -- ;" "check for working compile command" { + "Could not load libcc1.*\r\n$gdb_prompt $" { + set result 1 + } + -re "Command not supported on this host\\..*\r\n$gdb_prompt $" { + set result 1 + } + -re "\r\n$gdb_prompt $" { + } + } + return $result +} + +# This namespace provides some convenience functions for running +# "compile code" and "compile print" tests. +# +# Exported functions are defined inline below. +# +# General usage: +# +# Start a new session, noting that the variable "var" will be used for +# "compile code" expressions. This variable /must/ exist in the stopped +# location. +# +# CompileExpression::new "var" +# +# Test the implicit expression "foo;" with result/value 3. +# CompileExpression::test "foo" 3 +# ---> Runs the following tests (name of tests ignored for illustration) +# gdb_test_no_output "compile code var = foo" +# gdb_test "p var" "= 3" +# gdb_test "compile print foo;" "= 3" +# +# Test the explicit expression "a = function (3); var = a;" with the result 21. +# CompileExpression::test "a = function (3); var = a;" 21 -explicit +# ---> Runs the following tests (name of tests ignored for illustration) +# gdb_test_no_output "compile code a = function (3); var = a;" +# gdb_test "p var" "= 21" +# +# Additional option flags may be passed to test to control the behavior +# of the test harness: +# +# Pass -explicit to specify that the test uses an explicit expression, +# one which sets the value of the variable (see above). Only the code test +# will be run. +# +# Pass -value and/or -print to indicate that the value and/or print steps +# will optionally fail. Specify "xfail" or "kfail" to indicate how +# particular step will fail. These may be followed by any accepted DejaGNU +# parameters such as architecture and bug#. [See examples below.] +# +# To specify that the compile (and consequently print and value tests) is +# expected to kfail/xfail, use -kfail or -xfail with any appropriate +# DejaGNU parameters. Both options override -print and -value. +# [-xfail is given precedence over -kfail should both be given.] +# +# -value is used when a "code" test is run, specifying that the "compile +# code" and "print VAR" steps will fail in the prescribed manner. +# [If the print step generates a PASS, the test is considered invalidly +# written. VAR's value should /always/ be invalidated before a test is +# run.] +# +# -print is used to specify that an expression will fail in the prescribed +# manner when "print" test is executed. +# +# Pass "-name NAME" to set an optional test name. If not specified, +# the harness will use test names such as "compile code EXPR" and +# "result of compile code EXPR". +# +# Pass "-noprint" or "-nocode" to suppress print or code tests, respectively, +# This is useful when the expression being tested modifies the object +# being tested, e.g., "a++". +# +# These options must be passed LAST to CompileExpression::test. +# +# Examples: +# +# Both "code" and "print" tests are expected to xfail: +# CompileExpression add_imp "foo" 3 -compile {xfail *-*-*} -print {xfail *-*-*} +# +# The "print $VARIABLE" portion of the "code" test is expected to kfail +# (the actual "compile code" GDB command will succeed), but the "print" +# test should pass: +# CompileExpression add_imp "foo" 3 -value {kfail *-*-* gdb/1234} + +namespace eval ::CompileExpression { + + # The variable name to check testing results. This variable + # must be in scope when tests are run. + variable varName_ {} + + # Start a new expression list. VARNAME is the name of the variable + # that will be printed to check if the result of the test was + # successful. + proc new {varname} { + variable varName_ + + set varName_ $varname + } + + # Test an expression. + # + # See the preamble for a list of valid optional arguments. + # + # Implicit expressions will be sent to GDB in the form + # "$varName = $EXP". "p $varName" will be used to decide the pass + # or fail status of the test. + # + # Explicit expressions will be sent to GDB as-is and tested using only + # "compile code". The expression should set the value of the variable + # $varName, which is then printed to determine whether the test passed + # or failed. + # + # Unlike explicit expressions, implicit expressions are tested with both + # "compile print" and "compile code". + + proc test {exp result args} { + parse_args {{value {"" ""}} {print {"" ""}} {name ""} + {noprint} {nocode} {explicit} {xfail {"" ""}} {kfail {"" ""}}} + + if {[lindex $xfail 0] != ""} { + set l "xfail $xfail" + } elseif {[lindex $kfail 0] != ""} { + set l "kfail $kfail" + } else { + set l "" + set compile {"" ""} + } + if {$l != ""} { + set compile $l + set print $l + set value $l + } + + if {!$nocode} { + do_test_ code $exp $result $explicit $name \ + [list $compile $value $print] + } + if {!$noprint} { + do_test_ print $exp $result $explicit $name \ + [list $compile $value $print] + } + } + + # Run a compile test for CMD ("print" or "code"). + + proc do_test_ {cmd exp result is_explicit tst fail_list} { + variable varName_ + + if {![string match $cmd "code"] + && ![string match $cmd "print"]} { + error "invalid command, $cmd; should be \"print\" or \"compile\"" + } + + # Get expected result of test. Will be "" if test is + # expected to PASS. + lassign $fail_list fail_compile fail_value fail_print + + # Set a test name if one hasn't been provided. + if {$tst == ""} { + set tst "compile $cmd $exp" + } + + if {[string match $cmd "print"]} { + if {!$is_explicit} { + eval setup_failures_ $fail_print + gdb_test "compile print $exp" $result $tst + } + } else { + if {$is_explicit} { + set command "compile code $exp" + } else { + set command "compile code $varName_ = $exp" + } + eval setup_failures_ $fail_compile + gdb_test_no_output $command $tst + eval setup_failures_ $fail_value + gdb_test "p $varName_" "= $result" "result of $tst" + } + } + + # A convenience proc used to set up xfail and kfail tests. + # HOW is either xfail or kfail (case is ignored). ARGS is any + # optional architecture, bug number, or other string to pass to + # respective DejaGNU setup_$how routines. + + proc setup_failures_ {how args} { + switch -nocase $how { + xfail { + eval setup_xfail $args + } + + kfail { + eval setup_kfail $args + } + + default { + # Do nothing. Either the test is expected to PASS + # or we have an unhandled failure mode. + } + } + } +} -- cgit v1.1