#include "clang/Parse/Action.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/DenseSet.h"
namespace clang {
UsingDirectivesTy UsingDirectives;
public:
- /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
- /// it (which acts like the label decl in some ways). Forward referenced
- /// labels have a LabelStmt created for them with a null location & SubStmt.
- typedef llvm::DenseMap<IdentifierInfo*, Action::StmtTy*> LabelMapTy;
- LabelMapTy LabelMap;
-
Scope(Scope *Parent, unsigned ScopeFlags) {
Init(Parent, ScopeFlags);
}
if (Flags & TemplateParamScope) TemplateParamParent = this;
DeclsInScope.clear();
UsingDirectives.clear();
- LabelMap.clear();
Entity = 0;
}
};
StdNamespace = 0;
TUScope = 0;
- ActiveScope = 0;
-
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
/// the active block object that represents it.
BlockSemaInfo *CurBlock;
- /// ActiveScope - If inside of a function, method, or block definition,
- /// this contains a pointer to the active scope that represents it.
- Scope *ActiveScope;
-
/// PackContext - Manages the stack for #pragma pack. An alignment
/// of 0 indicates default alignment.
void *PackContext; // Really a "PragmaPackStack*"
+ /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
+ /// it (which acts like the label decl in some ways). Forward referenced
+ /// labels have a LabelStmt created for them with a null location & SubStmt.
+ llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
+
llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
/// ExtVectorDecls - This is a list all the extended vector types. This allows
Decl *decl = static_cast<Decl*>(D);
FunctionDecl *FD = cast<FunctionDecl>(decl);
- ActiveScope = FnBodyScope;
-
// See if this is a redefinition.
const FunctionDecl *Definition;
if (FD->getBody(Definition)) {
return 0;
}
PopDeclContext();
-
- // 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;
-
// Verify and clean out per-function state.
- bool HaveLabels = !ActiveScope->LabelMap.empty();
+ bool HaveLabels = !LabelMap.empty();
// Check goto/label use.
- for (Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.begin(),
- E = ActiveScope->LabelMap.end(); I != E; ++I) {
+ for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
+ I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
// definitions are indicated with a null substmt.
- LabelStmt *L = static_cast<LabelStmt*>(I->second);
- if (L->getSubStmt() == 0) {
+ if (I->second->getSubStmt() == 0) {
+ LabelStmt *L = I->second;
// Emit error.
Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
}
}
}
- // This reset is for both functions and methods.
- ActiveScope = 0;
+ LabelMap.clear();
if (!Body) return D;
// Allow all of Sema to see that we are entering a method definition.
PushDeclContext(FnBodyScope, MDecl);
- ActiveScope = FnBodyScope;
-
// Create Decl objects for each parameter, entrring them in the scope for
// binding to their use.
SourceLocation LabLoc,
IdentifierInfo *LabelII) {
// Look up the record for this label identifier.
- llvm::DenseMap<IdentifierInfo*, Action::StmtTy*>::iterator I =
- ActiveScope->LabelMap.find(LabelII);
+ LabelStmt *&LabelDecl = LabelMap[LabelII];
- LabelStmt *LabelDecl;
-
// If we haven't seen this label yet, create a forward reference. It
// will be validated and/or cleaned up in ActOnFinishFunctionBody.
- if (I == ActiveScope->LabelMap.end()) {
+ if (LabelDecl == 0)
LabelDecl = new (Context) LabelStmt(LabLoc, LabelII, 0);
- ActiveScope->LabelMap.insert(std::make_pair(LabelII, LabelDecl));
- } else
- LabelDecl = static_cast<LabelStmt *>(I->second);
-
// Create the AST node. The address of a label always has type 'void*'.
return new (Context) AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
Context.getPointerType(Context.VoidTy));
// Add BSI to CurBlock.
BSI->PrevBlockInfo = CurBlock;
CurBlock = BSI;
- ActiveScope = BlockScope;
BSI->ReturnType = 0;
BSI->TheScope = BlockScope;
// Ensure that CurBlock is deleted.
llvm::OwningPtr<BlockSemaInfo> CC(CurBlock);
- // Before popping CurBlock, set ActiveScope to this scope's function
- // or block parent.
- ActiveScope = CurBlock->TheScope->getParent();
- while (ActiveScope &&
- ((ActiveScope->getFlags() & (Scope::FnScope | Scope::BlockScope)) == 0))
- ActiveScope = ActiveScope->getParent();
-
// Pop off CurBlock, handle nested blocks.
CurBlock = CurBlock->PrevBlockInfo;
PopDeclContext();
- // Before popping CurBlock, set ActiveScope to this scope's function
- // or block parent.
- ActiveScope = CurBlock->TheScope->getParent();
- while (ActiveScope &&
- ((ActiveScope->getFlags() & (Scope::FnScope | Scope::BlockScope)) == 0))
- ActiveScope = ActiveScope->getParent();
-
// Pop off CurBlock, handle nested blocks.
CurBlock = CurBlock->PrevBlockInfo;
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.
- Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.find(II);
+ LabelStmt *&LabelDecl = LabelMap[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);
+ if (LabelDecl == 0)
+ return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt));
assert(LabelDecl->getID() == II && "Label mismatch!");
return StmtError(Diag(GotoLoc, diag::err_goto_in_block));
// Look up the record for this label identifier.
- Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.find(LabelII);
+ LabelStmt *&LabelDecl = LabelMap[LabelII];
- LabelStmt *LabelDecl;
-
- // If not forward referenced or defined already, just create a new LabelStmt.
- if (I == ActiveScope->LabelMap.end()) {
+ // If we haven't seen this label yet, create a forward reference.
+ if (LabelDecl == 0)
LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0);
- ActiveScope->LabelMap.insert(std::make_pair(LabelII, LabelDecl));
- } else
- LabelDecl = static_cast<LabelStmt *>(I->second);
return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc));
}
-// RUN: clang %s -verify -fblocks -fsyntax-only
-
-int a() {
- A:if (1) xx();
- return ^{A:return 1;}();
-}
-int b() {
- A: return ^{int a; A:return 1;}();
-}
-
-int d() {
- A: return ^{int a; A: a = ^{int a; A:return 1;}() + ^{int b; A:return 2;}(); return a; }();
-}
-
-int c() {
- goto A; return ^{ A:return 1;}(); // expected-error {{use of undeclared label 'A'}}
-}