On Wed, Jul 27, 2011 at 12:51 AM, Chandler Carruth <chandlerc at google.com>wrote:> On Tue, Jul 26, 2011 at 10:41 AM, Talin <viridia at gmail.com> wrote: > >> The assertions in LLVM would be a lot more useful if they could print out >> not only the source code of the expression that failed, but also print the >> values of the various arguments. To that end, I have an idea for an improved >> assert macro which would use raw_ostream. It would look something like this: >> >> ASSERT_STRM(Ty == STy, "Expected " << Ty << " but got " << >> STy->getElementType(0)); >> > > Chromium (and several other Google open source projects) have a somewhat > superior variant of this: > > > http://google.com/codesearch#hfE6470xZHk/base/logging.h&exact_package=http://src.chromium.org/git/chromium.git&q=CHECK&type=cs&l=398 > > It ends up looking like: > > CHECK(Ty == STy) << "Expected " << Ty << " .." << ...; > > The important difference is that most of the parameters go outside of the > macro rather than inside, making error messages way more intelligible. *If* > we want to go this direction in LLVM, I'd much rather see this formulation. > It's still easy to have it compile away to nothing using ?: operator. > > Can you explain how it avoids evaluating the arguments in the false case? Ilooked at the code but it's pretty complex.> *If* there is a desire to go this route, I've worked closely with several > variants of the pattern and would be happy to contribute a minimal > implementation. > > However, I agree with Chris's concerns about how useful this is in LLVM. > While I've used it on projects where it provides tremendous value, with LLVM > I often end up in the debugger anyways. I think the automatic debugger > trapping is marginally more useful, but only marginally. Having my debugger > discard the SIGABRT and continue isn't too hard. On the flip side, it might > make crash reports from users much more useful (in the absence of, or prior > to arriving at, a reduction). I think the cost is quite low, so maybe its > worth it, but maybe it isn't. > > I'll leave it to Chris and others to make the call, just wanted to make > sure a slightly different implementation was on the table in case it does go > in... >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110727/9e0f1cc0/attachment.html>
On Wed, Jul 27, 2011 at 3:31 PM, Talin <viridia at gmail.com> wrote:> Can you explain how it avoids evaluating the arguments in the false case? I > looked at the code but it's pretty complex. >Essentially it expands to something like: !(Ty == STy) ? (void)0 : Voidifier() & llvm::dbgs() << ... where you have something vaguely along the lines of struct Voidifier { void operator&(raw_ostream &); }; The conditional expression ensures that the side-effects of the LHS and RHS are contained, while allowing the convenient syntax. The voidifier hack is just for types, there are other simple ways to phrase it that boil down to the same construct. You could also implement it in LLVM as: if (!(Ty == STy)) {} else llvm::dbgs() which works as long as its not used as the lone statement in an unbraced else statement. The existing implementations are much more complex in order to support various different constructs. Something like the above would likely serve LLVM's needs. Again, I'm happy to provide a very minimal implementation for consideration if there is interest, I'm just not sure there is interest. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110727/1bd28b99/attachment.html>
If LLVM decides not to adopt it, I'd still like it for my own frontend. (If it does decide to adopt it, I'll use the LLVM version in my frontend.) On Wed, Jul 27, 2011 at 4:00 PM, Chandler Carruth <chandlerc at google.com>wrote:> On Wed, Jul 27, 2011 at 3:31 PM, Talin <viridia at gmail.com> wrote: > >> Can you explain how it avoids evaluating the arguments in the false case? >> I looked at the code but it's pretty complex. >> > > Essentially it expands to something like: > > !(Ty == STy) ? (void)0 : Voidifier() & llvm::dbgs() << ... > > where you have something vaguely along the lines of > > struct Voidifier { > void operator&(raw_ostream &); > }; > > The conditional expression ensures that the side-effects of the LHS and RHS > are contained, while allowing the convenient syntax. The voidifier hack is > just for types, there are other simple ways to phrase it that boil down to > the same construct. You could also implement it in LLVM as: > > if (!(Ty == STy)) {} else llvm::dbgs() > > which works as long as its not used as the lone statement in an unbraced > else statement. > > The existing implementations are much more complex in order to support > various different constructs. Something like the above would likely serve > LLVM's needs. Again, I'm happy to provide a very minimal implementation for > consideration if there is interest, I'm just not sure there is interest. >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110727/2a9c1d0c/attachment.html>
So I went ahead and implemented this in my own frontend - I've been using it for both assertions and conditional debug statements. I like it quite a bit, and like you say, it compiles down to nothing in non-debug builds. On Wed, Jul 27, 2011 at 4:00 PM, Chandler Carruth <chandlerc at google.com>wrote:> On Wed, Jul 27, 2011 at 3:31 PM, Talin <viridia at gmail.com> wrote: > >> Can you explain how it avoids evaluating the arguments in the false case? >> I looked at the code but it's pretty complex. >> > > Essentially it expands to something like: > > !(Ty == STy) ? (void)0 : Voidifier() & llvm::dbgs() << ... > > where you have something vaguely along the lines of > > struct Voidifier { > void operator&(raw_ostream &); > }; > > The conditional expression ensures that the side-effects of the LHS and RHS > are contained, while allowing the convenient syntax. The voidifier hack is > just for types, there are other simple ways to phrase it that boil down to > the same construct. You could also implement it in LLVM as: > > if (!(Ty == STy)) {} else llvm::dbgs() > > which works as long as its not used as the lone statement in an unbraced > else statement. > > The existing implementations are much more complex in order to support > various different constructs. Something like the above would likely serve > LLVM's needs. Again, I'm happy to provide a very minimal implementation for > consideration if there is interest, I'm just not sure there is interest. >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110808/aeac2de7/attachment.html>