Here's an example of how this would be used: In the constructor for ConstantVector, there's an assert: assert(C->getType() == T->getElementType() && "Initializer for vector element doesn't match vector element type!"); I would change this to: ASSERT_STRM(C->getType() == T->getElementType(), "Initializer for vector element " << I - V.begin() << " with type " << C->getType() << " doesn't match vector element type " << T->getElementType()); With more detailed assertions like this, a much larger class of programmer errors can be diagnosed without having to go into the debugger. Because the stream is a raw_ostream, LLVM types and values can easily be printed to the stream without having to convert them to string form. Based on the suggestions so far, I'm guessing that the macro would look like this: #include "llvm/Support/raw_ostream.h" namespace llvm { // This just writes out "Assertion Failed" and the file/line number in // a form that IDEs can parse. void assertion_prologue(const char * file, unsigned line); // This does the trap or abort or whatever. void assertion_trap(); #if NDEBUG #define LLVM_ASSERT_STRM(expr, args) do {} while false // Alternatively // #define LLVM_ASSERT_STRM(expr, args) (void)0 #else /// Assertion macro that acts as an error output stream. Typical usage: /// /// LLVM_ASSERT_STRM(a != b, "Expected " << a << " == " << " b") #define LLVM_ASSERT_STRM(expr, args) \ do { if (!(expr)) { \ assertion_prologue(__FILE__, __LINE__); \ errs() << args << "\n"; \ assertion_trap(); \ } while (false) #endif /// Assertion macro that behaves like standard C assert(). #define LLVM_ASSERT(expr) LLVM_LLASSEERT_STRM(expr, #expr) /// Assertion macro that expects two values to be equal, as defined /// by the equality operator. #define LLVM_LLASSERT_EQ(expected, actual) \ LLVM_LLASSEERT_STRM(expected == actual, "Expected: " << expected << \ " but actually was " << actual) I'm open to suggestions on naming - LLVM_ASSERT_STRM may be a little too verbose, but you have to be careful about name collisions since macros aren't namespaced. In particular I want to avoid any overlap with Google Test, which has a bunch of ASSERT_XXX macros. On Tue, Jul 26, 2011 at 8:01 PM, Nathan Jeffords <blunted2night at gmail.com>wrote:> sorry, my previous message got sent too early > > I think the macro should look something like this: > > #define ASSERT_STRM(cond,expr) \ > do { > if (cond) { > std::cerr << expr << std::end; > assertion_trap (); > } > } while (false) > > > On Tue, Jul 26, 2011 at 7:57 PM, Nathan Jeffords <blunted2night at gmail.com>wrote: > >> wrapping the macro's body in: >> >> do { ... } while (false) >> >> would make the the macro a proper statement so that: >> >> if (cond) >> ASSERT(some_other_cond); >> else >> do_something_cool (); >> >> compiles as expected. >> >> IMO, it would work as such >> >> #define ASSERT_STM(cond,expr) >> >> >> On Tue, Jul 26, 2011 at 6:36 PM, Reid Kleckner <reid.kleckner at gmail.com>wrote: >> >>> He wants to be able to resume execution from the debugger after >>> assertion failure. >>> >>> Reid >>> >>> On Tue, Jul 26, 2011 at 8:07 PM, Alistair Lynn <arplynn at gmail.com> >>> wrote: >>> > Hi- >>> > >>> >> Yep, but tripping the debugger is highly non-portable. >>> > >>> > You're suggesting that inline asm is more portable than calling abort? >>> > >>> > Alistair >>> > >>> > _______________________________________________ >>> > LLVM Developers mailing list >>> > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>> > >>> >>> _______________________________________________ >>> LLVM Developers mailing list >>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>> >> >> > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110726/43267dcc/attachment.html>
For a non-verbose version, maybe "assertf" or "asserts", though that may be too short. Something like that could work if it where limited to non externally visible code (i.e. only cpp files or internal headers) On Tue, Jul 26, 2011 at 9:17 PM, Talin <viridia at gmail.com> wrote:> Here's an example of how this would be used: In the constructor for > ConstantVector, there's an assert: > > assert(C->getType() == T->getElementType() && > "Initializer for vector element doesn't match vector element > type!"); > > I would change this to: > > ASSERT_STRM(C->getType() == T->getElementType(), > "Initializer for vector element " << I - V.begin() << " with type " << > C->getType() << " doesn't match vector element type " << > T->getElementType()); > > With more detailed assertions like this, a much larger class of programmer > errors can be diagnosed without having to go into the debugger. > > Because the stream is a raw_ostream, LLVM types and values can easily be > printed to the stream without having to convert them to string form. > > Based on the suggestions so far, I'm guessing that the macro would look > like this: > > #include "llvm/Support/raw_ostream.h" > > namespace llvm { > > // This just writes out "Assertion Failed" and the file/line number in > // a form that IDEs can parse. > void assertion_prologue(const char * file, unsigned line); > > // This does the trap or abort or whatever. > void assertion_trap(); > > #if NDEBUG > #define LLVM_ASSERT_STRM(expr, args) do {} while false > // Alternatively > // #define LLVM_ASSERT_STRM(expr, args) (void)0 > #else > > /// Assertion macro that acts as an error output stream. Typical usage: > /// > /// LLVM_ASSERT_STRM(a != b, "Expected " << a << " == " << " b") > #define LLVM_ASSERT_STRM(expr, args) \ > do { if (!(expr)) { \ > assertion_prologue(__FILE__, __LINE__); \ > errs() << args << "\n"; \ > assertion_trap(); \ > } while (false) > > #endif > > /// Assertion macro that behaves like standard C assert(). > #define LLVM_ASSERT(expr) LLVM_LLASSEERT_STRM(expr, #expr) > > /// Assertion macro that expects two values to be equal, as defined > /// by the equality operator. > #define LLVM_LLASSERT_EQ(expected, actual) \ > LLVM_LLASSEERT_STRM(expected == actual, "Expected: " << expected << \ > " but actually was " << actual) > > > I'm open to suggestions on naming - LLVM_ASSERT_STRM may be a little too > verbose, but you have to be careful about name collisions since macros > aren't namespaced. In particular I want to avoid any overlap with Google > Test, which has a bunch of ASSERT_XXX macros. > > On Tue, Jul 26, 2011 at 8:01 PM, Nathan Jeffords <blunted2night at gmail.com>wrote: > >> sorry, my previous message got sent too early >> >> I think the macro should look something like this: >> >> #define ASSERT_STRM(cond,expr) \ >> do { >> if (cond) { >> std::cerr << expr << std::end; >> assertion_trap (); >> } >> } while (false) >> >> >> On Tue, Jul 26, 2011 at 7:57 PM, Nathan Jeffords <blunted2night at gmail.com >> > wrote: >> >>> wrapping the macro's body in: >>> >>> do { ... } while (false) >>> >>> would make the the macro a proper statement so that: >>> >>> if (cond) >>> ASSERT(some_other_cond); >>> else >>> do_something_cool (); >>> >>> compiles as expected. >>> >>> IMO, it would work as such >>> >>> #define ASSERT_STM(cond,expr) >>> >>> >>> On Tue, Jul 26, 2011 at 6:36 PM, Reid Kleckner <reid.kleckner at gmail.com>wrote: >>> >>>> He wants to be able to resume execution from the debugger after >>>> assertion failure. >>>> >>>> Reid >>>> >>>> On Tue, Jul 26, 2011 at 8:07 PM, Alistair Lynn <arplynn at gmail.com> >>>> wrote: >>>> > Hi- >>>> > >>>> >> Yep, but tripping the debugger is highly non-portable. >>>> > >>>> > You're suggesting that inline asm is more portable than calling abort? >>>> > >>>> > Alistair >>>> > >>>> > _______________________________________________ >>>> > LLVM Developers mailing list >>>> > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>> > >>>> >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>> >>> >>> >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> > > > -- > -- Talin >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110726/cb48deeb/attachment.html>
On Jul 26, 2011, at 9:17 PM, Talin wrote:> Here's an example of how this would be used: In the constructor for ConstantVector, there's an assert: > > assert(C->getType() == T->getElementType() && > "Initializer for vector element doesn't match vector element type!"); > > I would change this to: > > ASSERT_STRM(C->getType() == T->getElementType(), > "Initializer for vector element " << I - V.begin() << " with type " << > C->getType() << " doesn't match vector element type " << > T->getElementType()); > > With more detailed assertions like this, a much larger class of programmer errors can be diagnosed without having to go into the debugger. > > Because the stream is a raw_ostream, LLVM types and values can easily be printed to the stream without having to convert them to string form.I'm unconvinced that this is worth it at all. This is only going to allow you to "avoid going into the debugger" in the most trivial cases. -Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110726/886f2e3a/attachment.html>
On Tue, Jul 26, 2011 at 10:59 PM, Chris Lattner <clattner at apple.com> wrote:> > On Jul 26, 2011, at 9:17 PM, Talin wrote: > > Here's an example of how this would be used: In the constructor for > ConstantVector, there's an assert: > > assert(C->getType() == T->getElementType() && > "Initializer for vector element doesn't match vector element > type!"); > > I would change this to: > > ASSERT_STRM(C->getType() == T->getElementType(), > "Initializer for vector element " << I - V.begin() << " with type " << > C->getType() << " doesn't match vector element type " << > T->getElementType()); > > With more detailed assertions like this, a much larger class of programmer > errors can be diagnosed without having to go into the debugger. > > Because the stream is a raw_ostream, LLVM types and values can easily be > printed to the stream without having to convert them to string form. > > > I'm unconvinced that this is worth it at all. This is only going to allow > you to "avoid going into the debugger" in the most trivial cases. > > From an API user's perspective, those trivial cases happen quitefrequently, at least in my experience. Often times I only need to know what type is involved to figure out what went wrong. -Chris>-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110727/3cc5cf1e/attachment.html>
jo at durchholz.org
2011-Jul-27 14:43 UTC
[LLVMdev] Proposal for better assertions in LLVM
> I'm unconvinced that this is worth it at all. This is only going to allow > you to "avoid going into the debugger" in the most trivial cases.People doing something new tend to run into the trivial cases quite often. That's exactly the user population that will profit most from more informative error messages. E.g. people who're getting their feet wet with LLVM in general. Even more so, people starting to hack on LLVM. Just my 2c.
On Tue, Jul 26, 2011 at 10:59 PM, Chris Lattner <clattner at apple.com> wrote:> > On Jul 26, 2011, at 9:17 PM, Talin wrote: > > Here's an example of how this would be used: In the constructor for > ConstantVector, there's an assert: > > assert(C->getType() == T->getElementType() && > "Initializer for vector element doesn't match vector element > type!"); > > I would change this to: > > ASSERT_STRM(C->getType() == T->getElementType(), > "Initializer for vector element " << I - V.begin() << " with type " << > C->getType() << " doesn't match vector element type " << > T->getElementType()); > > With more detailed assertions like this, a much larger class of programmer > errors can be diagnosed without having to go into the debugger. > > Because the stream is a raw_ostream, LLVM types and values can easily be > printed to the stream without having to convert them to string form. > > > I'm unconvinced that this is worth it at all. This is only going to allow > you to "avoid going into the debugger" in the most trivial cases. > > Question - are you opposed to having a general "assertion with streamedarguments" facility in llvm/Support at all, or are you merely opposed to the work involved in replacing the existing assertions en-masse? If it's the latter, I'll make you a deal - every time I get an assert that I don't think gives me enough information, I'll send a patch to improve it. But that can only happen if the general mechanism is in place first. And I'd use that general mechanism in my own code regardless of whether it's used in LLVM or not.> -Chris >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110728/b254f536/attachment.html>