diff options
author | 2011-03-16 19:56:32 +0000 | |
---|---|---|
committer | 2011-03-16 19:56:32 +0000 | |
commit | 8cf858f3c0dd9f33cf17271a291ca389e808aa8c (patch) | |
tree | 01d88649b0ffed2cda9afd98aab3537830ea7d5f | |
parent | --- Merging r127373 into '.': (diff) | |
download | llvm-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.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Sema/IdentifierResolver.h | 9 | ||||
-rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseObjc.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/IdentifierResolver.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 19 | ||||
-rw-r--r-- | clang/test/SemaCXX/goto.cpp | 69 | ||||
-rw-r--r-- | clang/test/SemaObjCXX/goto.mm | 16 |
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 |