зеркало из https://github.com/microsoft/clang-1.git
Add an AttributedStmt type to represent a statement with C++11 attributes
attached. Since we do not support any attributes which appertain to a statement (yet), testing of this is necessarily quite minimal. Patch by Alexander Kornienko! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154723 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
9cdd1e3450
Коммит
534986f2b2
|
@ -861,7 +861,6 @@ public:
|
|||
void dumpXML(raw_ostream &OS) const;
|
||||
|
||||
private:
|
||||
const Attr *getAttrsImpl() const;
|
||||
void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);
|
||||
void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
|
||||
ASTContext &Ctx);
|
||||
|
|
|
@ -1870,6 +1870,7 @@ DEF_TRAVERSE_STMT(GotoStmt, { })
|
|||
DEF_TRAVERSE_STMT(IfStmt, { })
|
||||
DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
|
||||
DEF_TRAVERSE_STMT(LabelStmt, { })
|
||||
DEF_TRAVERSE_STMT(AttributedStmt, { })
|
||||
DEF_TRAVERSE_STMT(NullStmt, { })
|
||||
DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { })
|
||||
DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { })
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/AST/StmtIterator.h"
|
||||
#include "clang/AST/DeclGroup.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -794,6 +795,47 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/// \brief Represents an attribute applied to a statement.
|
||||
///
|
||||
/// Represents an attribute applied to a statement. For example:
|
||||
/// [[omp::for(...)]] for (...) { ... }
|
||||
///
|
||||
class AttributedStmt : public Stmt {
|
||||
Stmt *SubStmt;
|
||||
SourceLocation AttrLoc;
|
||||
AttrVec Attrs;
|
||||
// TODO: It can be done as Attr *Attrs[1]; and variable size array as in
|
||||
// StringLiteral
|
||||
|
||||
friend class ASTStmtReader;
|
||||
|
||||
public:
|
||||
AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt)
|
||||
: Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) {
|
||||
}
|
||||
|
||||
// \brief Build an empty attributed statement.
|
||||
explicit AttributedStmt(EmptyShell Empty)
|
||||
: Stmt(AttributedStmtClass, Empty) {
|
||||
}
|
||||
|
||||
SourceLocation getAttrLoc() const { return AttrLoc; }
|
||||
const AttrVec &getAttrs() const { return Attrs; }
|
||||
Stmt *getSubStmt() { return SubStmt; }
|
||||
const Stmt *getSubStmt() const { return SubStmt; }
|
||||
|
||||
SourceRange getSourceRange() const LLVM_READONLY {
|
||||
return SourceRange(AttrLoc, SubStmt->getLocEnd());
|
||||
}
|
||||
child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == AttributedStmtClass;
|
||||
}
|
||||
static bool classof(const AttributedStmt *) { return true; }
|
||||
};
|
||||
|
||||
|
||||
/// IfStmt - This represents an if/then/else.
|
||||
///
|
||||
class IfStmt : public Stmt {
|
||||
|
|
|
@ -1563,6 +1563,9 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
|
|||
def warn_attribute_ignored : Warning<"%0 attribute ignored">;
|
||||
def warn_unknown_attribute_ignored : Warning<
|
||||
"unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
|
||||
def warn_attribute_invalid_on_stmt : Warning<
|
||||
"attribute %0 cannot be specified on a statement">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def warn_declspec_attribute_ignored : Warning<
|
||||
"attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>;
|
||||
def warn_attribute_precede_definition : Warning<
|
||||
|
|
|
@ -12,6 +12,7 @@ class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> {
|
|||
def NullStmt : Stmt;
|
||||
def CompoundStmt : Stmt;
|
||||
def LabelStmt : Stmt;
|
||||
def AttributedStmt : Stmt;
|
||||
def IfStmt : Stmt;
|
||||
def SwitchStmt : Stmt;
|
||||
def WhileStmt : Stmt;
|
||||
|
|
|
@ -1517,42 +1517,40 @@ private:
|
|||
//===--------------------------------------------------------------------===//
|
||||
// C99 6.8: Statements and Blocks.
|
||||
|
||||
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = NULL) {
|
||||
StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0) {
|
||||
StmtVector Stmts(Actions);
|
||||
return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);
|
||||
}
|
||||
StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,
|
||||
StmtResult ParseStatementOrDeclaration(StmtVector &Stmts,
|
||||
bool OnlyStatement,
|
||||
SourceLocation *TrailingElseLoc = NULL);
|
||||
StmtResult ParseExprStatement(ParsedAttributes &Attrs);
|
||||
StmtResult ParseLabeledStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseCaseStatement(ParsedAttributes &Attr,
|
||||
bool MissingCase = false,
|
||||
SourceLocation *TrailingElseLoc = 0);
|
||||
StmtResult ParseStatementOrDeclarationAfterAttributes(
|
||||
StmtVector &Stmts,
|
||||
bool OnlyStatement,
|
||||
SourceLocation *TrailingElseLoc,
|
||||
ParsedAttributesWithRange &Attrs);
|
||||
StmtResult ParseExprStatement();
|
||||
StmtResult ParseLabeledStatement(ParsedAttributesWithRange &attrs);
|
||||
StmtResult ParseCaseStatement(bool MissingCase = false,
|
||||
ExprResult Expr = ExprResult());
|
||||
StmtResult ParseDefaultStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
|
||||
bool isStmtExpr = false);
|
||||
StmtResult ParseCompoundStatement(ParsedAttributes &Attr,
|
||||
bool isStmtExpr,
|
||||
StmtResult ParseDefaultStatement();
|
||||
StmtResult ParseCompoundStatement(bool isStmtExpr = false);
|
||||
StmtResult ParseCompoundStatement(bool isStmtExpr,
|
||||
unsigned ScopeFlags);
|
||||
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
|
||||
bool ParseParenExprOrCondition(ExprResult &ExprResult,
|
||||
Decl *&DeclResult,
|
||||
SourceLocation Loc,
|
||||
bool ConvertToBoolean);
|
||||
StmtResult ParseIfStatement(ParsedAttributes &Attr,
|
||||
SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseSwitchStatement(ParsedAttributes &Attr,
|
||||
SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseWhileStatement(ParsedAttributes &Attr,
|
||||
SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseDoStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseForStatement(ParsedAttributes &Attr,
|
||||
SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseGotoStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseContinueStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseBreakStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseReturnStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseDoStatement();
|
||||
StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);
|
||||
StmtResult ParseGotoStatement();
|
||||
StmtResult ParseContinueStatement();
|
||||
StmtResult ParseBreakStatement();
|
||||
StmtResult ParseReturnStatement();
|
||||
StmtResult ParseAsmStatement(bool &msAsm);
|
||||
StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
|
||||
|
||||
|
@ -1586,7 +1584,7 @@ private:
|
|||
/// \brief The behavior of this __if_exists or __if_not_exists block
|
||||
/// should.
|
||||
IfExistsBehavior Behavior;
|
||||
};
|
||||
};
|
||||
|
||||
bool ParseMicrosoftIfExistsCondition(IfExistsCondition& Result);
|
||||
void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
|
||||
|
@ -1602,14 +1600,14 @@ private:
|
|||
//===--------------------------------------------------------------------===//
|
||||
// C++ 6: Statements and Blocks
|
||||
|
||||
StmtResult ParseCXXTryBlock(ParsedAttributes &Attr);
|
||||
StmtResult ParseCXXTryBlock();
|
||||
StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
|
||||
StmtResult ParseCXXCatchBlock();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// MS: SEH Statements and Blocks
|
||||
|
||||
StmtResult ParseSEHTryBlock(ParsedAttributes &Attr);
|
||||
StmtResult ParseSEHTryBlock();
|
||||
StmtResult ParseSEHTryBlockCommon(SourceLocation Loc);
|
||||
StmtResult ParseSEHExceptBlock(SourceLocation Loc);
|
||||
StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
|
||||
|
@ -1883,6 +1881,7 @@ private:
|
|||
void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
|
||||
if (!attrs.Range.isValid()) return;
|
||||
DiagnoseProhibitedAttributes(attrs);
|
||||
attrs.clear();
|
||||
}
|
||||
void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
|
||||
|
||||
|
@ -1967,7 +1966,7 @@ private:
|
|||
|
||||
void ParseTypeofSpecifier(DeclSpec &DS);
|
||||
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
|
||||
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
|
||||
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
|
||||
|
|
|
@ -1974,6 +1974,10 @@ public:
|
|||
bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC);
|
||||
bool CheckNoReturnAttr(const AttributeList &attr);
|
||||
|
||||
/// \brief Stmt attributes - this routine is the top level dispatcher.
|
||||
StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
|
||||
SourceRange Range);
|
||||
|
||||
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
|
||||
bool &IncompleteImpl, unsigned DiagID);
|
||||
void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
|
||||
|
@ -2251,6 +2255,9 @@ public:
|
|||
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
||||
SourceLocation ColonLoc, Stmt *SubStmt);
|
||||
|
||||
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
|
||||
Stmt *SubStmt);
|
||||
|
||||
StmtResult ActOnIfStmt(SourceLocation IfLoc,
|
||||
FullExprArg CondVal, Decl *CondVar,
|
||||
Stmt *ThenVal,
|
||||
|
|
|
@ -964,6 +964,8 @@ namespace clang {
|
|||
STMT_DEFAULT,
|
||||
/// \brief A LabelStmt record.
|
||||
STMT_LABEL,
|
||||
/// \brief An AttributedStmt record.
|
||||
STMT_ATTRIBUTED,
|
||||
/// \brief An IfStmt record.
|
||||
STMT_IF,
|
||||
/// \brief A SwitchStmt record.
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
typedef SmallVectorImpl<uint64_t> RecordDataImpl;
|
||||
|
||||
friend class ASTDeclWriter;
|
||||
friend class ASTStmtWriter;
|
||||
private:
|
||||
/// \brief Map that provides the ID numbers of each type within the
|
||||
/// output stream, plus those deserialized from a chained PCH.
|
||||
|
|
|
@ -97,8 +97,8 @@ Stmt *Stmt::IgnoreImplicit() {
|
|||
|
||||
/// \brief Strip off all label-like statements.
|
||||
///
|
||||
/// This will strip off label statements, case statements, and default
|
||||
/// statements recursively.
|
||||
/// This will strip off label statements, case statements, attributed
|
||||
/// statements and default statements recursively.
|
||||
const Stmt *Stmt::stripLabelLikeStatements() const {
|
||||
const Stmt *S = this;
|
||||
while (true) {
|
||||
|
@ -106,6 +106,8 @@ const Stmt *Stmt::stripLabelLikeStatements() const {
|
|||
S = LS->getSubStmt();
|
||||
else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
|
||||
S = SC->getSubStmt();
|
||||
else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S))
|
||||
S = AS->getSubStmt();
|
||||
else
|
||||
return S;
|
||||
}
|
||||
|
|
|
@ -169,6 +169,23 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
|
|||
PrintStmt(Node->getSubStmt(), 0);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
|
||||
OS << "[[";
|
||||
bool first = true;
|
||||
for (AttrVec::const_iterator it = Node->getAttrs().begin(),
|
||||
end = Node->getAttrs().end();
|
||||
it != end; ++it) {
|
||||
if (!first) {
|
||||
OS << ", ";
|
||||
first = false;
|
||||
}
|
||||
// TODO: check this
|
||||
(*it)->printPretty(OS, Context);
|
||||
}
|
||||
OS << "]] ";
|
||||
PrintStmt(Node->getSubStmt(), 0);
|
||||
}
|
||||
|
||||
void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
|
||||
OS << "if (";
|
||||
PrintExpr(If->getCond());
|
||||
|
|
|
@ -109,6 +109,11 @@ void StmtProfiler::VisitLabelStmt(const LabelStmt *S) {
|
|||
VisitDecl(S->getDecl());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitAttributedStmt(const AttributedStmt *S) {
|
||||
VisitStmt(S);
|
||||
// TODO: maybe visit attributes?
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitIfStmt(const IfStmt *S) {
|
||||
VisitStmt(S);
|
||||
VisitDecl(S->getConditionVariable());
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/Basic/AttrKinds.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
@ -1069,6 +1070,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
|
|||
case Stmt::LambdaExprClass:
|
||||
return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
|
||||
|
||||
case Stmt::AttributedStmtClass:
|
||||
return Visit(cast<AttributedStmt>(S)->getSubStmt(), asc);
|
||||
|
||||
case Stmt::MemberExprClass:
|
||||
return VisitMemberExpr(cast<MemberExpr>(S), asc);
|
||||
|
||||
|
@ -1131,7 +1135,7 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
|
|||
|
||||
/// VisitChildren - Visit the children of a Stmt.
|
||||
CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) {
|
||||
CFGBlock *lastBlock = Block;
|
||||
CFGBlock *lastBlock = Block;
|
||||
for (Stmt::child_range I = Terminator->children(); I; ++I)
|
||||
if (Stmt *child = *I)
|
||||
if (CFGBlock *b = Visit(child))
|
||||
|
|
|
@ -79,6 +79,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
|
|||
case Stmt::CompoundStmtClass:
|
||||
case Stmt::DeclStmtClass:
|
||||
case Stmt::LabelStmtClass:
|
||||
case Stmt::AttributedStmtClass:
|
||||
case Stmt::GotoStmtClass:
|
||||
case Stmt::BreakStmtClass:
|
||||
case Stmt::ContinueStmtClass:
|
||||
|
@ -173,6 +174,8 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
|
|||
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
|
||||
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
|
||||
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
|
||||
case Stmt::AttributedStmtClass:
|
||||
EmitAttributedStmt(cast<AttributedStmt>(*S)); break;
|
||||
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
|
||||
case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
|
||||
case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
|
||||
|
@ -332,6 +335,10 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
|
|||
EmitStmt(S.getSubStmt());
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
|
||||
EmitStmt(S.getSubStmt());
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
|
||||
// If this code is reachable then emit a stop point (if generating
|
||||
// debug info). We have to do this ourselves because we are on the
|
||||
|
|
|
@ -1948,6 +1948,7 @@ public:
|
|||
void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt.
|
||||
|
||||
void EmitLabelStmt(const LabelStmt &S);
|
||||
void EmitAttributedStmt(const AttributedStmt &S);
|
||||
void EmitGotoStmt(const GotoStmt &S);
|
||||
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
|
||||
void EmitIfStmt(const IfStmt &S);
|
||||
|
|
|
@ -958,7 +958,7 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
|
|||
/// [C++] namespace-definition
|
||||
/// [C++] using-directive
|
||||
/// [C++] using-declaration
|
||||
/// [C++0x/C11] static_assert-declaration
|
||||
/// [C++11/C11] static_assert-declaration
|
||||
/// others... [FIXME]
|
||||
///
|
||||
Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
|
||||
|
|
|
@ -1926,11 +1926,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
|||
// unless they've already reported an error.
|
||||
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
|
||||
Diag(Tok, diag::ext_gnu_statement_expr);
|
||||
|
||||
Actions.ActOnStartStmtExpr();
|
||||
|
||||
ParsedAttributes attrs(AttrFactory);
|
||||
StmtResult Stmt(ParseCompoundStatement(attrs, true));
|
||||
StmtResult Stmt(ParseCompoundStatement(true));
|
||||
ExprType = CompoundStmt;
|
||||
|
||||
// If the substmt parsed correctly, build the AST node.
|
||||
|
|
|
@ -78,13 +78,30 @@ using namespace clang;
|
|||
StmtResult
|
||||
Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
|
||||
SourceLocation *TrailingElseLoc) {
|
||||
const char *SemiError = 0;
|
||||
StmtResult Res;
|
||||
|
||||
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
||||
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX0XAttributes(attrs, 0, /*MightBeObjCMessageSend*/ true);
|
||||
ParsedAttributesWithRange Attrs(AttrFactory);
|
||||
MaybeParseCXX0XAttributes(Attrs, 0, /*MightBeObjCMessageSend*/ true);
|
||||
|
||||
StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,
|
||||
OnlyStatement, TrailingElseLoc, Attrs);
|
||||
|
||||
assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
|
||||
"attributes on empty statement");
|
||||
|
||||
if (Attrs.empty() || Res.isInvalid())
|
||||
return Res;
|
||||
|
||||
return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range);
|
||||
}
|
||||
|
||||
StmtResult
|
||||
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
|
||||
bool OnlyStatement, SourceLocation *TrailingElseLoc,
|
||||
ParsedAttributesWithRange &Attrs) {
|
||||
const char *SemiError = 0;
|
||||
StmtResult Res;
|
||||
|
||||
// Cases in this switch statement should fall through if the parser expects
|
||||
// the token to end in a semicolon (in which case SemiError should be set),
|
||||
|
@ -95,6 +112,7 @@ Retry:
|
|||
switch (Kind) {
|
||||
case tok::at: // May be a @try or @throw statement
|
||||
{
|
||||
ProhibitAttributes(Attrs); // TODO: is it correct?
|
||||
AtLoc = ConsumeToken(); // consume @
|
||||
return ParseObjCAtStatement(AtLoc);
|
||||
}
|
||||
|
@ -108,7 +126,7 @@ Retry:
|
|||
Token Next = NextToken();
|
||||
if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
|
||||
// identifier ':' statement
|
||||
return ParseLabeledStatement(attrs);
|
||||
return ParseLabeledStatement(Attrs);
|
||||
}
|
||||
|
||||
if (Next.isNot(tok::coloncolon)) {
|
||||
|
@ -210,7 +228,7 @@ Retry:
|
|||
if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
|
||||
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
|
||||
DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext,
|
||||
DeclEnd, attrs);
|
||||
DeclEnd, Attrs);
|
||||
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
|
||||
}
|
||||
|
||||
|
@ -219,54 +237,54 @@ Retry:
|
|||
return StmtError();
|
||||
}
|
||||
|
||||
return ParseExprStatement(attrs);
|
||||
return ParseExprStatement();
|
||||
}
|
||||
|
||||
case tok::kw_case: // C99 6.8.1: labeled-statement
|
||||
return ParseCaseStatement(attrs);
|
||||
return ParseCaseStatement();
|
||||
case tok::kw_default: // C99 6.8.1: labeled-statement
|
||||
return ParseDefaultStatement(attrs);
|
||||
return ParseDefaultStatement();
|
||||
|
||||
case tok::l_brace: // C99 6.8.2: compound-statement
|
||||
return ParseCompoundStatement(attrs);
|
||||
return ParseCompoundStatement();
|
||||
case tok::semi: { // C99 6.8.3p3: expression[opt] ';'
|
||||
bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
|
||||
return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
|
||||
}
|
||||
|
||||
case tok::kw_if: // C99 6.8.4.1: if-statement
|
||||
return ParseIfStatement(attrs, TrailingElseLoc);
|
||||
return ParseIfStatement(TrailingElseLoc);
|
||||
case tok::kw_switch: // C99 6.8.4.2: switch-statement
|
||||
return ParseSwitchStatement(attrs, TrailingElseLoc);
|
||||
return ParseSwitchStatement(TrailingElseLoc);
|
||||
|
||||
case tok::kw_while: // C99 6.8.5.1: while-statement
|
||||
return ParseWhileStatement(attrs, TrailingElseLoc);
|
||||
return ParseWhileStatement(TrailingElseLoc);
|
||||
case tok::kw_do: // C99 6.8.5.2: do-statement
|
||||
Res = ParseDoStatement(attrs);
|
||||
Res = ParseDoStatement();
|
||||
SemiError = "do/while";
|
||||
break;
|
||||
case tok::kw_for: // C99 6.8.5.3: for-statement
|
||||
return ParseForStatement(attrs, TrailingElseLoc);
|
||||
return ParseForStatement(TrailingElseLoc);
|
||||
|
||||
case tok::kw_goto: // C99 6.8.6.1: goto-statement
|
||||
Res = ParseGotoStatement(attrs);
|
||||
Res = ParseGotoStatement();
|
||||
SemiError = "goto";
|
||||
break;
|
||||
case tok::kw_continue: // C99 6.8.6.2: continue-statement
|
||||
Res = ParseContinueStatement(attrs);
|
||||
Res = ParseContinueStatement();
|
||||
SemiError = "continue";
|
||||
break;
|
||||
case tok::kw_break: // C99 6.8.6.3: break-statement
|
||||
Res = ParseBreakStatement(attrs);
|
||||
Res = ParseBreakStatement();
|
||||
SemiError = "break";
|
||||
break;
|
||||
case tok::kw_return: // C99 6.8.6.4: return-statement
|
||||
Res = ParseReturnStatement(attrs);
|
||||
Res = ParseReturnStatement();
|
||||
SemiError = "return";
|
||||
break;
|
||||
|
||||
case tok::kw_asm: {
|
||||
ProhibitAttributes(attrs);
|
||||
ProhibitAttributes(Attrs);
|
||||
bool msAsm = false;
|
||||
Res = ParseAsmStatement(msAsm);
|
||||
Res = Actions.ActOnFinishFullStmt(Res.get());
|
||||
|
@ -276,16 +294,19 @@ Retry:
|
|||
}
|
||||
|
||||
case tok::kw_try: // C++ 15: try-block
|
||||
return ParseCXXTryBlock(attrs);
|
||||
return ParseCXXTryBlock();
|
||||
|
||||
case tok::kw___try:
|
||||
return ParseSEHTryBlock(attrs);
|
||||
ProhibitAttributes(Attrs); // TODO: is it correct?
|
||||
return ParseSEHTryBlock();
|
||||
|
||||
case tok::annot_pragma_vis:
|
||||
ProhibitAttributes(Attrs);
|
||||
HandlePragmaVisibility();
|
||||
return StmtEmpty();
|
||||
|
||||
case tok::annot_pragma_pack:
|
||||
ProhibitAttributes(Attrs);
|
||||
HandlePragmaPack();
|
||||
return StmtEmpty();
|
||||
}
|
||||
|
@ -306,11 +327,10 @@ Retry:
|
|||
}
|
||||
|
||||
/// \brief Parse an expression statement.
|
||||
StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {
|
||||
StmtResult Parser::ParseExprStatement() {
|
||||
// If a case keyword is missing, this is where it should be inserted.
|
||||
Token OldToken = Tok;
|
||||
|
||||
// FIXME: Use the attributes
|
||||
// expression[opt] ';'
|
||||
ExprResult Expr(ParseExpression());
|
||||
if (Expr.isInvalid()) {
|
||||
|
@ -331,7 +351,7 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {
|
|||
<< FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
|
||||
|
||||
// Recover parsing as a case statement.
|
||||
return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr);
|
||||
return ParseCaseStatement(/*MissingCase=*/true, Expr);
|
||||
}
|
||||
|
||||
// Otherwise, eat the semicolon.
|
||||
|
@ -339,7 +359,7 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {
|
|||
return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get()));
|
||||
}
|
||||
|
||||
StmtResult Parser::ParseSEHTryBlock(ParsedAttributes & Attrs) {
|
||||
StmtResult Parser::ParseSEHTryBlock() {
|
||||
assert(Tok.is(tok::kw___try) && "Expected '__try'");
|
||||
SourceLocation Loc = ConsumeToken();
|
||||
return ParseSEHTryBlockCommon(Loc);
|
||||
|
@ -358,13 +378,12 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
|
|||
if(Tok.isNot(tok::l_brace))
|
||||
return StmtError(Diag(Tok,diag::err_expected_lbrace));
|
||||
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
StmtResult TryBlock(ParseCompoundStatement(attrs));
|
||||
StmtResult TryBlock(ParseCompoundStatement());
|
||||
if(TryBlock.isInvalid())
|
||||
return move(TryBlock);
|
||||
|
||||
StmtResult Handler;
|
||||
if (Tok.is(tok::identifier) &&
|
||||
if (Tok.is(tok::identifier) &&
|
||||
Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
|
||||
SourceLocation Loc = ConsumeToken();
|
||||
Handler = ParseSEHExceptBlock(Loc);
|
||||
|
@ -418,8 +437,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
|
|||
if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen))
|
||||
return StmtError();
|
||||
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
StmtResult Block(ParseCompoundStatement(attrs));
|
||||
StmtResult Block(ParseCompoundStatement());
|
||||
|
||||
if(Block.isInvalid())
|
||||
return move(Block);
|
||||
|
@ -437,8 +455,7 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
|
|||
raii2(Ident___abnormal_termination, false),
|
||||
raii3(Ident_AbnormalTermination, false);
|
||||
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
StmtResult Block(ParseCompoundStatement(attrs));
|
||||
StmtResult Block(ParseCompoundStatement());
|
||||
if(Block.isInvalid())
|
||||
return move(Block);
|
||||
|
||||
|
@ -451,7 +468,7 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
|
|||
/// identifier ':' statement
|
||||
/// [GNU] identifier ':' attributes[opt] statement
|
||||
///
|
||||
StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
|
||||
StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
|
||||
assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
|
||||
"Not an identifier!");
|
||||
|
||||
|
@ -463,7 +480,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
|
|||
// identifier ':' statement
|
||||
SourceLocation ColonLoc = ConsumeToken();
|
||||
|
||||
// Read label attributes, if present.
|
||||
// Read label attributes, if present. attrs will contain both C++11 and GNU
|
||||
// attributes (if present) after this point.
|
||||
MaybeParseGNUAttributes(attrs);
|
||||
|
||||
StmtResult SubStmt(ParseStatement());
|
||||
|
@ -474,8 +492,10 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
|
|||
|
||||
LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
|
||||
IdentTok.getLocation());
|
||||
if (AttributeList *Attrs = attrs.getList())
|
||||
if (AttributeList *Attrs = attrs.getList()) {
|
||||
Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
|
||||
attrs.clear();
|
||||
}
|
||||
|
||||
return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
|
||||
SubStmt.get());
|
||||
|
@ -486,10 +506,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
|
|||
/// 'case' constant-expression ':' statement
|
||||
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
|
||||
///
|
||||
StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase,
|
||||
ExprResult Expr) {
|
||||
StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
|
||||
assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
|
||||
// FIXME: Use attributes?
|
||||
|
||||
// It is very very common for code to contain many case statements recursively
|
||||
// nested, as in (but usually without indentation):
|
||||
|
@ -625,9 +643,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase,
|
|||
/// 'default' ':' statement
|
||||
/// Note that this does not parse the 'statement' at the end.
|
||||
///
|
||||
StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {
|
||||
//FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseDefaultStatement() {
|
||||
assert(Tok.is(tok::kw_default) && "Not a default stmt!");
|
||||
SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
|
||||
|
||||
|
@ -668,9 +684,8 @@ StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {
|
|||
SubStmt.get(), getCurScope());
|
||||
}
|
||||
|
||||
StmtResult Parser::ParseCompoundStatement(ParsedAttributes &Attr,
|
||||
bool isStmtExpr) {
|
||||
return ParseCompoundStatement(Attr, isStmtExpr, Scope::DeclScope);
|
||||
StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
|
||||
return ParseCompoundStatement(isStmtExpr, Scope::DeclScope);
|
||||
}
|
||||
|
||||
/// ParseCompoundStatement - Parse a "{}" block.
|
||||
|
@ -700,11 +715,8 @@ StmtResult Parser::ParseCompoundStatement(ParsedAttributes &Attr,
|
|||
/// [OMP] barrier-directive
|
||||
/// [OMP] flush-directive
|
||||
///
|
||||
StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs,
|
||||
bool isStmtExpr,
|
||||
StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
|
||||
unsigned ScopeFlags) {
|
||||
//FIXME: Use attributes?
|
||||
|
||||
assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
|
||||
|
||||
// Enter a scope to hold everything within the compound stmt. Compound
|
||||
|
@ -894,10 +906,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
|
|||
/// [C++] 'if' '(' condition ')' statement
|
||||
/// [C++] 'if' '(' condition ')' statement 'else' statement
|
||||
///
|
||||
StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs,
|
||||
SourceLocation *TrailingElseLoc) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
|
||||
assert(Tok.is(tok::kw_if) && "Not an if stmt!");
|
||||
SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
|
||||
|
||||
|
@ -1028,10 +1037,7 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs,
|
|||
/// switch-statement:
|
||||
/// 'switch' '(' expression ')' statement
|
||||
/// [C++] 'switch' '(' condition ')' statement
|
||||
StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs,
|
||||
SourceLocation *TrailingElseLoc) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
|
||||
assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
|
||||
SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
|
||||
|
||||
|
@ -1119,10 +1125,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs,
|
|||
/// while-statement: [C99 6.8.5.1]
|
||||
/// 'while' '(' expression ')' statement
|
||||
/// [C++] 'while' '(' condition ')' statement
|
||||
StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs,
|
||||
SourceLocation *TrailingElseLoc) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
|
||||
assert(Tok.is(tok::kw_while) && "Not a while stmt!");
|
||||
SourceLocation WhileLoc = Tok.getLocation();
|
||||
ConsumeToken(); // eat the 'while'.
|
||||
|
@ -1194,9 +1197,7 @@ StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs,
|
|||
/// do-statement: [C99 6.8.5.2]
|
||||
/// 'do' statement 'while' '(' expression ')' ';'
|
||||
/// Note: this lets the caller parse the end ';'.
|
||||
StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseDoStatement() {
|
||||
assert(Tok.is(tok::kw_do) && "Not a do stmt!");
|
||||
SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
|
||||
|
||||
|
@ -1277,10 +1278,7 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
|
|||
/// [C++0x] for-range-initializer:
|
||||
/// [C++0x] expression
|
||||
/// [C++0x] braced-init-list [TODO]
|
||||
StmtResult Parser::ParseForStatement(ParsedAttributes &attrs,
|
||||
SourceLocation *TrailingElseLoc) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
|
||||
assert(Tok.is(tok::kw_for) && "Not a for stmt!");
|
||||
SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
|
||||
|
||||
|
@ -1535,9 +1533,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs,
|
|||
///
|
||||
/// Note: this lets the caller parse the end ';'.
|
||||
///
|
||||
StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseGotoStatement() {
|
||||
assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
|
||||
SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
|
||||
|
||||
|
@ -1571,9 +1567,7 @@ StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
|
|||
///
|
||||
/// Note: this lets the caller parse the end ';'.
|
||||
///
|
||||
StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseContinueStatement() {
|
||||
SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
|
||||
return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
|
||||
}
|
||||
|
@ -1584,9 +1578,7 @@ StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {
|
|||
///
|
||||
/// Note: this lets the caller parse the end ';'.
|
||||
///
|
||||
StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseBreakStatement() {
|
||||
SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
|
||||
return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
|
||||
}
|
||||
|
@ -1594,9 +1586,7 @@ StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {
|
|||
/// ParseReturnStatement
|
||||
/// jump-statement:
|
||||
/// 'return' expression[opt] ';'
|
||||
StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) {
|
||||
// FIXME: Use attributes?
|
||||
|
||||
StmtResult Parser::ParseReturnStatement() {
|
||||
assert(Tok.is(tok::kw_return) && "Not a return stmt!");
|
||||
SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
|
||||
|
||||
|
@ -2043,9 +2033,7 @@ bool Parser::trySkippingFunctionBody() {
|
|||
/// try-block:
|
||||
/// 'try' compound-statement handler-seq
|
||||
///
|
||||
StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) {
|
||||
// FIXME: Add attributes?
|
||||
|
||||
StmtResult Parser::ParseCXXTryBlock() {
|
||||
assert(Tok.is(tok::kw_try) && "Expected 'try'");
|
||||
|
||||
SourceLocation TryLoc = ConsumeToken();
|
||||
|
@ -2072,17 +2060,17 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
|
|||
if (Tok.isNot(tok::l_brace))
|
||||
return StmtError(Diag(Tok, diag::err_expected_lbrace));
|
||||
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
StmtResult TryBlock(ParseCompoundStatement(attrs, /*isStmtExpr=*/false,
|
||||
|
||||
StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
|
||||
Scope::DeclScope|Scope::TryScope));
|
||||
if (TryBlock.isInvalid())
|
||||
return move(TryBlock);
|
||||
|
||||
// Borland allows SEH-handlers with 'try'
|
||||
|
||||
if((Tok.is(tok::identifier) &&
|
||||
Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
|
||||
Tok.is(tok::kw___finally)) {
|
||||
if ((Tok.is(tok::identifier) &&
|
||||
Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
|
||||
Tok.is(tok::kw___finally)) {
|
||||
// TODO: Factor into common return ParseSEHHandlerCommon(...)
|
||||
StmtResult Handler;
|
||||
if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
|
||||
|
@ -2103,6 +2091,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
|
|||
}
|
||||
else {
|
||||
StmtVector Handlers(Actions);
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX0XAttributes(attrs);
|
||||
ProhibitAttributes(attrs);
|
||||
|
||||
|
@ -2168,8 +2157,7 @@ StmtResult Parser::ParseCXXCatchBlock() {
|
|||
return StmtError(Diag(Tok, diag::err_expected_lbrace));
|
||||
|
||||
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
|
||||
ParsedAttributes attrs(AttrFactory);
|
||||
StmtResult Block(ParseCompoundStatement(attrs));
|
||||
StmtResult Block(ParseCompoundStatement());
|
||||
if (Block.isInvalid())
|
||||
return move(Block);
|
||||
|
||||
|
@ -2188,24 +2176,23 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
|
|||
if (Result.Behavior == IEB_Dependent) {
|
||||
if (!Tok.is(tok::l_brace)) {
|
||||
Diag(Tok, diag::err_expected_lbrace);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
ParsedAttributes Attrs(AttrFactory);
|
||||
StmtResult Compound = ParseCompoundStatement(Attrs);
|
||||
|
||||
StmtResult Compound = ParseCompoundStatement();
|
||||
if (Compound.isInvalid())
|
||||
return;
|
||||
|
||||
|
||||
StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,
|
||||
Result.IsIfExists,
|
||||
Result.SS,
|
||||
Result.SS,
|
||||
Result.Name,
|
||||
Compound.get());
|
||||
if (DepResult.isUsable())
|
||||
Stmts.push_back(DepResult.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BalancedDelimiterTracker Braces(*this, tok::l_brace);
|
||||
if (Braces.consumeOpen()) {
|
||||
Diag(Tok, diag::err_expected_lbrace);
|
||||
|
|
|
@ -40,6 +40,7 @@ add_clang_library(clangSema
|
|||
SemaOverload.cpp
|
||||
SemaPseudoObject.cpp
|
||||
SemaStmt.cpp
|
||||
SemaStmtAttr.cpp
|
||||
SemaTemplate.cpp
|
||||
SemaTemplateDeduction.cpp
|
||||
SemaTemplateInstantiate.cpp
|
||||
|
|
|
@ -345,7 +345,6 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
|
|||
StmtResult
|
||||
Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
||||
SourceLocation ColonLoc, Stmt *SubStmt) {
|
||||
|
||||
// If the label was multiply defined, reject it now.
|
||||
if (TheDecl->getStmt()) {
|
||||
Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
|
||||
|
@ -361,6 +360,16 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
|||
return Owned(LS);
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
|
||||
const AttrVec &Attrs,
|
||||
Stmt *SubStmt) {
|
||||
// Fill in the declaration and return it. Variable length will require to
|
||||
// change this to AttributedStmt::Create(Context, ....);
|
||||
// and probably using ArrayRef
|
||||
AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);
|
||||
return Owned(LS);
|
||||
}
|
||||
|
||||
StmtResult
|
||||
Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
|
||||
Stmt *thenStmt, SourceLocation ElseLoc,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements stmt-related attribute processing.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "TargetAttributesSema.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Sema/DelayedDiagnostic.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
|
||||
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A) {
|
||||
switch (A.getKind()) {
|
||||
default:
|
||||
// if we're here, then we parsed an attribute, but didn't recognize it as a
|
||||
// statement attribute => it is declaration attribute
|
||||
S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt) <<
|
||||
A.getName()->getName();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
|
||||
SourceRange Range) {
|
||||
AttrVec Attrs;
|
||||
for (const AttributeList* l = AttrList; l; l = l->getNext()) {
|
||||
if (Attr *a = ProcessStmtAttribute(*this, S, *l))
|
||||
Attrs.push_back(a);
|
||||
}
|
||||
|
||||
if (Attrs.empty())
|
||||
return S;
|
||||
|
||||
return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
|
||||
}
|
|
@ -1044,6 +1044,15 @@ public:
|
|||
return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
|
||||
}
|
||||
|
||||
/// \brief Build a new label statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
|
||||
Stmt *SubStmt) {
|
||||
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
|
||||
}
|
||||
|
||||
/// \brief Build a new "if" statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -5154,14 +5163,30 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
|
|||
S->getDecl());
|
||||
if (!LD)
|
||||
return StmtError();
|
||||
|
||||
|
||||
|
||||
|
||||
// FIXME: Pass the real colon location in.
|
||||
return getDerived().RebuildLabelStmt(S->getIdentLoc(),
|
||||
cast<LabelDecl>(LD), SourceLocation(),
|
||||
SubStmt.get());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
|
||||
StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
|
||||
if (SubStmt.isInvalid())
|
||||
return StmtError();
|
||||
|
||||
// TODO: transform attributes
|
||||
if (SubStmt.get() == S->getSubStmt() /* && attrs are the same */)
|
||||
return S;
|
||||
|
||||
return getDerived().RebuildAttributedStmt(S->getAttrLoc(),
|
||||
S->getAttrs(),
|
||||
SubStmt.get());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
|
||||
|
|
|
@ -159,9 +159,18 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
|
|||
S->setIdentLoc(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
|
||||
VisitStmt(S);
|
||||
AttrVec Attrs;
|
||||
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
||||
S->Attrs = Attrs;
|
||||
S->SubStmt = Reader.ReadSubStmt();
|
||||
S->AttrLoc = ReadSourceLocation(Record, Idx);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitIfStmt(IfStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setConditionVariable(Reader.getContext(),
|
||||
S->setConditionVariable(Reader.getContext(),
|
||||
ReadDeclAs<VarDecl>(Record, Idx));
|
||||
S->setCond(Reader.ReadSubExpr());
|
||||
S->setThen(Reader.ReadSubStmt());
|
||||
|
@ -1630,6 +1639,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
S = new (Context) LabelStmt(Empty);
|
||||
break;
|
||||
|
||||
case STMT_ATTRIBUTED:
|
||||
S = new (Context) AttributedStmt(Empty);
|
||||
break;
|
||||
|
||||
case STMT_IF:
|
||||
S = new (Context) IfStmt(Empty);
|
||||
break;
|
||||
|
|
|
@ -651,6 +651,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
|
|||
RECORD(STMT_CASE);
|
||||
RECORD(STMT_DEFAULT);
|
||||
RECORD(STMT_LABEL);
|
||||
RECORD(STMT_ATTRIBUTED);
|
||||
RECORD(STMT_IF);
|
||||
RECORD(STMT_SWITCH);
|
||||
RECORD(STMT_WHILE);
|
||||
|
|
|
@ -106,6 +106,14 @@ void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
|
|||
Code = serialization::STMT_LABEL;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.WriteAttributes(S->getAttrs(), Record);
|
||||
Writer.AddStmt(S->getSubStmt());
|
||||
Writer.AddSourceLocation(S->getAttrLoc(), Record);
|
||||
Code = serialization::STMT_ATTRIBUTED;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.AddDeclRef(S->getConditionVariable(), Record);
|
||||
|
|
|
@ -536,6 +536,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
case Stmt::IfStmtClass:
|
||||
case Stmt::IndirectGotoStmtClass:
|
||||
case Stmt::LabelStmtClass:
|
||||
case Stmt::AttributedStmtClass:
|
||||
case Stmt::NoStmtClass:
|
||||
case Stmt::NullStmtClass:
|
||||
case Stmt::SwitchStmtClass:
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
|
||||
|
||||
void foo(int i) {
|
||||
|
||||
[[unknown_attribute]] ;
|
||||
[[unknown_attribute]] { }
|
||||
[[unknown_attribute]] if (0) { }
|
||||
[[unknown_attribute]] for (;;);
|
||||
[[unknown_attribute]] do {
|
||||
[[unknown_attribute]] continue;
|
||||
} while (0);
|
||||
[[unknown_attribute]] while (0);
|
||||
|
||||
[[unknown_attribute]] switch (i) {
|
||||
[[unknown_attribute]] case 0:
|
||||
[[unknown_attribute]] default:
|
||||
[[unknown_attribute]] break;
|
||||
}
|
||||
|
||||
[[unknown_attribute]] goto here;
|
||||
[[unknown_attribute]] here:
|
||||
|
||||
[[unknown_attribute]] try {
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
[[unknown_attribute]] return;
|
||||
|
||||
|
||||
alignas(8) ; // expected-warning {{attribute aligned cannot be specified on a statement}}
|
||||
[[noreturn]] { } // expected-warning {{attribute noreturn cannot be specified on a statement}}
|
||||
[[noreturn]] if (0) { } // expected-warning {{attribute noreturn cannot be specified on a statement}}
|
||||
[[noreturn]] for (;;); // expected-warning {{attribute noreturn cannot be specified on a statement}}
|
||||
[[noreturn]] do { // expected-warning {{attribute noreturn cannot be specified on a statement}}
|
||||
[[unavailable]] continue; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
} while (0);
|
||||
[[unknown_attributqqq]] while (0); // TODO: remove 'qqq' part and enjoy 'empty loop body' warning here (DiagnoseEmptyLoopBody)
|
||||
[[unknown_attribute]] while (0); // no warning here yet, just an unknown attribute
|
||||
|
||||
[[unused]] switch (i) { // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
[[uuid]] case 0: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
[[visibility]] default: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
[[carries_dependency]] break; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
|
||||
}
|
||||
|
||||
[[fastcall]] goto there; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
[[noinline]] there: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
|
||||
[[lock_returned]] try { // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
[[weakref]] return; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
|
||||
}
|
|
@ -31,15 +31,17 @@ void f(X *noreturn) {
|
|||
|
||||
// An attribute is OK.
|
||||
[[]];
|
||||
[[int(), noreturn]];
|
||||
[[int(), noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}}
|
||||
[[class, test(foo 'x' bar),,,]];
|
||||
[[bitand, noreturn]];
|
||||
[[bitand, noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}}
|
||||
|
||||
[[noreturn]]int(e)();
|
||||
int e2(); // expected-warning {{interpreted as a function declaration}} expected-note{{}}
|
||||
|
||||
// A function taking a noreturn function.
|
||||
int(f)([[noreturn]] int());
|
||||
int(f)([[noreturn]] int()); // expected-note {{here}}
|
||||
f(e);
|
||||
f(e2); // expected-error {{cannot initialize a parameter of type 'int (*)() __attribute__((noreturn))' with an lvalue of type 'int ()'}}
|
||||
|
||||
// Variables initialized by a message send.
|
||||
int(g)([[noreturn getSelf] getSize]);
|
||||
|
|
|
@ -247,19 +247,23 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
|
|||
case Stmt::CompoundStmtClass:
|
||||
K = CXCursor_CompoundStmt;
|
||||
break;
|
||||
|
||||
|
||||
case Stmt::NullStmtClass:
|
||||
K = CXCursor_NullStmt;
|
||||
break;
|
||||
|
||||
|
||||
case Stmt::LabelStmtClass:
|
||||
K = CXCursor_LabelStmt;
|
||||
break;
|
||||
|
||||
|
||||
case Stmt::AttributedStmtClass:
|
||||
K = CXCursor_UnexposedStmt;
|
||||
break;
|
||||
|
||||
case Stmt::DeclStmtClass:
|
||||
K = CXCursor_DeclStmt;
|
||||
break;
|
||||
|
||||
|
||||
case Stmt::IntegerLiteralClass:
|
||||
K = CXCursor_IntegerLiteral;
|
||||
break;
|
||||
|
@ -287,7 +291,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
|
|||
case Stmt::UnaryOperatorClass:
|
||||
K = CXCursor_UnaryOperator;
|
||||
break;
|
||||
|
||||
|
||||
case Stmt::CXXNoexceptExprClass:
|
||||
K = CXCursor_UnaryExpr;
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче