This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH: Reimplementation of error.c


Hi,
attached is the patch for error.c which Gabriel foreshadowed yesterday.

This patch reworks the error.c functions into a (hopefully) more
consistent framework. Currently the tree to string functions have a
single boolean switch (V) which is overloaded to mean different things
in
different contexts. As this verbose flag is passed around, it's meaning
changes and it is hard to get a consistent output of trees. I'll
describe
the big picture, the rough outline of changes, impact to other parts of
the compiler, specific output details and future ideas.

Big Picture
===========
Instead of a single flag, a set of enumerated flags are used, each
controlling a specific aspect of stringification. To retain the
existing error reporting interface, which uses a '#' flag to switch on
the verbose flag, the print escape functions map verbose to a suitable
set of the mask flags. The enumerated flags are exported outside of
error.c, so that template code in pt.c can make use of them.

Several functions which are currently exported from error.c are no
longer exported, as they are unused elsewhere.

The enumeration tree_string_flags can be bit-ored together and are,
TS_PLAIN - null value
TS_CHASE_TYPEDEFS - produce a canonical output (the CANONICAL flag)
TS_DECORATE - add `typedef', `static', `virtual' as needed
TS_FUNC_NORETURN - don't show function declaration return type
TS_FUNC_THROW - show function declaration throw spec
TS_PARM_DEFAULTS - show function parm default values
TS_EXPR_PARENS - wrap EXPR node in parens (the `NOP' flag)
TS_AGGR_TAGS - show `class', `struct', `union', `enum' tag
TS_DECL_TYPE - show the type of a decl (not just it's name)
TS_FUNC_SCOPE - explicitly show scope of function-scope objects
TS_PEDANTIC_NAME - pedanticly name show global scope, and other pedantry
TS_MARK_CORE - use an '@' to show the core of a type (later)
internal use flags
TS_TEMPLATE_PARM - the decl is really a template non-type parm
TS_TEMPLATE_PLAIN - don't decorate a primary template-name

Changes in error.c
------------------
The definition of cp_printers is moved, to allow the callbacks to be
declared `static'.

OB_UNPUT is removed.

OB_END_TEMPLATE_ID is reworked.

args_to_string, assop_to_string, code_to_string, cv_to_string,
decl_to_string, expr_to_string, fndecl_to_string, language_to_string,
op_to_string, parm_to_string, type_to_string are made static

dump_template_decl - new static function

interesting_scope_p is removed (replaced by dump_scope).
dump_type_real is returned back to dump_type (the canonical
arg is no longer required)

New Functions
dump_scope, which dumps an object's scope, if desired.
dump_template_parms, which dumps the parameters of a template
declaration or instantiation.
dump_mark_core which deals with the TS_MARK_CORE flag
dump_template_decl which deals with dumping a template declaration.

Modified Functions
dump_qualifiers, simplified and returns a flag indicating whether
anything was output. this means multi-level cv qualified pointers
are printed nicerly.

Functions which take a 'v' (and a 'pedantic_name') parameter are altered
to take a 'flags' parameter. Internal modifications are fairly
straightforward. Whenever we 'sorry', we emit something like
'{typeerror}' rather than nothing in the output string.

When dumping a template name, we generate the '<...>' part here, rather
than have that precomputed and stored as part of the template type name.
I.e.
'template<class T> struct X' remains an 'X' rather than being mangled to
'X<T>'. This gives control at stringification time a to how the template
parameters are rendered. dump_template_parms does this.

Impact on other parts
---------------------
mangle_class_name_for_template (pt.c) is no longer required. We simply
use the template name in classtype_mangled_name.

Several diagnostics throught the rest of the compiler had a '#' flag in
the '%' escape sequence added or removed, in order to retain the current
formatting.

The behaviour of __PRETTY_FUNCTION__ changes. Naturally all the expected
tweaks will affect the __PRETTY_FUNCTION__ string, but also static
member functions change.
Currently those are rendered as `static void X::fn()'. Now they are
rendered
as plain `void X::fn ()'. The TS_DECORATE controls whether `static' is
emitted,
and I augmented it to also show `virtual' should that be needed. This
change causes g++.pt/memtemp77.C to fail as it does a strcmp against an
expected
__PRETTY_FUNCTION__ name. Does not seem particularly concerned about the
string,
only that the right one is generated.

Output Effects
-------

Templates were previously rendered sometimes as 'template<class T>
struct X<T>', and sometimes as 'X<T>'. The latter can cause confusion
when 'T' exists as a type in the current scope -- is it a
specialization of X with global type T?

The behaviour I chose was that non-instantiations are printed either
as template<class T> struct X' or as 'X<>' (depending it's the
TEMPLATE_DECL or just a RECORD_TYPE of a templatized class), whereas
instantiations use 'X<int>' etc. (An instantiation must have at least
one parameter, so can never be `X<>'.) Similarly for function templates.
This means that template scope objects might be rendered as
`X<>::member'
(template definition), or `X<int>::member'
(specialization/instantiation).

Multi level pointer types are printed more neatly, especially when cv
qualifiers are involved. I have retained the existing behaviour of
putting
white space before a `*' (as in `int *thing') rather than afterwards
(`int* thing'). Multilevel pointers are rendered as `int **thing' or
`int *const *thing', rather than `int * *thing' and `int *const *thing'
as
they are now. More complicated cases are `panama &panama::operator'
rather
than `panama & panama::operator' and, `int Y::X::*(Y::X::*foo3 ()) ()'
rather
than `int Y::X::* (Y::X::* foo3())()'

There is more consistency about when an aggregate specifier is printed.
Currently we might print `struct X fn(X)' whereas the patch would print
either `X fn (x)', or `struct fn (struct X)', depending on TS_AGGR_TAGS.

You'll notice that we now print a space between a function name and the
parameter list, as FSF coding requires.

The `In function `void fn(int)'' diagnostic preamble doesn't print
default
parameter values -- I considered them unnecessary here.

Following this, the testsuite logs showed many differences in the error
formatting. To make sure that these were intentional I ran a shell
script (logcmp.sh) to compare old and new logs. The script applies sed
commands to the logs and diffs the result. What still remains different
is operated on again. The residual difference shows some special cases.
(I diffed the logs before adding the space between function name and
parameters, as that caused a lot of differences which were awkward to
automatically remove without obscuring what might be real problems.)

Interestingly, something that `fell out in the wash' when
dumping a type involving typedef'd templates is that we don't always
look through the typedef (the TS_CHASE_TYPEDEFS controls this). This
can make error messages more understandible. For instance, rather than
`Graph<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0>
>,Empty>::Graph(const Graph<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Empty> &)'
we get the more understandable,
`Graph<string,Empty>::Graph(const Graph<string,Empty> &)'
I think this is a good thing.

Future ideas
------------
Finally, why the TS_MARK_CORE? I've got some other code which uses
these functions to output definition and declaration information,
including sufficient type and name information that a post processor can
generate documentation from the original source. Marking type cores
means that that tool does not need to know much about how types are
built.

Also Gabriel Dos Reis has further plans for augmenting the tree to
string functions, as he said last week, and this patch is (I beleive)
a substantial move in that direction. Gabriel is aware of this patch,
and examined an earlier version.

Attached are
error.patch.gz - the patch
log.raw.diff.gz - diff of pre and post g++.log files
log.cooked.diff.gz - output of shell script run on pre and post g++.log
files
logcmp.sh - the (zsh) shell script

Ok?

nathan
-- 
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
        I have seen the death of PhotoShop -- it is called GIMP
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk

error.patch.gz

logcmp.sh

log.raw.diff.gz

log.cooked.diff.gz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]