Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Travis Vitek wrote: Martin Sebor wrote: Farid Zaripov wrote: I've just tried to declare and define __rw_once with throw(...) exception specification and compiler doesn't issues warning in that case. Yes, but the documentation linked to explicitly says... Explicit exception specifications are not allowed on C functions. [http://msdn2.microsoft.com/en-us/library/wfa0edys(VS.80).aspx] I tested, it does compile, and the destructors are getting called as they should when an explicit throw(...) spec is added to the C linkage function. That said, I cringe at the thought relying on behavior that is documented to not work or is not supported. FWIW, I looked to see if throw(...) is being used by any projects out there and what for. I've found a few but none very helpful. In particular, I found only one extern C function with throw(...), and that's in some toy example. All the other hits point to C++ functions: http://www.google.com/codesearch?q=throw%5C+*%5C%28%5C+*%5C.%5C.%5C.%5C+*%5C%29+lang%3Ac%2B%2B Martin
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Farid Zaripov wrote: From: Martin Sebor [mailto:[EMAIL PROTECTED] I just found out that the /Ehc flag enables the nothrow default for C linkage functions. So changing the /EHsc flag to /EHs will fix this for both VC7 and 8. Do you happen to know if there's a #pragma that will let us select the mode we need for just the one function? There's no #pragma for that, but we can compile all cpp files with /Ehsc, and some set of specified files with /EHs. But, there is __declspec(throw) - right?
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Farid Zaripov wrote: -Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Saturday, August 18, 2007 12:00 AM To: stdcxx-dev@incubator.apache.org Subject: Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp I just found out that the /Ehc flag enables the nothrow default for C linkage functions. So changing the /EHsc flag to /EHs will fix this for both VC7 and 8. Do you happen to know if there's a #pragma that will let us select the mode we need for just the one function? There's no #pragma for that, but we can compile all cpp files with /Ehsc, and some set of specified files with /EHs. Okay, that's something to consider. We'll have to see how pervasive the use of __rw_once() will be as soon as I'm done switching to it (so far I think it'll be needed in only a handful of places) and whether any of the initialization functions will potentially throw. Btw., from the MSVC Exception Handling Model: http://msdn2.microsoft.com/en-us/library/1deeycx5(VS.80).aspx it looks like by default the compiler generates code that makes catch blocks catch structured exceptions (in addition the C++ kind). That's generally considered bad practice, but it may be relied on by user code for historical reasons. We need to be careful not to impose requirements on our users that would go against this historical practice (doing so could break working code). Martin
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
William A. Rowe, Jr. wrote: Farid Zaripov wrote: From: Martin Sebor [mailto:[EMAIL PROTECTED] I just found out that the /Ehc flag enables the nothrow default for C linkage functions. So changing the /EHsc flag to /EHs will fix this for both VC7 and 8. Do you happen to know if there's a #pragma that will let us select the mode we need for just the one function? There's no #pragma for that, but we can compile all cpp files with /Ehsc, and some set of specified files with /EHs. But, there is __declspec(throw) - right? There is __declspec(nothrow) to indicate that a function cannot throw exceptions (the default for C functions) but I don't see one to indicate the opposite, i.e., that a C function can throw. One would think it'd be the logical extension given that all C++ functions can throw by default and no C functions can. Here's the latest man page on __declspec(nothrow): http://msdn2.microsoft.com/en-us/library/49147z04(VS.80).aspx Martin
RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
-Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Tuesday, August 21, 2007 9:36 PM To: stdcxx-dev@incubator.apache.org Subject: Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp William A. Rowe, Jr. wrote: Farid Zaripov wrote: From: Martin Sebor [mailto:[EMAIL PROTECTED] I just found out that the /Ehc flag enables the nothrow default for C linkage functions. So changing the /EHsc flag to /EHs will fix this for both VC7 and 8. Do you happen to know if there's a #pragma that will let us select the mode we need for just the one function? There's no #pragma for that, but we can compile all cpp files with /Ehsc, and some set of specified files with /EHs. But, there is __declspec(throw) - right? There is __declspec(nothrow) to indicate that a function cannot throw exceptions (the default for C functions) but I don't see one to indicate the opposite, i.e., that a C function can throw. One would think it'd be the logical extension given that all C++ functions can throw by default and no C functions can. You're right. But there is throw(...) exception specification which tells the compiler that the function can throw an exception. http://msdn2.microsoft.com/en-us/library/wfa0edys(VS.80).aspx Farid.
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Farid Zaripov wrote: -Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Tuesday, August 21, 2007 9:26 PM To: stdcxx-dev@incubator.apache.org Subject: Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp There's no #pragma for that, but we can compile all cpp files with /Ehsc, and some set of specified files with /EHs. Okay, that's something to consider. We'll have to see how pervasive the use of __rw_once() will be as soon as I'm done switching to it (so far I think it'll be needed in only a handful of places) and whether any of the initialization functions will potentially throw. I've just tried to declare and define __rw_once with throw(...) exception specification and compiler doesn't issues warning in that case. Good to know! We still need to decide how to handle this in the general case (for compilers that behave like MSVC, if there are any) but we can certainly start using this extension to silence the MSVC warnings. Btw., from the MSVC Exception Handling Model: http://msdn2.microsoft.com/en-us/library/1deeycx5(VS.80).aspx it looks like by default the compiler generates code that makes catch blocks catch structured exceptions (in addition the C++ kind). That's generally considered bad practice, but it may be relied on by user code for historical reasons. We need to be careful not to impose requirements on our users that would go against this historical practice (doing so could break working code). It was by default only in MSVC versions prior 7.0 (because the only asynhronous exceptions handling model was implemented. Since MSVC 7.0 they added synhronous exceptions handling model and this model is used by default. Thanks for the clarification! I've also discovered it in the docs since I sent my mail. Martin
RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Martin Sebor wrote: Farid Zaripov wrote: I've just tried to declare and define __rw_once with throw(...) exception specification and compiler doesn't issues warning in that case. Yes, but the documentation linked to explicitly says... Explicit exception specifications are not allowed on C functions. [http://msdn2.microsoft.com/en-us/library/wfa0edys(VS.80).aspx] I tested, it does compile, and the destructors are getting called as they should when an explicit throw(...) spec is added to the C linkage function. That said, I cringe at the thought relying on behavior that is documented to not work or is not supported. Maybe when the documentation is referring to C functions it means functions that are compiled as C source [x.c instead of x.cpp] and not functions with C linkage? Good to know! We still need to decide how to handle this in the general case (for compilers that behave like MSVC, if there are any) but we can certainly start using this extension to silence the MSVC warnings. Is the goal really to just squelch the warnings? I hope not. So back at square one, I have another question. Lets assume a program will abort() if an exception is thrown through a C function. This characterization test will fail, and the build framework will probably set a preprocessor flag _RWSTD_NO_EXTERN_C_EXCEPTIONS. What exactly would we do to prevent this from being a problem? I can think of two things. 1. Add a try/catch block inside every once function definition that might throw. 2. Implement our own pthread_once() type function that has C++ linkage and use it with all configurations on all platforms. Both solutions are compatible with all systems, and would eliminate the warning on MSVC as a side effect. Obviously the first option isn't that pleasant because there is no _good_ way I can see to communicate a failure back to the application. Is there something wrong with the second option? Travis
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Travis Vitek wrote: Martin Sebor wrote: Farid Zaripov wrote: I've just tried to declare and define __rw_once with throw(...) exception specification and compiler doesn't issues warning in that case. Yes, but the documentation linked to explicitly says... Explicit exception specifications are not allowed on C functions. [http://msdn2.microsoft.com/en-us/library/wfa0edys(VS.80).aspx] Yet they describe the behavior of functions, including those with C linkage, in terms of explicit exception specification. How ironic! I tested, it does compile, and the destructors are getting called as they should when an explicit throw(...) spec is added to the C linkage function. That said, I cringe at the thought relying on behavior that is documented to not work or is not supported. No kidding! Maybe when the documentation is referring to C functions it means functions that are compiled as C source [x.c instead of x.cpp] and not functions with C linkage? Who knows... Have you tried it? Good to know! We still need to decide how to handle this in the general case (for compilers that behave like MSVC, if there are any) but we can certainly start using this extension to silence the MSVC warnings. Is the goal really to just squelch the warnings? I hope not. No, not just that (we could simply use #pragma warning to silence them if that was the only goal). So back at square one, I have another question. Lets assume a program will abort() if an exception is thrown through a C function. This characterization test will fail, and the build framework will probably set a preprocessor flag _RWSTD_NO_EXTERN_C_EXCEPTIONS. What exactly would we do to prevent this from being a problem? I can think of two things. 1. Add a try/catch block inside every once function definition that might throw. 2. Implement our own pthread_once() type function that has C++ linkage and use it with all configurations on all platforms. Both solutions are compatible with all systems, and would eliminate the warning on MSVC as a side effect. Obviously the first option isn't that pleasant because there is no _good_ way I can see to communicate a failure back to the application. Is there something wrong with the second option? Good questions. I suppose the potential overhead would be my biggest concern. The solution we discussed recently on another list (overloading pthread_once() for extern C++ functions) involves dynamically allocating a small chunk of memory. That's a steep price to pay for one time initialization. But we might be solving a non-issue. I'm not sure yet that there are any one-time initializers in the library that can throw an exception. So I think we're safe until we've actually found one that does. Although it surely would be nice to have a robust solution in place just in case we add an initializer that can throw in the future. Btw., there is another alternative: For compilers like MSVC that ignore the difference between extern C and extern C++ functions (i.e., where _RWSTD_NO_EXTERN_C_COMPATIBILITY is #undefined) we can just pass extern C++ functions to __rw_once(). Martin
RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Martin Sebor wrote: Maybe when the documentation is referring to C functions it means functions that are compiled as C source [x.c instead of x.cpp] and not functions with C linkage? Who knows... Have you tried it? I have now. The compiler chokes on 'throw' when compiling C sources as it should. Good questions. I suppose the potential overhead would be my biggest concern. The solution we discussed recently on another list (overloading pthread_once() for extern C++ functions) involves dynamically allocating a small chunk of memory. That's a steep price to pay for one time initialization. Well we wouldn't need to do that as the entire system would be implemented in C++. You already provide such an implementation for the windows configuration. But we might be solving a non-issue. I'm not sure yet that there are any one-time initializers in the library that can throw an exception. So I think we're safe until we've actually found one that does. Although it surely would be nice to have a robust solution in place just in case we add an initializer that can throw in the future. Agreed, and agreed.
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Travis Vitek wrote: Martin Sebor wrote: Maybe when the documentation is referring to C functions it means functions that are compiled as C source [x.c instead of x.cpp] and not functions with C linkage? Who knows... Have you tried it? I have now. The compiler chokes on 'throw' when compiling C sources as it should. Makes sense. So I wonder what the heck the purpose of throw(...) is supposed to be given that every C++ function is always (regardless of any compiler switches) implicitly declared with it and if it's not allowed on C functions (clearly it *is* allowed if the compiler accepts it, so what gives?) Martin
RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Martin Sebor wrote: Travis Vitek wrote: Martin, I'm not sure if you're aware, but I don't believe that the destructors for stack objects inside the C functions will be called. I know that this is the case for MSVC7/8. This isn't an issue for your testcase, but it may be an issue for the functions invoked by __rw_once. Interesting! I didn't know about this limitation. It's something we need to keep in mind when writing the initialization functions. Perhaps the solution will be to require the initialization function to have the empty exception specification. That way we could rely on the compiler to detect initialization functions that can throw. I just found out that the /Ehc flag enables the nothrow default for C linkage functions. So changing the /EHsc flag to /EHs will fix this for both VC7 and 8. Travis
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Travis Vitek wrote: Martin Sebor wrote: Travis Vitek wrote: Martin, I'm not sure if you're aware, but I don't believe that the destructors for stack objects inside the C functions will be called. I know that this is the case for MSVC7/8. This isn't an issue for your testcase, but it may be an issue for the functions invoked by __rw_once. Interesting! I didn't know about this limitation. It's something we need to keep in mind when writing the initialization functions. Perhaps the solution will be to require the initialization function to have the empty exception specification. That way we could rely on the compiler to detect initialization functions that can throw. I just found out that the /Ehc flag enables the nothrow default for C linkage functions. So changing the /EHsc flag to /EHs will fix this for both VC7 and 8. Do you happen to know if there's a #pragma that will let us select the mode we need for just the one function? Martin
RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Martin, I'm not sure if you're aware, but I don't believe that the destructors for stack objects inside the C functions will be called. I know that this is the case for MSVC7/8. This isn't an issue for your testcase, but it may be an issue for the functions invoked by __rw_once. I think this is by design, but I found it a little weird that the ascii value of the first character of each parameter is passed to div_throw/div_nothrow. I had the urge to add modify the argument processing lines to something more like this so that I could pass arguments and get the expected results. const int x = argc 2 ? 0 : int (*argv [1]) - '0'; const int y = argc 3 ? 0 : int (*argv [2]) - '0'; Travis Author: sebor Date: Tue Aug 14 15:48:02 2007 New Revision: 565959 URL: http://svn.apache.org/viewvc?view=revrev=565959 Log: 2007-08-14 Martin Sebor [EMAIL PROTECTED] * EXTERN_C_EXCEPTIONS.cpp: New config test to determine whether it's possible to throw exceptions from functions with C language linkage. Added: incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp (with props) Added: incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/src/EXTE RN_C_EXCEPTIONS.cpp?view=autorev=565959
RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Sorry, I should clarify that. Destructors for stack objects in C functions aren't called when an exception is thrown. Testcase... C:\(type t.cpp) (cl /nologo /EHsc t.cpp) struct Object { static int counter; Object() { Object::counter += 1; } ~Object() { Object::counter -= 1; } }; /* static */ int Object::counter = 0; extern C { int extern_c_function (int x, int y, int (*fun)(int, int)) { Object obj; if (fun) return fun (x, y); return 0; } int div_throw (int x, int y) { Object obj; if (0 == y) throw y; return x / y; } } // extern C int main (int argc, char *argv[]) { const int x = argc 2 ? 0 : int (*argv [1]) - '0'; const int y = argc 3 ? 0 : int (*argv [2]) - '0'; try { extern_c_function (x, y, div_throw); } catch (int res) { // nothing } return Object::counter != 0; } t.cpp t.cpp(32) : warning C4297: 'div_throw' : function assumed not to throw an exception but does The function is extern C and /EHc was specified C:\t 1 1 C:\if errorlevel 1 (echo failure) else (echo success!) success! C:\t 1 0 C:\if errorlevel 1 (echo failure!) else (echo success!) failure! -Original Message- From: Travis Vitek [mailto:[EMAIL PROTECTED] Sent: Tuesday, August 14, 2007 5:18 PM To: stdcxx-dev@incubator.apache.org Subject: RE: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp Martin, I'm not sure if you're aware, but I don't believe that the destructors for stack objects inside the C functions will be called. I know that this is the case for MSVC7/8. This isn't an issue for your testcase, but it may be an issue for the functions invoked by __rw_once. I think this is by design, but I found it a little weird that the ascii value of the first character of each parameter is passed to div_throw/div_nothrow. I had the urge to add modify the argument processing lines to something more like this so that I could pass arguments and get the expected results. const int x = argc 2 ? 0 : int (*argv [1]) - '0'; const int y = argc 3 ? 0 : int (*argv [2]) - '0'; Travis
Re: svn commit: r565959 - /incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp
Travis Vitek wrote: Martin, I'm not sure if you're aware, but I don't believe that the destructors for stack objects inside the C functions will be called. I know that this is the case for MSVC7/8. This isn't an issue for your testcase, but it may be an issue for the functions invoked by __rw_once. Interesting! I didn't know about this limitation. It's something we need to keep in mind when writing the initialization functions. Perhaps the solution will be to require the initialization function to have the empty exception specification. That way we could rely on the compiler to detect initialization functions that can throw. I think this is by design, but I found it a little weird that the ascii value of the first character of each parameter is passed to div_throw/div_nothrow. I had the urge to add modify the argument processing lines to something more like this so that I could pass arguments and get the expected results. Yeah, it doesn't make much sense. The only reason for the code is to try to prevent overachieving optimizers from generating C++ code for the C functions and doing the right thing in the simple test case. I should add a comment explaining this. Martin const int x = argc 2 ? 0 : int (*argv [1]) - '0'; const int y = argc 3 ? 0 : int (*argv [2]) - '0'; Travis Author: sebor Date: Tue Aug 14 15:48:02 2007 New Revision: 565959 URL: http://svn.apache.org/viewvc?view=revrev=565959 Log: 2007-08-14 Martin Sebor [EMAIL PROTECTED] * EXTERN_C_EXCEPTIONS.cpp: New config test to determine whether it's possible to throw exceptions from functions with C language linkage. Added: incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp (with props) Added: incubator/stdcxx/trunk/etc/config/src/EXTERN_C_EXCEPTIONS.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/src/EXTE RN_C_EXCEPTIONS.cpp?view=autorev=565959