r205728 - Thread Safety Analysis: update to internal SExpr handling.
Delesley Hutchins
delesley at google.com
Tue Apr 8 15:36:19 PDT 2014
Thanks for the long and detailed review! Responses are below, fixes
are in r205809.
> It seems like a whole lot of these could be forward declares.
This is only included in one spot, so it doesn't matter all that much,
but I've tried to trim down the list. :-)
>> +// Simple Visitor class for traversing a clang CFG.
>> +class CFGVisitor {
>> ...
>> +};
>
> These all look very much like they should be virtual methods.
No. The traversal routine is templatized to avoid the overhead of
virtual calls.
> nullptr instead of 0?
Fixed, here and elsewhere.
>> + ~CFGWalker() { }
>
> Why is this required?
It's not. Deleted.
>> + // Initialize the CFGWalker. This setup only needs to be done once, even
>> + // if there are multiple passes over the CFG.
>> + bool init(AnalysisDeclContext &AC) {
>
> Why is this not a constructor when it only needs to be done once?
I want to decouple construction and initialization here.
>> + for (CFGBlock::const_iterator BI = CurrBlock->begin(),
>> + BE = CurrBlock->end();
>> + BI != BE; ++BI) {
>
> Range-based for loop?
Done.
> Getting rid of these const_casts would be wonderful, if possible.
I agree, but it's not possible in this case.
> Why are these all public?
Because of the way things are hooked together right now. Added TODO;
will fix later.
> It seems like a lot of these methods shouldn't be public.
Switched to protected.
> Why protected?
So it's possible to create derived builders.
>> +// Dump an SCFG to llvm::errs().
>> +void printSCFG(CFGWalker &walker);
>
> This seems like it'd be more reasonable as a dump() method on
> CFGWalker than a stand-alone function.
I disagree. CFGWalker is a tool to walk a clang::CFG, and is designed
for multiple passes with different visitors. printSCFG constructs and
prints a til::SCFG. It is mainly for testing purposes, and should not
be part of the public interface of CFGWalker.
> Everything in this file is in the til namespace, yet it has an odd
> mixture of naming conventions used. Eg) til::TILPrettyPrinter,
Good point. I fixed most of these. I kept the opcode ones, because I
like green bike sheds. :-)
> Can an existing container class suffice? I'm not keen on adding
> another container data type, much less exposing it like this.
I will switch to a different container in a future patch.
> You're kind of missing a virtual destructor here. Future inherits from
> SExpr and exposes virtual functions, so polymorphic deletion of a
> Future through a static type of SExpr would be problematic.
No, I very much do not want a virtual method table, because SExprs are
supposed to be very small, bump-allocated classes, and I have gone to
great lengths to avoid the extra overhead. Moreover, because they use
bump-allocation, SExpr destructors are never called. Future is the
only class which has a virtual method, and where I'm willing to pay
the memory penalty for having it.
> This isn't a typical pattern used in the code base, and it makes it
> harder to write const-correct code.
Already fixed in my last patch.
> expr() instead of clangExpr()? A bit of a bikeshed, but the name is
> just kind of odd to me.
No. expr() in other classes returns an SExpr, whereas this method
links back to clang::Expr.
> decl() instead of clangDecl() for the same reasoning as above?
No. Same reason as before. The TIL is a separate language, so any
links back to clang are spelled out for clarity.
> Why _x?
The default name for an unnamed variable is always 'x', but there
might be real variables with that name, so I add a leading underscore.
:-)
> Should there be an assert that NumUses >= 0 when detaching (to catch
> mismatches)?
Good idea. Added.
> Seems like NumUses should be unsigned.
Done. Now that there's an assert, I'm more comfortable with that decision. :-)
> I would really rather not see a constructor which steals memory from
> something else -- could it be a factory function instead, so it's at
> least a little more readily apparent to callers?
I've changed these to use move semantics for clarity. (As you have
noticed, my first patch had very little C++11.) A factory method
would break the pattern used by all of the other constructors.
> This would be more clear with reverse iterators (until we get a
> reverse range adapter).
Added TODO.
>> + void setArena(MemRegionRef A) { Arena = A; }
>
> This seems like it could be used as a constructor parameter instead.
Can't, without making it a constructor parameter of Traversal, which
is intended for use with classes that don't involve MemRegions.
>> +// Basic class for comparison operations over expressions.
>> +template <typename Self>
>> +class TILComparator {
>> +public:
>> + Self *self() { return reinterpret_cast<Self *>(this); }
>
> Does this need to be public?
Changed to protected.
> Why not private?
For future extension. There is more than one way to pretty print an expression.
> Why not an enumeration instead?
Mainly because I'm doing arithmetic with them.
> These two lines can be removed entirely instead of left commented out.
Except that I constantly uncomment them for testing. :-)
> Seems like CallExpr could use an arguments() range function that could
> be used here. ;-)
True. :-) As could several CFG routines.
>> +// Build a complete SCFG from a clang CFG.
>> +class SCFGBuilder : public CFGVisitor {
>> +public:
>> + // return true if E should be included in the SCFG
>> + bool includeExpr(til::SExpr* E) {
>
> This should be private. That goes for other members of this class as well.
Done.
> These are being leaked. unique_ptr perhaps?
Nice catch! Thanks! Fixed.
> All of these blocks wind up being leaked.
Thanks again. Fixed.
--
DeLesley Hutchins | Software Engineer | delesley at google.com | 505-206-0315
More information about the cfe-commits
mailing list