mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-06 01:19:28 +00:00
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 llvm-svn: 125817
This commit is contained in:
parent
4ba77fa976
commit
43e7f31f11
@ -62,6 +62,8 @@ def ext_gnu_indirect_goto : Extension<
|
|||||||
"use of GNU indirect-goto extension">, InGroup<GNU>;
|
"use of GNU indirect-goto extension">, InGroup<GNU>;
|
||||||
def ext_gnu_address_of_label : Extension<
|
def ext_gnu_address_of_label : Extension<
|
||||||
"use of GNU address-of-label extension">, InGroup<GNU>;
|
"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<
|
def ext_gnu_statement_expr : Extension<
|
||||||
"use of GNU statement expression extension">, InGroup<GNU>;
|
"use of GNU statement expression extension">, InGroup<GNU>;
|
||||||
def ext_gnu_conditional_expr : Extension<
|
def ext_gnu_conditional_expr : Extension<
|
||||||
|
@ -1414,7 +1414,8 @@ public:
|
|||||||
QualType T1, QualType T2,
|
QualType T1, QualType T2,
|
||||||
UnresolvedSetImpl &Functions);
|
UnresolvedSetImpl &Functions);
|
||||||
|
|
||||||
LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc);
|
LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
|
||||||
|
bool isLocalLabel = false);
|
||||||
|
|
||||||
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
|
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
|
||||||
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
|
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
|
||||||
|
@ -282,6 +282,8 @@ void StmtDumper::DumpDeclarator(Decl *D) {
|
|||||||
UD->getTargetNestedNameDecl()->print(OS,
|
UD->getTargetNestedNameDecl()->print(OS,
|
||||||
PrintingPolicy(UD->getASTContext().getLangOptions()));
|
PrintingPolicy(UD->getASTContext().getLangOptions()));
|
||||||
OS << ";\"";
|
OS << ";\"";
|
||||||
|
} else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
|
||||||
|
OS << "label " << LD->getNameAsString();
|
||||||
} else {
|
} else {
|
||||||
assert(0 && "Unexpected decl");
|
assert(0 && "Unexpected decl");
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,6 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
|||||||
case Decl::Friend:
|
case Decl::Friend:
|
||||||
case Decl::FriendTemplate:
|
case Decl::FriendTemplate:
|
||||||
case Decl::Block:
|
case Decl::Block:
|
||||||
case Decl::Label:
|
|
||||||
assert(0 && "Declaration not should not be in declstmts!");
|
assert(0 && "Declaration not should not be in declstmts!");
|
||||||
case Decl::Function: // void X();
|
case Decl::Function: // void X();
|
||||||
case Decl::Record: // struct/union/class X;
|
case Decl::Record: // struct/union/class X;
|
||||||
@ -82,6 +81,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
|||||||
case Decl::UsingDirective: // using namespace X; [C++]
|
case Decl::UsingDirective: // using namespace X; [C++]
|
||||||
case Decl::NamespaceAlias:
|
case Decl::NamespaceAlias:
|
||||||
case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
|
case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
|
||||||
|
case Decl::Label: // __label__ x;
|
||||||
// None of these decls require codegen support.
|
// None of these decls require codegen support.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -476,12 +476,41 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
|||||||
|
|
||||||
SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
|
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);
|
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)) {
|
if (Tok.is(tok::annot_pragma_unused)) {
|
||||||
HandlePragmaUnused();
|
HandlePragmaUnused();
|
||||||
continue;
|
continue;
|
||||||
|
@ -2760,10 +2760,18 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
|
|||||||
/*InBaseClass=*/false, Consumer, Visited);
|
/*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.
|
// Do a lookup to see if we have a label with this name already.
|
||||||
NamedDecl *Res = LookupSingleName(CurScope, II, Loc, LookupLabel,
|
NamedDecl *Res = 0;
|
||||||
NotForRedeclaration);
|
|
||||||
|
// 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
|
// 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.
|
// in a Block, we don't want to reuse a label in an enclosing function.
|
||||||
if (Res && Res->getDeclContext() != CurContext)
|
if (Res && Res->getDeclContext() != CurContext)
|
||||||
@ -2772,7 +2780,8 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc) {
|
|||||||
if (Res == 0) {
|
if (Res == 0) {
|
||||||
// If not forward referenced or defined already, create the backing decl.
|
// If not forward referenced or defined already, create the backing decl.
|
||||||
Res = LabelDecl::Create(Context, CurContext, Loc, II);
|
Res = LabelDecl::Create(Context, CurContext, Loc, II);
|
||||||
PushOnScopeChains(Res, CurScope->getFnParent(), true);
|
PushOnScopeChains(Res, isLocalLabel ? CurScope : CurScope->getFnParent(),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cast<LabelDecl>(Res);
|
return cast<LabelDecl>(Res);
|
||||||
|
@ -1,6 +1,30 @@
|
|||||||
/* RUN: %clang_cc1 -fsyntax-only -verify %s
|
/* RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void foo() {
|
void test1() {
|
||||||
goto ; /* expected-error {{expected identifier}} */
|
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'}} */
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user