4

Two questions about this :

  • Is there a way to force g++ to ignore the throw specifiers ?
    (for example, as I remember, Visual Studio ignores the throw specifiers, different from throw())

  • Is it possible to force g++ to check if the throw specifiers are correct - what I mean is to check ( and this can be done by a one-pass compilers ) if the functions with throw specifiers call functions, that may throw by just watching theirs throw specifiers and watch for executing throw for exceptions, that will violate the specifiers ? (Note: this should not watch the functions without throw specifiers, because this could cause tons of warnings )


EDIT: I'll add some examples for my second question.

Suppose we have:

// sorry for the coding style here, but I don't want it to be unnecessary long
class A { /* .. */ };
class B : public A { /* .. */ };
class C { /* .. */ };
void no_throw_spec() { /* .. */ }
void no_throw_at_all() throw() { /* .. */ }
void throws_A() throw( A ) { /* .. */ }

// this is fine, don't do anything
void f() 
{ no_throw_spec(); no_throw_at_all(); throws_A(); }

void g() throw()
{ 
    no_throw_spec(); no_throw_at_all(); // OK
    throws_A();  // warning here - throws_A() may throw A, but g() has throw()!
}

void h() throw( A )
{
    no_throw_spec(); no_throw_at_all(); throws_A(); // OK
    if( /* .. */ ) 
        throw B(); // OK, B inherits A, it's OK
    /* .. */
    throw C();    // C does not inherit A, so WARNING!
}
Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
  • 1
    I think Herb Sutter's article about exception specifications still applies even though it's pretty old http://www.gotw.ca/publications/mill22.htm – Mark B May 18 '11 at 13:41
  • I know. And how is this related? If you mean, that I should not write exception specifications, I know that. I was just curious. – Kiril Kirov May 18 '11 at 14:23
  • 2
    Given that throw specifiers are not part of the type of a function, surely a C++ compiler cannot check them *in general*, in any computable number of passes. For example, `void doit(void(*f)()) throws() { f(); }`. `doit` violates its throw specification if (and only if) `f` throws anything. So should the compiler reject this on grounds that it *may* violate, since there is no way to tell at compile time that it will only be called with nothrow functions as arguments? Java only achieves checked exceptions by making the throws clause part of the function signature. – Steve Jessop May 18 '11 at 15:31
  • Or do you mean that functions passed around come under the heading of, "called functions that have no throw specifiers"? And hence the compiler accepts that code even though there's no particular grounds to believe that it won't violate its throw specification. Beware too that there are standard functions with no throw specifier that are documented to throw, like `std::vector::at`, presumably you would need to annotate these with manufactured specifiers, or they'd never get checked. – Steve Jessop May 18 '11 at 15:36
  • Hmm, I haven't thought about function pointers..but they could be like the functions without any throw specifiers. See my edit for more info (: – Kiril Kirov May 18 '11 at 16:09

2 Answers2

3
  • gcc has an option -fno-enforce-eh-specs, see the documentation and check that it does what you want.

  • I don't remember any way to statically check exception specifications with gcc.

Note that (dynamic) exception specifications are deprecated in C++0X which add a noexcept exception specification replacing the empty exception specification case (it is also checked dynamically and has provisions helping to use it in templates).

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • Wasn't it `noexcept`? But that is also runtime checked, not statically at compile time. – Xeo May 18 '11 at 12:40
  • @Xeo, yes on both points. My point is that doing now anything with non empty exception specification is advancing on a different path than the one the committee has chosen. – AProgrammer May 18 '11 at 12:42
  • I know about C++0x, that made me wonder about the current C++03. This option is cool, btw, thanks! – Kiril Kirov May 18 '11 at 12:45
  • 1
    "_I don't remember any way to statically check exception specifications with gcc._" Statically checking ES is not really doable in most programs (most useful programs would not ES-check; that's why Java doesn't try to do it.) It might be useful in some programs with absolutely no polymorphism, I am not sure the benefits are worth it. – curiousguy Nov 02 '11 at 21:32
2

Yes, you can make g++ ignore throw by:

#define throw(x)

About the rest you need to change the compiler code or make your own script/program in build process that will check for those things, it can be easily done with regexp.

Edit:

about your comment, finding the hierarchy of exceptions is really easy. use regexp like:

class ([^ ]*) : ([^ ]*)

and input that to a hash, and later make hierarchical data.
To match exceptions in functions that throw them use:

([^\(\s]*)[\s]*([^\)])[\s]*(throw[\s]*\([^\)]*\)){((throw[\s]*[^;])|*)*}

its not tested and might have some errors, but good place to start

Daniel
  • 30,896
  • 18
  • 85
  • 139
  • @Dani - thanks about the first one, +1. About the second point - I cannot change the compiler code easily :D Also, regex will no work here, because for this check we need to know the whole hierarchy of the exceptions - which is not that easy to be done for a big project, just using regex. Or at least I think so. – Kiril Kirov May 18 '11 at 12:10
  • 1
    @Dani, but if someone uses as `throw 0;` will it ignore ? – iammilind May 18 '11 at 12:13
  • btw, `x` should be replaced by me for all specifiers or it is some kind of variable, that will match everything between `(` and `)` ? – Kiril Kirov May 18 '11 at 12:14
  • It won't match `throw 0`, and it will match only 1 parameter of any type. To match any number of arguments use `#define throw(...)`, it still won't match `throw 0`. – Daniel May 18 '11 at 12:18
  • 'easily' with regexp? how about a method that which calls another method which calls another method .... which throws? – stijn May 18 '11 at 12:23
  • So what? The compiler goes through all functions, right? It's enough to check only the first level. But still, not "easily" and not with regex :D – Kiril Kirov May 18 '11 at 12:26
  • @Dani - about your edit - and this must be done for _each_ file in the project, that is not that easy - for example, when you use some libraries. It's not that simple, a compiler should do this, IMO. – Kiril Kirov May 18 '11 at 12:29
  • yes, a `Kiril Kirov` compiler, not a `c++` compiler. when you want to define a new language, even if its close to existing one, you need to get your hands dirty. – Daniel May 18 '11 at 12:31
  • Jesus :D Who is talking about new language :D – Kiril Kirov May 18 '11 at 12:35
  • Well, you want to change c++ features, thats a different language to me – Daniel May 18 '11 at 12:37
  • I don't want to change C++ features, I want to make the compiler to check some things for me - valid throw specifications (for the second one; the first one is something, that C++0x will have, I just wandered if this can be done in C++03) – Kiril Kirov May 18 '11 at 12:42
  • The language specifications include the compiler specifications – Daniel May 18 '11 at 12:43
  • 1
    @Dani: no, adding warnings to a compiler does not change the language. Ignoring throw specifications does change the language (the compiler is no longer conforming), but that one's already covered. – Steve Jessop May 18 '11 at 15:28