Aaron W. LaFramboise wrote: > Jason Merrill wrote: >> Sergio Giro wrote: >>> I perceived that many people think that the throw qualifiers, as >>> described by the standard, are not useful >> >> Yes. But that's not a reason to add a slightly different non-standard >> feature that would require people already using standard exception >> specifications to rewrite everything. That's just a non-starter. > > This is also the feature I'd like to see: a static checker for the > existing throw specification feature. >
Thats what EDoc++ ( http://edoc.sourceforge.net/intro.html ) achieves among a few other things like generating doxygen documentation. However i agree with Sergio that having a feature that performs static analysis of exception propagation at compile time as part of GCC would be a helpful feature. The problem with EDoc++ as pointed out by Sergio is that it is not integrated into GCC and so maintainence is an issue as gcc evolves. > I've been an advocate for eh specs, and I believe they are usable in > their present form. For reasons pointed out elsewhere, Java-esque > static checking really isn't going to work for C++. The only way that > Java even gets away with it is why letting the vast majority of > exceptions--those are derived from Error--slip through. That is, Java > throw(something) is equivalent to C++ throw(something, Error), where > Java's Error is probably close to C++'s std::runtime_error. > (Unfortunately std::bad_alloc and similar don't derive from > std::runtime_error or share a common parent.) > EDoc++ provides the ability to "ignore" certain exceptions. The exception types to ignore can be specified in a "suppressions" file. Its the users decision as to whether they wish to do this or not. In my projects using EDoc++ i have opted for NOT including exception specifiers for all my functions but just using the generated documentation to determine what exceptions may be thrown. Otherwise as you said, it will become necessary to include a number of different std::... exceptions in the throw specifiers for completeness or to ignore the fact that they may occur. Which brings up the question is it allowable to let the program terminate if say a std::bad_alloc exception is thrown. I think the current manual audit process for using exceptions and knowing exactly what is going on is the biggest killer for using exceptions properly in C++. That was the initial purpose of creating this project. > The main problem with eh specs in their present form, besides poor > support on some non-GCC compilers, is the lack of tools available to > audit the specs. This is a challenge to implement, as it needs to use > non-intrusive decorators and heuristics to allow the user to indicate > cases where exceptions logically won't propagate, even though they > 'theoretically could.' Complete static checking would end up being the > equivalent of -Weffc++: completely useless. > Yes. I agree completely. My first version of EDoc++ did not include the concept of suppressions, and it just became infeasible to use. There was too much information and a lot of it just really was not important to the average developer. Practically every function that included a throw specifier would emit errors if it used anything from STL as for example std::bad_alloc would be thrown or something similar. By using an external suppressions file it is possible to indicate locations where exceptions will not logically propagate even though the compiler thinks that they will as well as saying that std::bad_alloc among others are "runtime" exceptions equivalent to Java and not necessary in the specs. Again there are issues involved with maintaining an external suppressions file as opposed to some form of markup within the source code. Suppressions can also be used to say i am only interested in information for a certain set of functions or to restrict the callgraph that may have been pessimistically expanded from virtual functions or function pointer calls, or to add function calls (which is currently necessary when using plugins) or really to modify the resulting data in any way imaginable. (The suppressions file is actually a python script that can manipulate the EDoc++ applications internal data structures) > But I do think the compiler is the right place to do this sort of > checking, as it needs to have available to it all of the same sorts of > analysis as a compiler. Good luck, Sergio, if you want to work on this. > Yes. Trying to construct accurate callgraphs is very difficult without the compiler. Especially with all the implicitly generated constructors and the like. Not to mention other issues that i have encountered like static/inline functions with the same name but DIFFERENT implementations in different translation units (Jee that is a poor coding style but it is possible using the preprocessor) and code compiled with -fno-exceptions linked with code that allows exceptions, same with C++ and C code intermixed, templates and vague linkage, differing throws() specifiers for a functions prototype in different translation units, and the list of complexities goes on... Many issues i believe relate to poor usage of the C++ language or overlooked bugs caused by things like declaring prototypes in more than one place and forgetting to copy across the throw() specifier. But all these wonderful things are "possible" with C++. By generating the information with the compiler you know exactly what is being used and it does a lot of the hard work for you. EDoc++ is implemented as a modification to the gcc 4.0.1 and also requires a post processing tool that looks at the information generated by this modified GCC once all the compilation is complete. To make such a feature as Segio is describing useful in g++, i would say that the first stage is to get it working as described in previous emails where it would emit errors for throw specifiers that do not include say std::bad_alloc, and then as a second stage using some form of markup in the source or some other method like the external suppressions file that it should then be capable of modifying that data to suppress certain exception types, or override compiler generated information for cases where it can not accurately determine say the callgraph. There is a lot of work required in implementing a feature like this well i think. I do also think however that it is worth the effort (Which is why i have been working on EDoc++) and that such a feature would be valuable within gcc itself. Anyhow, i think i have been rambling again... I am curios to see where this thread leads. Brendon.