[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

steve naroff snaroff at apple.com
Sat Feb 28 13:05:06 PST 2009


On Feb 28, 2009, at 2:48 PM, Chris Lattner wrote:

>
> On Feb 28, 2009, at 8:48 AM, Steve Naroff wrote:
>
>> Author: snaroff
>> Date: Sat Feb 28 10:48:43 2009
>> New Revision: 65694
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=65694&view=rev
>> Log:
>> Fix <rdar://problem/6451399> problems with labels and blocks.
>>
>> - Move the 'LabelMap' from Sema to Scope. To avoid layering  
>> problems, the second element is now a 'StmtTy *', which makes the  
>> LabelMap a bit more verbose to deal with.
>> - Add 'ActiveScope' to Sema. Managed by ActOnStartOfFunctionDef(),  
>> ObjCActOnStartOfMethodDef(), ActOnBlockStmtExpr().
>> - Changed ActOnLabelStmt(), ActOnGotoStmt(), ActOnAddrLabel(), and  
>> ActOnFinishFunctionBody() to use the new ActiveScope.
>> - Added FIXME to workaround in ActOnFinishFunctionBody() (for  
>> dealing with C++ nested functions).
>
> 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.

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

>>
>> +  /// 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).

>> +  // 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.

>
>
>> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Sat Feb 28 10:48:43 2009
>> @@ -165,12 +165,19 @@
>> Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
>>                     SourceLocation ColonLoc, StmtArg subStmt) {
>>  Stmt *SubStmt = static_cast<Stmt*>(subStmt.release());
>> +
>>  // Look up the record for this label identifier.
>> -  LabelStmt *&LabelDecl = LabelMap[II];
>> +  Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.find(II);
>>
>> +  LabelStmt *LabelDecl;
>> +
>>  // 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 *"?

>
>
>>  // Look up the record for this label identifier.
>> -  LabelStmt *&LabelDecl = LabelMap[LabelII];
>> +  Scope::LabelMapTy::iterator I = ActiveScope- 
>> >LabelMap.find(LabelII);
>
> likewise here.
>
> -Chris




More information about the cfe-commits mailing list