summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-03-16 19:56:32 +0000
committerBill Wendling <isanbard@gmail.com>2011-03-16 19:56:32 +0000
commit8cf858f3c0dd9f33cf17271a291ca389e808aa8c (patch)
tree01d88649b0ffed2cda9afd98aab3537830ea7d5f
parent--- Merging r127373 into '.': (diff)
downloadllvm-project-8cf858f3c0dd9f33cf17271a291ca389e808aa8c.tar.gz
llvm-project-8cf858f3c0dd9f33cf17271a291ca389e808aa8c.tar.bz2
llvm-project-8cf858f3c0dd9f33cf17271a291ca389e808aa8c.zip
--- Merging r127623 into '.':
A test/SemaCXX/goto.cpp U include/clang/Sema/IdentifierResolver.h U lib/Sema/SemaDecl.cpp U lib/Sema/IdentifierResolver.cpp --- Merging r127737 into '.': U test/SemaCXX/goto.cpp G include/clang/Sema/IdentifierResolver.h G lib/Sema/SemaDecl.cpp G lib/Sema/IdentifierResolver.cpp --- Merging r127738 into '.': A test/SemaObjCXX/goto.mm G test/SemaCXX/goto.cpp U include/clang/Parse/Parser.h U lib/Parse/ParseObjc.cpp U lib/Parse/ParseExpr.cpp U lib/Parse/ParseCXXInlineMethods.cpp U lib/Parse/ParseStmt.cpp U lib/Parse/Parser.cpp llvm-svn: 127752
-rw-r--r--clang/include/clang/Parse/Parser.h4
-rw-r--r--clang/include/clang/Sema/IdentifierResolver.h9
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp5
-rw-r--r--clang/lib/Parse/ParseExpr.cpp1
-rw-r--r--clang/lib/Parse/ParseObjc.cpp14
-rw-r--r--clang/lib/Parse/ParseStmt.cpp22
-rw-r--r--clang/lib/Parse/Parser.cpp5
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp23
-rw-r--r--clang/lib/Sema/SemaDecl.cpp19
-rw-r--r--clang/test/SemaCXX/goto.cpp69
-rw-r--r--clang/test/SemaObjCXX/goto.mm16
11 files changed, 167 insertions, 20 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 78bd04b6bd10..988fa92ccf35 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1271,8 +1271,8 @@ private:
SourceLocation *DeclEnd = 0);
Decl *ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- Decl *ParseFunctionStatementBody(Decl *Decl);
- Decl *ParseFunctionTryBlock(Decl *Decl);
+ Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
+ Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
/// \brief When in code-completion, skip parsing of the function/method body
/// unless the body contains the code-completion point.
diff --git a/clang/include/clang/Sema/IdentifierResolver.h b/clang/include/clang/Sema/IdentifierResolver.h
index 770f146e6a14..8385ce8ee12c 100644
--- a/clang/include/clang/Sema/IdentifierResolver.h
+++ b/clang/include/clang/Sema/IdentifierResolver.h
@@ -53,6 +53,11 @@ class IdentifierResolver {
/// declaration was not found, returns false.
bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+ /// \brief Insert the given declaration at the given position in the list.
+ void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) {
+ Decls.insert(Pos, D);
+ }
+
private:
DeclsTy Decls;
};
@@ -166,6 +171,10 @@ public:
/// (and, therefore, replaced).
bool ReplaceDecl(NamedDecl *Old, NamedDecl *New);
+ /// \brief Insert the given declaration after the given iterator
+ /// position.
+ void InsertDeclAfter(iterator Pos, NamedDecl *D);
+
/// \brief Link the declaration into the chain of declarations for
/// the given identifier.
///
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 399473840a94..baa038ea98da 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -261,7 +261,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
if (Tok.is(tok::kw_try)) {
- ParseFunctionTryBlock(LM.D);
+ ParseFunctionTryBlock(LM.D, FnScope);
assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
Tok.getLocation()) &&
"ParseFunctionTryBlock went over the cached tokens!");
@@ -276,13 +276,14 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// Error recovery.
if (!Tok.is(tok::l_brace)) {
+ FnScope.Exit();
Actions.ActOnFinishFunctionBody(LM.D, 0);
return;
}
} else
Actions.ActOnDefaultCtorInitializers(LM.D);
- ParseFunctionStatementBody(LM.D);
+ ParseFunctionStatementBody(LM.D, FnScope);
if (Tok.getLocation() != origLoc) {
// Due to parsing error, we either went over the cached tokens or
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 4a155a302f8d..03b34174296f 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1940,6 +1940,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
}
StmtResult Stmt(ParseCompoundStatementBody());
+ BlockScope.Exit();
if (!Stmt.isInvalid())
Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
else
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index f32a322f024a..6781bd3c49ed 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -1717,9 +1717,12 @@ Decl *Parser::ParseObjCMethodDefinition() {
// specified Declarator for the method.
Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl);
- if (PP.isCodeCompletionEnabled())
- if (trySkippingFunctionBodyForCodeCompletion())
+ if (PP.isCodeCompletionEnabled()) {
+ if (trySkippingFunctionBodyForCodeCompletion()) {
+ BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(MDecl, 0);
+ }
+ }
StmtResult FnBody(ParseCompoundStatementBody());
@@ -1728,12 +1731,11 @@ Decl *Parser::ParseObjCMethodDefinition() {
FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
MultiStmtArg(Actions), false);
- // TODO: Pass argument information.
- Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
-
// Leave the function body scope.
BodyScope.Exit();
-
+
+ // TODO: Pass argument information.
+ Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
return MDecl;
}
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index d1376accca90..e3e8dc507dba 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1522,14 +1522,17 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
return true;
}
-Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
+Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
- if (PP.isCodeCompletionEnabled())
- if (trySkippingFunctionBodyForCodeCompletion())
+ if (PP.isCodeCompletionEnabled()) {
+ if (trySkippingFunctionBodyForCodeCompletion()) {
+ BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, 0);
-
+ }
+ }
+
PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
"parsing function body");
@@ -1543,6 +1546,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
MultiStmtArg(Actions), false);
+ BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
}
@@ -1551,7 +1555,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
/// function-try-block:
/// 'try' ctor-initializer[opt] compound-statement handler-seq
///
-Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
+Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
@@ -1562,9 +1566,12 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
if (Tok.is(tok::colon))
ParseConstructorInitializer(Decl);
- if (PP.isCodeCompletionEnabled())
- if (trySkippingFunctionBodyForCodeCompletion())
+ if (PP.isCodeCompletionEnabled()) {
+ if (trySkippingFunctionBodyForCodeCompletion()) {
+ BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, 0);
+ }
+ }
SourceLocation LBraceLoc = Tok.getLocation();
StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
@@ -1574,6 +1581,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
MultiStmtArg(Actions), false);
+ BodyScope.Exit();
return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
}
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index d9b37d2c56cf..3946fc720807 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -801,7 +801,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
D.getMutableDeclSpec().abort();
if (Tok.is(tok::kw_try))
- return ParseFunctionTryBlock(Res);
+ return ParseFunctionTryBlock(Res, BodyScope);
// If we have a colon, then we're probably parsing a C++
// ctor-initializer.
@@ -810,13 +810,14 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Recover from error.
if (!Tok.is(tok::l_brace)) {
+ BodyScope.Exit();
Actions.ActOnFinishFunctionBody(Res, 0);
return Res;
}
} else
Actions.ActOnDefaultCtorInitializers(Res);
- return ParseFunctionStatementBody(Res);
+ return ParseFunctionStatementBody(Res, BodyScope);
}
/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
index 10856225ad0f..d520a6edabf8 100644
--- a/clang/lib/Sema/IdentifierResolver.cpp
+++ b/clang/lib/Sema/IdentifierResolver.cpp
@@ -168,6 +168,29 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
IDI->AddDecl(D);
}
+void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
+ DeclarationName Name = D->getDeclName();
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (Pos == iterator() || isDeclPtr(Ptr)) {
+ // Simple case: insert at the end of the list (which is the
+ // end of the stored vector).
+ AddDecl(D);
+ return;
+ }
+
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
+ // General case: insert the declaration at the appropriate point in the
+ // list, which already has at least two elements.
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ if (Pos.isIterator()) {
+ IDI->InsertDecl(Pos.getIterator() + 1, D);
+ } else
+ IDI->InsertDecl(IDI->decls_begin(), D);
+}
+
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
/// The decl must already be part of the decl chain.
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 126c5dcc8036..89b2185cf199 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -493,7 +493,24 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
}
S->AddDecl(D);
- IdResolver.AddDecl(D);
+
+ if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) {
+ // Implicitly-generated labels may end up getting generated in an order that
+ // isn't strictly lexical, which breaks name lookup. Be careful to insert
+ // the label at the appropriate place in the identifier chain.
+ for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) {
+ DeclContext *IDC = (*I)->getLexicalDeclContext();
+ if (IDC == CurContext) {
+ if (!S->isDeclScope(*I))
+ continue;
+ } else if (IDC->Encloses(CurContext))
+ break;
+ }
+
+ IdResolver.InsertDeclAfter(I, D);
+ } else {
+ IdResolver.AddDecl(D);
+ }
}
bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
diff --git a/clang/test/SemaCXX/goto.cpp b/clang/test/SemaCXX/goto.cpp
new file mode 100644
index 000000000000..8b8379613d81
--- /dev/null
+++ b/clang/test/SemaCXX/goto.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
+
+// PR9463
+double *end;
+void f() {
+ {
+ int end = 0;
+ goto end;
+ end = 1;
+ }
+
+ end:
+ return;
+}
+
+void g() {
+ end = 1; // expected-error{{assigning to 'double *' from incompatible type 'int'}}
+}
+
+void h(int end) {
+ {
+ goto end; // expected-error{{use of undeclared label 'end'}}
+ }
+}
+
+void h2(int end) {
+ {
+ __label__ end;
+ goto end;
+
+ end:
+ ::end = 0;
+ }
+ end:
+ end = 1;
+}
+
+class X {
+public:
+ X();
+};
+
+void rdar9135994()
+{
+X:
+ goto X;
+}
+
+namespace PR9495 {
+ struct NonPOD { NonPOD(); ~NonPOD(); };
+
+ void f(bool b) {
+ NonPOD np;
+ if (b) {
+ goto undeclared; // expected-error{{use of undeclared label 'undeclared'}}
+ }
+ }
+
+ void g() {
+ (void)^(bool b){
+ NonPOD np;
+ if (b) {
+ goto undeclared; // expected-error{{use of undeclared label 'undeclared'}}
+ }
+ };
+ }
+}
+
+
diff --git a/clang/test/SemaObjCXX/goto.mm b/clang/test/SemaObjCXX/goto.mm
new file mode 100644
index 000000000000..67df1f4c3240
--- /dev/null
+++ b/clang/test/SemaObjCXX/goto.mm
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR9495
+struct NonPOD { NonPOD(); ~NonPOD(); };
+
+@interface A
+@end
+
+@implementation A
+- (void)method:(bool)b {
+ NonPOD np;
+ if (b) {
+ goto undeclared; // expected-error{{use of undeclared label 'undeclared'}}
+ }
+}
+@end