-
Notifications
You must be signed in to change notification settings - Fork 593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify C++ exceptions #3380
Merged
Merged
Simplify C++ exceptions #3380
Changes from 2 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
7b91d9a
Refactor / simplify / fix C++ exceptions
bernardnormier 135b1b5
Cleanup
bernardnormier 6ec6d1a
Simplify Timer impl
bernardnormier fcd8dcc
More cleanup
bernardnormier 5a45e32
Include type ID in LocalException ice_print
bernardnormier 9b388b4
Merge remote-tracking branch 'origin/main' into cpp-exception
bernardnormier b732940
Add doc-comment for what()
bernardnormier File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,112 +1,49 @@ | ||
// | ||
// Copyright (c) ZeroC, Inc. All rights reserved. | ||
// | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#ifndef ICE_EXCEPTION_H | ||
#define ICE_EXCEPTION_H | ||
|
||
#include "Config.h" | ||
#include "ValueF.h" | ||
|
||
#include <exception> | ||
#include <memory> | ||
#include <ostream> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace Ice | ||
{ | ||
/** | ||
* Abstract base class for all Ice exceptions. It has only two derived classes: LocalException and UserException. | ||
* \headerfile Ice/Ice.h | ||
*/ | ||
/// Abstract base class for all Ice exceptions. It has only two derived classes: LocalException and UserException. | ||
/// \headerfile Ice/Ice.h | ||
class ICE_API Exception : public std::exception | ||
{ | ||
public: | ||
/** | ||
* Constructs an exception with a default message. | ||
* @param file The file where this exception is constructed. This C string is not copied. | ||
* @param line The line where this exception is constructed. | ||
*/ | ||
Exception(const char* file, int line) noexcept; | ||
|
||
/** | ||
* Constructs an exception. | ||
* @param file The file where this exception is constructed. This C string is not copied. | ||
* @param line The line where this exception is constructed. | ||
* @param message The error message adopted by this exception and returned by what(). | ||
*/ | ||
Exception(const char* file, int line, std::string message); | ||
|
||
/** | ||
* Copy constructor. | ||
* @param other The exception to copy. | ||
*/ | ||
Exception(const Exception& other) noexcept = default; | ||
|
||
/** | ||
* Assignment operator. | ||
* @param rhs The exception to assign. | ||
*/ | ||
Exception& operator=(const Exception& rhs) noexcept = default; | ||
|
||
/** | ||
* Returns the error message of this exception. | ||
* @return The error message. | ||
*/ | ||
[[nodiscard]] const char* what() const noexcept override; | ||
|
||
/** | ||
* Returns the type ID of this exception. This corresponds to the Slice type ID for Slice-defined exceptions, | ||
* and to a similar fully scoped name for other exceptions. For example "::Ice::CommunicatorDestroyedException". | ||
* @return The type ID of this exception | ||
*/ | ||
Exception() = default; | ||
Exception(const Exception&) = default; | ||
Exception& operator=(const Exception&) = default; | ||
|
||
// Need out-of-line virtual function to avoid weak vtable, which in turn requires the default constructor, | ||
// copy constructor, and copy assignment operator to be declared explicitly. | ||
~Exception() override; | ||
|
||
/// Returns the type ID of this exception. This corresponds to the Slice type ID for Slice-defined exceptions, | ||
/// and to a similar fully scoped name for other exceptions. For example | ||
/// "::Ice::CommunicatorDestroyedException". | ||
/// @return The type ID of this exception | ||
[[nodiscard]] virtual const char* ice_id() const noexcept = 0; | ||
|
||
/** | ||
* Outputs a description of this exception to a stream. This function is called by operator<<(std::ostream&, | ||
* const Ice::Exception&). The default implementation outputs ice_id(). The application can override the | ||
* ice_print of a user exception to produce a more detailed description, with typically the ice_id() plus | ||
* additional information. | ||
* @param os The output stream. | ||
*/ | ||
virtual void ice_print(std::ostream& os) const { os << ice_id(); } | ||
|
||
/** | ||
* Returns the name of the file where this exception was constructed. | ||
* @return The file name. | ||
*/ | ||
[[nodiscard]] const char* ice_file() const noexcept; | ||
|
||
/** | ||
* Returns the line number where this exception was constructed. | ||
* @return The line number. | ||
*/ | ||
[[nodiscard]] int ice_line() const noexcept; | ||
|
||
/** | ||
* Returns the stack trace at the point this exception was constructed. | ||
* @return The stack trace as a string, or an empty string if stack trace collection is not enabled. | ||
*/ | ||
[[nodiscard]] std::string ice_stackTrace() const; | ||
|
||
/** | ||
* Enables the collection of stack traces for exceptions. On Windows, calling this function more than once is | ||
* useful to refresh the symbol module list; on other platforms, the second and subsequent calls have no effect. | ||
*/ | ||
static void ice_enableStackTraceCollection(); | ||
|
||
private: | ||
friend ICE_API std::ostream& operator<<(std::ostream&, const Exception&); | ||
|
||
const char* _file; // can be nullptr | ||
int _line; // not used when _file is nullptr | ||
std::shared_ptr<std::string> _whatString; // shared storage for custom _what message. | ||
const char* _what; // can be nullptr | ||
std::shared_ptr<std::vector<void*>> _stackFrames; // shared storage for stack frames. | ||
/// Outputs a description of this exception to a stream. | ||
/// @param os The output stream. | ||
virtual void ice_print(std::ostream& os) const = 0; | ||
}; | ||
|
||
ICE_API std::ostream& operator<<(std::ostream&, const Exception&); | ||
/// Outputs a description of an Ice exception to a stream by calling the ice_print member function of this | ||
/// exception. | ||
/// @param os The output stream. | ||
/// @param exception The exception to describe. | ||
/// @return The output stream. | ||
inline std::ostream& operator<<(std::ostream& os, const Exception& exception) | ||
{ | ||
exception.ice_print(os); | ||
return os; | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,54 @@ | ||
// | ||
// Copyright (c) ZeroC, Inc. All rights reserved. | ||
// | ||
// Copyright (c) ZeroC, Inc. | ||
|
||
#ifndef ICE_LOCAL_EXCEPTION_H | ||
#define ICE_LOCAL_EXCEPTION_H | ||
|
||
#include "Exception.h" | ||
|
||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace Ice | ||
{ | ||
/** | ||
* Base class for all Ice exceptions not defined in Slice. | ||
* \headerfile Ice/Ice.h | ||
*/ | ||
/// Base class for all Ice exceptions not defined in Slice. | ||
/// \headerfile Ice/Ice.h | ||
class ICE_API LocalException : public Exception | ||
{ | ||
public: | ||
/** | ||
* Constructs a local exception. | ||
* @param file The file where this exception is constructed. This C string is not copied. | ||
* @param line The line where this exception is constructed. | ||
* @param message The error message adopted by this exception and returned by what(). | ||
*/ | ||
LocalException(const char* file, int line, std::string message) : Exception(file, line, std::move(message)) {} | ||
/// Constructs a local exception. | ||
/// @param file The file where this exception is constructed. This C string is not copied. | ||
/// @param line The line where this exception is constructed. | ||
/// @param message The error message adopted by this exception and returned by what(). | ||
LocalException(const char* file, int line, std::string message); | ||
|
||
[[nodiscard]] const char* what() const noexcept final; | ||
void ice_print(std::ostream& os) const final; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that
|
||
|
||
[[nodiscard]] const char* ice_id() const noexcept override; | ||
|
||
/// Gets the name of the file where this exception was constructed. | ||
/// @return The file name. | ||
[[nodiscard]] const char* ice_file() const noexcept; | ||
|
||
/// Gets the line number where this exception was constructed. | ||
/// @return The line number. | ||
[[nodiscard]] int ice_line() const noexcept; | ||
|
||
/// Gets the stack trace at the point this exception was constructed. | ||
/// @return The stack trace as a string, or an empty string if stack trace collection is not enabled. | ||
[[nodiscard]] std::string ice_stackTrace() const; | ||
|
||
/// Enables the collection of stack traces for exceptions. On Windows, calling this function more than once is | ||
/// useful to refresh the symbol module list; on other platforms, the second and subsequent calls have no | ||
/// effect. | ||
static void ice_enableStackTraceCollection(); | ||
|
||
private: | ||
const char* _file; | ||
int _line; | ||
std::shared_ptr<std::string> _whatString; // shared storage for custom _what message. | ||
std::shared_ptr<std::vector<void*>> _stackFrames; // shared storage for stack frames. | ||
}; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weak vtables break
dynamic_cast
andcatch(const XxxException&)
, and it's typically hard to find since we see these errors only at runtime. This particular weak vtable breaks the Ice/background test when it catchesconst Ice::Exception&
on macos.