[cfe-commits] r65694 - in /cfe/trunk: include/clang/Parse/Scope.h lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaStmt.cpp test/Sema/block-labels.c

Chris Lattner clattner at apple.com
Sat Feb 28 18:38:04 PST 2009


On Feb 28, 2009, at 1:05 PM, steve naroff wrote:
>> Thanks for working on this Steve.  I somewhat concerned about the  
>> cost of this though: scopes are very frantically pushed and popped,  
>> and adding a densemap to them seems potentially expensive.  Two  
>> possible solutions: 1) use a separate explicit stack for these, or  
>> 2) make scope contain a pointer to a (lazily initialized) densemap  
>> instead of containing it by value.  #2 would only penalize scopes  
>> that actually contain labels which are pretty rare.
>>
>> What do you think?
>>
>
> I considered #1, however it seemed cleaner to leverage the existing  
> Scope mechanism (which is a catch-all by design).
>
> Is the cost to setup an empty DenseMap much greater than setting up  
> an empty SmallVector? If so, then I guess I'd prefer #2.

It is not amazingly expensive (the first malloc happens on the first  
insert) but a densemap is 4 words, so this significantly increases the  
size of Scope.

> I don't have a strong opinion. Just let me know what you prefer and  
> I'll take care of it.

I agree with you that #1 is gross.  #2 seems reasonable.

>
>
>>>
>>> +  /// ActiveScope - If inside of a function, method, or block  
>>> definition,
>>> +  /// this contains a pointer to the active scope that represents  
>>> it.
>>> +  Scope *ActiveScope;
>>
>>> +  /// PrevFunctionScope - This is the scope for the enclosing  
>>> function.
>>> +  /// For global blocks, this will be null.
>>> +  Scope *PrevFunctionScope;
>>
>> How are these different?  Have you seen that Scope has a bunch of  
>> things like FnParent etc that make getting this information very  
>> cheap.  It seems best to use these pointers because they are  
>> guaranteed up to date and don't require new code to maintain them.
>>
>
> Just committed a fix for this (good catch).

Ok, you removed PrevFunctionScope (yay!) but kept ActiveScope.  What  
is ActiveScope? Can it be removed?

>>> +  // FIXME: Temporary hack to workaround nested C++ functions.  
>>> For example:
>>> +  // class C2 {
>>> +  //   void f() {
>>> +  //     class LC1 {
>>> +  //       int m() { return 1; }
>>> +  //     };
>>> +  //   }
>>> +  // };
>>> +  if (ActiveScope == 0)
>>> +    return D;
>>> +
>>
>> I don't understand the issue here.  Why doesn't this work?
>
> The code was crashing because ActiveScope was null.

Ok, but why?

>>> // If not forward referenced or defined already, just create a new  
>>> LabelStmt.
>>> +  if (I == ActiveScope->LabelMap.end()) {
>>> +    LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt);
>>> +    ActiveScope->LabelMap.insert(std::make_pair(II, LabelDecl));
>>> +    return Owned(LabelDecl);
>>> +  } else
>>> +    LabelDecl = static_cast<LabelStmt *>(I->second);
>>
>> Instead of using find+insert, please use the old idiom of  
>> constructing a reference into the map, something like:
>>
>> LabelStmt *&LabelDecl = ActiveScope->LabelMap[II];
>> if (LabelDecl == 0) {
>> LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt);
>> ActiveScope->LabelMap.insert(std::make_pair(II, LabelDecl));
>> return Owned(LabelDecl);
>> }
>>
>> This eliminates a lookup for the insert.
>
> I tried doing this, however C++ casting seemed to get in my way. Is  
> it possible to do what you want when the LabelMap is declared to  
> take a "void *"?

Yes, use:

Action::StmtTy *&LabelDecl = ActiveScope->LabelMap[II];

Thanks Steve,

-Chris




More information about the cfe-commits mailing list