implement full sema support for the GCC address-of-label extension.

llvm-svn: 39510
This commit is contained in:
Chris Lattner 2007-05-28 06:56:27 +00:00
parent e2473068d4
commit eefa10e78a
13 changed files with 104 additions and 44 deletions

View File

@ -14,6 +14,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/IdentifierTable.h"
using namespace llvm;
using namespace clang;
@ -74,3 +75,8 @@ bool Stmt::CollectingStats(bool enable) {
}
const char *LabelStmt::getName() const {
return getID()->getName();
}

View File

@ -132,7 +132,7 @@ void StmtPrinter::VisitDefaultStmt(DefaultStmt *Node) {
}
void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
Indent(-1) << Node->getLabel()->getName() << ":\n";
Indent(-1) << Node->getName() << ":\n";
PrintStmt(Node->getSubStmt(), 0);
}
@ -211,7 +211,7 @@ void StmtPrinter::VisitForStmt(ForStmt *Node) {
}
void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
Indent() << "goto " << Node->getLabel()->getLabel()->getName() << ";\n";
Indent() << "goto " << Node->getLabel()->getName() << ";\n";
}
void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {
@ -339,26 +339,6 @@ void StmtPrinter::VisitCastExpr(CastExpr *Node) {
OS << "(" << Node->getDestType().getAsString() << ")";
PrintExpr(Node->getSubExpr());
}
void StmtPrinter::VisitCXXCastExpr(CXXCastExpr *Node) {
switch (Node->getOpcode()) {
default:
assert(0 && "Not a C++ cast expression");
abort();
case CXXCastExpr::ConstCast: OS << "const_cast<"; break;
case CXXCastExpr::DynamicCast: OS << "dynamic_cast<"; break;
case CXXCastExpr::ReinterpretCast: OS << "reinterpret_cast<"; break;
case CXXCastExpr::StaticCast: OS << "static_cast<"; break;
}
OS << Node->getDestType().getAsString() << ">(";
PrintExpr(Node->getSubExpr());
OS << ")";
}
void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
OS << (Node->getValue() ? "true" : "false");
}
void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
PrintExpr(Node->getLHS());
OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
@ -372,6 +352,36 @@ void StmtPrinter::VisitConditionalOperator(ConditionalOperator *Node) {
PrintExpr(Node->getRHS());
}
// GNU extensions.
void StmtPrinter::VisitAddrLabel(AddrLabel *Node) {
OS << "&&" << Node->getLabel()->getName();
}
// C++
void StmtPrinter::VisitCXXCastExpr(CXXCastExpr *Node) {
switch (Node->getOpcode()) {
default:
assert(0 && "Not a C++ cast expression");
abort();
case CXXCastExpr::ConstCast: OS << "const_cast<"; break;
case CXXCastExpr::DynamicCast: OS << "dynamic_cast<"; break;
case CXXCastExpr::ReinterpretCast: OS << "reinterpret_cast<"; break;
case CXXCastExpr::StaticCast: OS << "static_cast<"; break;
}
OS << Node->getDestType().getAsString() << ">(";
PrintExpr(Node->getSubExpr());
OS << ")";
}
void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
OS << (Node->getValue() ? "true" : "false");
}
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//

View File

@ -549,17 +549,16 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
// unary-expression: '__alignof' '(' type-name ')'
return ParseSizeofAlignofExpression();
case tok::ampamp: { // unary-expression: '&&' identifier
Diag(Tok, diag::ext_gnu_address_of_label);
SourceLocation SavedLoc = ConsumeToken();
SourceLocation AmpAmpLoc = ConsumeToken();
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
return ExprResult(true);
}
// FIXME: Create a label ref for Tok.Ident.
Res = Actions.ParseUnaryOp(SavedLoc, SavedKind, 0);
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
Res = Actions.ParseAddrLabel(AmpAmpLoc, Tok.getLocation(),
Tok.getIdentifierInfo());
ConsumeToken();
return Res;
}
case tok::kw_const_cast:

View File

@ -197,7 +197,6 @@ Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) {
if (SubStmt.isInvalid)
SubStmt = Actions.ParseNullStmt(ColonLoc);
// FIXME: Enter this label into the symbol table for the function.
return Actions.ParseLabelStmt(IdentTok.getLocation(),
IdentTok.getIdentifierInfo(),
ColonLoc, SubStmt.Val);

View File

@ -236,6 +236,10 @@ public:
SourceLocation ColonLoc,
ExprTy *Cond, ExprTy *LHS, ExprTy *RHS);
/// ParseAddrLabel - Parse the GNU address of label extension: "&&foo".
virtual ExprResult ParseAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
IdentifierInfo *LabelII);
/// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
SourceLocation LAngleBracketLoc, TypeTy *Ty,

View File

@ -484,8 +484,7 @@ Sema::DeclTy *Sema::ParseFunctionDefBody(DeclTy *D, StmtTy *Body) {
if (I->second->getSubStmt() == 0) {
LabelStmt *L = I->second;
// Emit error.
Diag(L->getIdentLoc(), diag::err_undeclared_label_use,
L->getLabel()->getName());
Diag(L->getIdentLoc(), diag::err_undeclared_label_use, L->getName());
// At this point, we have gotos that use the bogus label. Stitch it into
// the function body so that they aren't leaked and that the AST is well

View File

@ -1064,7 +1064,6 @@ static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
case tok::kw___real: Opc = UnaryOperator::Real; break;
case tok::kw___imag: Opc = UnaryOperator::Imag; break;
case tok::ampamp: Opc = UnaryOperator::AddrLabel; break;
// FIXME: case tok::kw___extension__:
}
return Opc;
@ -1222,3 +1221,20 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
return true;
return new UnaryOperator((Expr *)Input, Opc, resultType, OpLoc);
}
/// ParseAddrLabel - Parse the GNU address of label extension: "&&foo".
Sema::ExprResult Sema::ParseAddrLabel(SourceLocation OpLoc,
SourceLocation LabLoc,
IdentifierInfo *LabelII) {
// Look up the record for this label identifier.
LabelStmt *&LabelDecl = LabelMap[LabelII];
// If we haven't seen this label yet, create a forward reference.
if (LabelDecl == 0)
LabelDecl = new LabelStmt(LabLoc, LabelII, 0);
// Create the AST node. The address of a label always has type 'void*'.
return new AddrLabel(OpLoc, LabLoc, LabelDecl,
Context.getPointerType(Context.VoidTy));
}

View File

@ -15,7 +15,6 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/Expr.h"
#include "clang/Parse/Scope.h"
#include "clang/Lex/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
using namespace llvm;
using namespace clang;
@ -61,12 +60,12 @@ Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
if (LabelDecl == 0)
return LabelDecl = new LabelStmt(IdentLoc, II, (Stmt*)SubStmt);
assert(LabelDecl->getLabel() == II && "Label mismatch!");
assert(LabelDecl->getID() == II && "Label mismatch!");
// Otherwise, this label was either forward reference or multiply defined. If
// multiply defined, reject it now.
if (LabelDecl->getSubStmt()) {
Diag(IdentLoc, diag::err_redefinition_of_label, II->getName());
Diag(IdentLoc, diag::err_redefinition_of_label, LabelDecl->getName());
Diag(LabelDecl->getIdentLoc(), diag::err_previous_definition);
return (Stmt*)SubStmt;
}

View File

@ -346,11 +346,11 @@
DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */,
DE67E7140C020EDF00F66BC5 /* Sema.h */,
DE67E7160C020EE400F66BC5 /* Sema.cpp */,
DE67E70A0C020EC500F66BC5 /* SemaType.cpp */,
DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */,
DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */,
DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */,
DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */,
DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */,
DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */,
DE67E70A0C020EC500F66BC5 /* SemaType.cpp */,
);
name = Sema;
sourceTree = "<group>";

View File

@ -230,7 +230,6 @@ public:
Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
SizeOf, AlignOf, // [C99 6.5.3.4] Sizeof (expr, not type) operator.
Real, Imag, // "__real expr"/"__imag expr" Extension.
AddrLabel, // && label Extension.
Extension // __extension__ marker.
};
@ -494,6 +493,26 @@ public:
static bool classof(const ConditionalOperator *) { return true; }
};
/// AddrLabel - The GNU address of label extension, representing &&label.
class AddrLabel : public Expr {
SourceLocation AmpAmpLoc, LabelLoc;
LabelStmt *Label;
public:
AddrLabel(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L, QualType t)
: Expr(AddrLabelClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
virtual SourceRange getSourceRange() const {
return SourceRange(AmpAmpLoc, LabelLoc);
}
LabelStmt *getLabel() const { return Label; }
virtual void visit(StmtVisitor &Visitor);
static bool classof(const Stmt *T) {
return T->getStmtClass() == AddrLabelClass;
}
static bool classof(const AddrLabel *) { return true; }
};
} // end namespace clang
} // end namespace llvm

View File

@ -141,7 +141,8 @@ public:
: Stmt(LabelStmtClass), IdentLoc(IL), Label(label), SubStmt(substmt) {}
SourceLocation getIdentLoc() const { return IdentLoc; }
IdentifierInfo *getLabel() { return Label; }
IdentifierInfo *getID() const { return Label; }
const char *getName() const;
Stmt *getSubStmt() { return SubStmt; }
void setIdentLoc(SourceLocation L) { IdentLoc = L; }

View File

@ -58,10 +58,13 @@ STMT(44, CastExpr , Expr)
STMT(45, BinaryOperator , Expr)
STMT(46, ConditionalOperator , Expr)
// GNU Extensions.
STMT(47, AddrLabel , Expr)
// C++ Expressions.
STMT(47, CXXCastExpr , CastExpr)
STMT(48, CXXBoolLiteralExpr , Expr)
LAST_EXPR(48)
STMT(48, CXXCastExpr , CastExpr)
STMT(49, CXXBoolLiteralExpr , Expr)
LAST_EXPR(49)
#undef STMT
#undef FIRST_STMT

View File

@ -247,7 +247,6 @@ public:
return 0;
}
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
@ -338,6 +337,12 @@ public:
return 0;
}
virtual ExprResult ParseAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
IdentifierInfo *LabelII) { // "&&foo"
return 0;
}
/// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
SourceLocation LAngleBracketLoc, TypeTy *Ty,