Diff Detail
Event Timeline
clang/include/clang/AST/Expr.h | ||
---|---|---|
2280–2285 | Replace with using Expr::Expr;? | |
2292–2316 | Don't use virtual functions here; we don't want to pay for a vtable in each CallExpr. Instead, make these non-virtual functions that dispatch based on the actual type (using dyn_cast / isa). | |
2305–2309 | If we want to guarantee that the arguments are contiguous, I don't think there's any need to expose getArgs here; new code should use arguments instead. (Also the return type of getArgs is wrong resulting in a violation of the aliasing rules -- another reason to avoid it.) | |
2311 | This setter should not be in the abstract interface. (It probably shouldn't be in the subtypes either.) |
clang/include/clang/AST/Expr.h | ||
---|---|---|
2292–2316 | Ah right, I was wondering whether it would be acceptable while writing this. |
@rsmith i hope i'm on the right track here.
It would be nice to throw out all the 10+ methods argument-getter and just use an ArrayRef, but it's a larger/scarier diff.
Also caching constructed ArrayRef doesn't work, as different parts of the codebase mutate expressions after construction =/
clang/include/clang/AST/Expr.h | ||
---|---|---|
2387 | This is a violation of the aliasing rules that we're trying to move away from (it's why we have the ExprIterator / ConstExprIterator classes rather than using ArrayRef here). Can we keep using the iterator_range<arg_iterator> approach? |
clang/include/clang/AST/Expr.h | ||
---|---|---|
2387 | Right, I see now. |
I realized that some of the motivating examples behind this patch also require uniform support for CXXNewExpr's placement arguments, otherwise we'd still have to duplicate code. And those have slightly different syntax, so it won't be a transparent change anymore (though it might be possible to avoid breaking the API by providing duplicate methods).
@rjmccall do you think you would have any suggestions on what can be done here?
The currently proposed version would have a non-virtual superclass which would use RTTI to dispatch to the generic parametersX methods.
That would require duplicating around 7 lines of boilerplate RTTI-dispatch code per each getter, and there are about 6 of them.
Er, by RTTI you mean just switching on getStmtClass()?
I'm not really opposed to this change in general, but I wonder if it's really the right way of achieving its goal, which appears to just be to make it easier to recognize user-level calls in the AST. Would it be better to just have a dedicated CallVisitor class that gets notified about all the different options, i.e. CallExpr, ObjCMessageExpr, CXXConstructExpr, operator new calls, and so on?
Er, by RTTI you mean just switching on getStmtClass()?
As far as I understand yes, basically doing dyn_cast myself as opposed to using virtual dispatch.
Would it be better to just have a dedicated CallVisitor class that gets notified about all the different options, i.e. CallExpr, ObjCMessageExpr, CXXConstructExpr, operator new calls, and so on?
We sort of have it in the analyzer, cf. CallEvent. A lot of code still ends up being duplicated/or worse, not general enough.
CallEvent looks like a good API to me. What do you think would become easier about it if you had this superclass? Or do people just not use CallEvent enough?
@rjmccall It's not sufficient.
- It requires context, which is not always available (that's the biggest problem).
- It can be too verbose - need to create a temporary object just when a simple isa/dyn_cast should suffice
For needed use cases: e.g. consider the duplication required in https://reviews.llvm.org/D48249
Okay, so you want an AST CallSite equivalent that just a failable constructor/factory? Something with the basic interface of ApplySite in Swift SIL:
https://github.com/apple/swift/blob/463a46704694ef27680f27095c05f1b901e07b80/include/swift/SIL/SILInstruction.h#L7501
Because this superclass gets you, like, 10% of the way there, and then will never ever get you any closer.
@rjmccall Sorry, I'm not quite sure what do you mean.
All the cases we have seen in the analyzer so far (and we have seen quite a lot) would have been solved by having generic arguments().
What currently ends up happening is that in the best case the good is duplicated, and in the worst case, the code does not handle unexpected types of calls correctly (objc-message-send instead of a function call)
Well, part of what I'm saying is that if you're willing to break away from the assumption that this is an abstract base class of various Expr classes, and instead just make it a separate class that just has its own convenient testing operations when you're starting with an Expr*, you can actually model calls that aren't just expressions with the same abstractions. Like you can have a CallSite that refers to the call to operator new in a CXXNewExpr, or to an implicit destructor call, or whatever.
Replace with using Expr::Expr;?