Author: lattner Date: Thu Feb 17 20:08:43 2011 New Revision: 125817 URL: http://llvm.org/viewvc/llvm-project?rev=125817&view=rev Log: implement basic support for __label__. I wouldn't be shocked if there are bugs from other clients that don't expect to see a LabelDecl in a DeclStmt, but if so they should be easy to fix.
This implements most of PR3429 and rdar://8287027 Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/StmtDumper.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/Parse/ParseStmt.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/test/Parser/goto.c Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Feb 17 20:08:43 2011 @@ -62,6 +62,8 @@ "use of GNU indirect-goto extension">, InGroup<GNU>; def ext_gnu_address_of_label : Extension< "use of GNU address-of-label extension">, InGroup<GNU>; +def ext_gnu_local_label : Extension< + "use of GNU locally declared label extension">, InGroup<GNU>; def ext_gnu_statement_expr : Extension< "use of GNU statement expression extension">, InGroup<GNU>; def ext_gnu_conditional_expr : Extension< Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 17 20:08:43 2011 @@ -1414,7 +1414,8 @@ QualType T1, QualType T2, UnresolvedSetImpl &Functions); - LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc); + LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, + bool isLocalLabel = false); DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); Modified: cfe/trunk/lib/AST/StmtDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/lib/AST/StmtDumper.cpp (original) +++ cfe/trunk/lib/AST/StmtDumper.cpp Thu Feb 17 20:08:43 2011 @@ -282,6 +282,8 @@ UD->getTargetNestedNameDecl()->print(OS, PrintingPolicy(UD->getASTContext().getLangOptions())); OS << ";\""; + } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) { + OS << "label " << LD->getNameAsString(); } else { assert(0 && "Unexpected decl"); } Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Feb 17 20:08:43 2011 @@ -70,7 +70,6 @@ case Decl::Friend: case Decl::FriendTemplate: case Decl::Block: - case Decl::Label: assert(0 && "Declaration not should not be in declstmts!"); case Decl::Function: // void X(); case Decl::Record: // struct/union/class X; @@ -82,6 +81,7 @@ case Decl::UsingDirective: // using namespace X; [C++] case Decl::NamespaceAlias: case Decl::StaticAssert: // static_assert(X, ""); [C++0x] + case Decl::Label: // __label__ x; // None of these decls require codegen support. return; Modified: cfe/trunk/lib/Parse/ParseStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmt.cpp Thu Feb 17 20:08:43 2011 @@ -476,12 +476,41 @@ SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'. - // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are - // only allowed at the start of a compound stmt regardless of the language. - StmtVector Stmts(Actions); - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are + // only allowed at the start of a compound stmt regardless of the language. + while (Tok.is(tok::kw___label__)) { + SourceLocation LabelLoc = ConsumeToken(); + Diag(LabelLoc, diag::ext_gnu_local_label); + + llvm::SmallVector<Decl *, 8> DeclsInGroup; + while (1) { + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected_ident); + break; + } + + IdentifierInfo *II = Tok.getIdentifierInfo(); + SourceLocation IdLoc = ConsumeToken(); + DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, true)); + + if (!Tok.is(tok::comma)) + break; + ConsumeToken(); + } + + DeclSpec DS; + DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS, + DeclsInGroup.data(), DeclsInGroup.size()); + StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation()); + + ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); + if (R.isUsable()) + Stmts.push_back(R.release()); + } + + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { if (Tok.is(tok::annot_pragma_unused)) { HandlePragmaUnused(); continue; Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Feb 17 20:08:43 2011 @@ -2760,10 +2760,18 @@ /*InBaseClass=*/false, Consumer, Visited); } -LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc) { +/// LookupOrCreateLabel - Do a name lookup of a label with the specified name. +/// If isLocalLabel is true, then this is a definition of an __label__ label +/// name, otherwise it is a normal label definition or use. +LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, + bool isLocalLabel) { // Do a lookup to see if we have a label with this name already. - NamedDecl *Res = LookupSingleName(CurScope, II, Loc, LookupLabel, - NotForRedeclaration); + NamedDecl *Res = 0; + + // Local label definitions always shadow existing labels. + if (!isLocalLabel) + Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); + // If we found a label, check to see if it is in the same context as us. When // in a Block, we don't want to reuse a label in an enclosing function. if (Res && Res->getDeclContext() != CurContext) @@ -2772,7 +2780,8 @@ if (Res == 0) { // If not forward referenced or defined already, create the backing decl. Res = LabelDecl::Create(Context, CurContext, Loc, II); - PushOnScopeChains(Res, CurScope->getFnParent(), true); + PushOnScopeChains(Res, isLocalLabel ? CurScope : CurScope->getFnParent(), + true); } return cast<LabelDecl>(Res); Modified: cfe/trunk/test/Parser/goto.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/goto.c?rev=125817&r1=125816&r2=125817&view=diff ============================================================================== --- cfe/trunk/test/Parser/goto.c (original) +++ cfe/trunk/test/Parser/goto.c Thu Feb 17 20:08:43 2011 @@ -1,6 +1,30 @@ /* RUN: %clang_cc1 -fsyntax-only -verify %s */ -void foo() { +void test1() { goto ; /* expected-error {{expected identifier}} */ } + + +void test2() { + l: /* expected-note {{previous definition is here}} */ + + { + __label__ l; + l: goto l; + } + + { + __label__ l; + __label__ h; /* expected-error {{use of undeclared label 'h'}} */ + l: goto l; + } + + /* PR3429 & rdar://8287027 + */ + { + l: /* expected-error {{redefinition of label 'l'}} */ + ; + } + +} _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits