aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclBase.h1
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h1
-rw-r--r--include/clang/AST/Stmt.h42
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Parse/Parser.h57
-rw-r--r--include/clang/Sema/Sema.h7
-rw-r--r--include/clang/Serialization/ASTBitCodes.h2
-rw-r--r--include/clang/Serialization/ASTWriter.h1
-rw-r--r--lib/AST/Stmt.cpp6
-rw-r--r--lib/AST/StmtPrinter.cpp17
-rw-r--r--lib/AST/StmtProfile.cpp5
-rw-r--r--lib/Analysis/CFG.cpp6
-rw-r--r--lib/CodeGen/CGStmt.cpp7
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseExpr.cpp4
-rw-r--r--lib/Parse/ParseStmt.cpp181
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/SemaStmt.cpp11
-rw-r--r--lib/Sema/SemaStmtAttr.cpp48
-rw-r--r--lib/Sema/TreeTransform.h29
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp15
-rw-r--r--lib/Serialization/ASTWriter.cpp1
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--test/Parser/cxx11-stmt-attributes.cpp54
-rw-r--r--test/Parser/objcxx11-attributes.mm8
-rw-r--r--tools/libclang/CXCursor.cpp14
29 files changed, 388 insertions, 146 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 4c675aed8f..223289123e 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -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);
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index a4ad525701..f1b5171021 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -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, { })
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 84bdfb89ca..1b0f576e27 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -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 {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e553740ab1..b6b6398da9 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 67d71e44c0..e7718cd80c 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -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;
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 0e5e8c7d88..a9e7a74d69 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -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);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 31c410a9f9..e8a9ff6971 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -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,
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 4591630357..f9bb8928a3 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -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.
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 4c62385cf2..e693f17593 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -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.
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 6af20df4be..e4d9f0a1ef 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -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;
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 3a44183e20..0d1066b7e3 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -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());
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index e5526cea74..4bdded1d60 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -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());
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d1334a5431..f4d9a354a5 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -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))
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index bf42dcb8e2..a1d0789573 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -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
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index f57dd5f587..0f3f8f962c 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -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);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cf3dca20d9..be84cdc55a 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 7f3a815edc..6d31396cc0 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -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.
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index fdb9788667..44320dfcb3 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -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