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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65694 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e99be90..98b8dbc 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2444,6 +2444,8 @@
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)) {
@@ -2586,17 +2588,29 @@
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 = !LabelMap.empty();
+ bool HaveLabels = !ActiveScope->LabelMap.empty();
// Check goto/label use.
- for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
- I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
+ for (Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.begin(),
+ E = ActiveScope->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.
- if (I->second->getSubStmt() == 0) {
- LabelStmt *L = I->second;
+ LabelStmt *L = static_cast<LabelStmt*>(I->second);
+ if (L->getSubStmt() == 0) {
// Emit error.
Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
@@ -2618,7 +2632,8 @@
}
}
}
- LabelMap.clear();
+ // This reset is for both functions and methods.
+ ActiveScope = 0;
if (!Body) return D;