forked from OSchip/llvm-project
implement full sema support for the GCC address-of-label extension.
llvm-svn: 39510
This commit is contained in:
parent
e2473068d4
commit
eefa10e78a
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue