<div>Hi Alex,</div><div><br></div><div>I think the patch is generally looking pretty good. All of your TODOs seem like reasonable things to defer to later patches. I have some specific comments below (mostly formatting-related):</div>
<div><br></div><div>> Index: include/clang/Basic/StmtNodes.td</div><div>> ===================================================================</div><div>> --- include/clang/Basic/StmtNodes.td<span class="Apple-tab-span" style="white-space:pre">  </span>(revision 154056)</div>
<div>> +++ include/clang/Basic/StmtNodes.td<span class="Apple-tab-span" style="white-space:pre">     </span>(working copy)</div><div>> @@ -12,6 +12,7 @@</div><div>>  def NullStmt : Stmt;</div><div>>  def CompoundStmt : Stmt;</div>
<div>>  def LabelStmt : Stmt;</div><div>> +def AttributedStmt : Stmt;</div><div>>  def IfStmt : Stmt;</div><div>>  def SwitchStmt : Stmt;</div><div>>  def WhileStmt : Stmt;</div><div>> Index: include/clang/Sema/Sema.h</div>
<div>> ===================================================================</div><div>> --- include/clang/Sema/Sema.h<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 154056)</div><div>> +++ include/clang/Sema/Sema.h<span class="Apple-tab-span" style="white-space:pre">  </span>(working copy)</div>
<div>> @@ -1973,6 +1973,10 @@</div><div>>    bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC);</div><div>>    bool CheckNoReturnAttr(const AttributeList &attr);</div><div>>  </div>
<div>> +  // Stmt attributes - this routine is the top level dispatcher.</div><div>> +  StmtResult ProcessStmtAttributes(StmtResult Stmt, AttributeList *Attrs,</div><div>> +                                   SourceRange Range);</div>
<div><br></div><div>Please pass a Stmt * to this function, not a StmtResult. It's not meaningful</div><div>to pass an invalid statement in here.</div><div><br></div><div>> +</div><div>>    void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,</div>
<div>>                             bool &IncompleteImpl, unsigned DiagID);</div><div>>    void WarnConflictingTypedMethods(ObjCMethodDecl *Method,</div><div>> @@ -2250,6 +2254,9 @@</div><div>>    StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,</div>
<div>>                              SourceLocation ColonLoc, Stmt *SubStmt);</div><div>>  </div><div>> +  StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,</div><div>> +                                 Stmt *SubStmt);</div>
<div>> +</div><div>>    StmtResult ActOnIfStmt(SourceLocation IfLoc,</div><div>>                           FullExprArg CondVal, Decl *CondVar,</div><div>>                           Stmt *ThenVal,</div><div>> Index: include/clang/AST/DeclBase.h</div>
<div>> ===================================================================</div><div>> --- include/clang/AST/DeclBase.h<span class="Apple-tab-span" style="white-space:pre">  </span>(revision 154056)</div><div>> +++ include/clang/AST/DeclBase.h<span class="Apple-tab-span" style="white-space:pre">       </span>(working copy)</div>
<div>> @@ -861,7 +861,6 @@</div><div>>    void dumpXML(raw_ostream &OS) const;</div><div>>  </div><div>>  private:</div><div>> -  const Attr *getAttrsImpl() const;</div><div>>    void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);</div>
<div>>    void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,</div><div>>                             ASTContext &Ctx);</div><div>> Index: include/clang/AST/Stmt.h</div><div>> ===================================================================</div>
<div>> --- include/clang/AST/Stmt.h<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 154056)</div><div>> +++ include/clang/AST/Stmt.h<span class="Apple-tab-span" style="white-space:pre">   </span>(working copy)</div>
<div>> @@ -20,6 +20,7 @@</div><div>>  #include "clang/AST/StmtIterator.h"</div><div>>  #include "clang/AST/DeclGroup.h"</div><div>>  #include "clang/AST/ASTContext.h"</div><div>> +#include "clang/AST/Attr.h"</div>
<div>>  #include "llvm/ADT/SmallVector.h"</div><div>>  #include "llvm/Support/Compiler.h"</div><div>>  #include "llvm/Support/raw_ostream.h"</div><div>> @@ -794,6 +795,43 @@</div>
<div>>  };</div><div>>  </div><div>>  </div><div>> +/// AttributedStmt - Represents an attribute applied to a statement. For example:</div><div><br></div><div>Please wrap this line to 80 columns.</div><div><br>
</div><div>> +///   [[omp::for(...)]] for (...) { ... }</div><div>> +///</div><div>> +class AttributedStmt : public Stmt {</div><div>> +  Stmt *SubStmt;</div><div>> +  SourceLocation AttrLoc;</div><div>> +  AttrVec Attrs;</div>
<div>> +  // !!! TODO: It can be done as Attr *Attrs[1]; and variable size array as in</div><div>> +  // StringLiteral</div><div><br></div><div>Dealing with this as a separate commit is fine. Drop the "!!!", though.</div>
<div><br></div><div>> +</div><div>> +  friend class ASTStmtReader;</div><div>> +</div><div>> +public:</div><div>> +  AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt)</div><div>> +    : Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) {</div>
<div>> +  }</div><div>> +</div><div>> +  // \brief Build an empty attributed statement.</div><div>> +  explicit AttributedStmt(EmptyShell Empty) : Stmt(AttributedStmtClass, Empty) { }</div><div><br></div><div>
Please wrap this line to 80 columns.</div><div><br></div><div>> +</div><div>> +  SourceLocation getAttrLoc() const { return AttrLoc; }</div><div>> +  const AttrVec &getAttrs() const { return Attrs; }</div><div>
> +  Stmt *getSubStmt() { return SubStmt; }</div><div>> +  const Stmt *getSubStmt() const { return SubStmt; }</div><div>> +</div><div>> +  SourceRange getSourceRange() const LLVM_READONLY {</div><div>> +    return SourceRange(AttrLoc, SubStmt->getLocEnd());</div>
<div>> +  }</div><div>> +  child_range children() { return child_range(&SubStmt, &SubStmt+1); }</div><div>> +</div><div>> +  static bool classof(const Stmt *T) {</div><div>> +    return T->getStmtClass() == AttributedStmtClass;</div>
<div>> +  }</div><div>> +  static bool classof(const AttributedStmt *) { return true; }</div><div>> +};</div><div>> +</div><div>> +</div><div>>  /// IfStmt - This represents an if/then/else.</div><div>>  ///</div>
<div>>  class IfStmt : public Stmt {</div><div>> Index: include/clang/AST/RecursiveASTVisitor.h</div><div>> ===================================================================</div><div>> --- include/clang/AST/RecursiveASTVisitor.h<span class="Apple-tab-span" style="white-space:pre">    </span>(revision 154056)</div>
<div>> +++ include/clang/AST/RecursiveASTVisitor.h<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div><div>> @@ -1870,6 +1870,7 @@</div><div>>  DEF_TRAVERSE_STMT(IfStmt, { })</div><div>
>  DEF_TRAVERSE_STMT(IndirectGotoStmt, { })</div><div>>  DEF_TRAVERSE_STMT(LabelStmt, { })</div><div>> +DEF_TRAVERSE_STMT(AttributedStmt, { })</div><div>>  DEF_TRAVERSE_STMT(NullStmt, { })</div><div>>  DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { })</div>
<div>>  DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { })</div><div>> Index: include/clang/Parse/Parser.h</div><div>> ===================================================================</div><div>> --- include/clang/Parse/Parser.h<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 154056)</div>
<div>> +++ include/clang/Parse/Parser.h<span class="Apple-tab-span" style="white-space:pre"> </span>(working copy)</div><div>> @@ -1510,37 +1510,34 @@</div><div>>      return ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);</div>
<div>>    }</div><div>>    StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,</div><div>> -                                         bool OnlyStatement,</div><div>> +                                        bool OnlyStatement,</div>
<div>>                                          SourceLocation *TrailingElseLoc = NULL);</div><div><br></div><div>"= 0" is much more common in this file than "= NULL". Please change the "& " to</div>
<div>" &", too.</div><div><br></div><div>> -  StmtResult ParseExprStatement(ParsedAttributes &Attrs);</div><div>> +  StmtResult ParseStatementOrDeclarationAfterAttributes(StmtVector& Stmts,</div>
<div>> +                                        bool OnlyStatement,</div><div>> +                                        SourceLocation *TrailingElseLoc,</div><div>> +                                        ParsedAttributesWithRange &Attrs);</div>
<div><br></div><div>Please insert a newline after the '(' and line up all the parameters, and change</div><div>the "& " to " &".</div><div><br></div><div>> +  StmtResult ParseExprStatement();</div>
<div>>    StmtResult ParseLabeledStatement(ParsedAttributes &Attr);</div><div>> -  StmtResult ParseCaseStatement(ParsedAttributes &Attr,</div><div>> -                                bool MissingCase = false,</div>
<div>> +  StmtResult ParseCaseStatement(bool MissingCase = false,</div><div>>                                  ExprResult Expr = ExprResult());</div><div>> -  StmtResult ParseDefaultStatement(ParsedAttributes &Attr);</div>
<div>> -  StmtResult ParseCompoundStatement(ParsedAttributes &Attr,</div><div>> -                                    bool isStmtExpr = false);</div><div>> -  StmtResult ParseCompoundStatement(ParsedAttributes &Attr,</div>
<div>> -                                    bool isStmtExpr,</div><div>> +  StmtResult ParseDefaultStatement();</div><div>> +  StmtResult ParseCompoundStatement(bool isStmtExpr = false);</div><div>> +  StmtResult ParseCompoundStatement(bool isStmtExpr,</div>
<div>>                                      unsigned ScopeFlags);</div><div>>    StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);</div><div>>    bool ParseParenExprOrCondition(ExprResult &ExprResult,</div>
<div>>                                   Decl *&DeclResult,</div><div>>                                   SourceLocation Loc,</div><div>>                                   bool ConvertToBoolean);</div><div>> -  StmtResult ParseIfStatement(ParsedAttributes &Attr,</div>
<div>> -                              SourceLocation *TrailingElseLoc);</div><div>> -  StmtResult ParseSwitchStatement(ParsedAttributes &Attr,</div><div>> -                                  SourceLocation *TrailingElseLoc);</div>
<div>> -  StmtResult ParseWhileStatement(ParsedAttributes &Attr,</div><div>> -                                 SourceLocation *TrailingElseLoc);</div><div>> -  StmtResult ParseDoStatement(ParsedAttributes &Attr);</div>
<div>> -  StmtResult ParseForStatement(ParsedAttributes &Attr,</div><div>> -                               SourceLocation *TrailingElseLoc);</div><div>> -  StmtResult ParseGotoStatement(ParsedAttributes &Attr);</div>
<div>> -  StmtResult ParseContinueStatement(ParsedAttributes &Attr);</div><div>> -  StmtResult ParseBreakStatement(ParsedAttributes &Attr);</div><div>> -  StmtResult ParseReturnStatement(ParsedAttributes &Attr);</div>
<div>> +  StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);</div><div>> +  StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);</div><div>> +  StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);</div>
<div>> +  StmtResult ParseDoStatement();</div><div>> +  StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);</div><div>> +  StmtResult ParseGotoStatement();</div><div>> +  StmtResult ParseContinueStatement();</div>
<div>> +  StmtResult ParseBreakStatement();</div><div>> +  StmtResult ParseReturnStatement();</div><div>>    StmtResult ParseAsmStatement(bool &msAsm);</div><div>>    StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);</div>
<div>>  </div><div>> @@ -1590,14 +1587,14 @@</div><div>>    //===--------------------------------------------------------------------===//</div><div>>    // C++ 6: Statements and Blocks</div><div>>  </div><div>
> -  StmtResult ParseCXXTryBlock(ParsedAttributes &Attr);</div><div>> +  StmtResult ParseCXXTryBlock();</div><div>>    StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);</div><div>>    StmtResult ParseCXXCatchBlock();</div>
<div>>  </div><div>>    //===--------------------------------------------------------------------===//</div><div>>    // MS: SEH Statements and Blocks</div><div>>  </div><div>> -  StmtResult ParseSEHTryBlock(ParsedAttributes &Attr);</div>
<div>> +  StmtResult ParseSEHTryBlock();</div><div>>    StmtResult ParseSEHTryBlockCommon(SourceLocation Loc);</div><div>>    StmtResult ParseSEHExceptBlock(SourceLocation Loc);</div><div>>    StmtResult ParseSEHFinallyBlock(SourceLocation Loc);</div>
<div>> @@ -1942,7 +1939,7 @@</div><div>>  </div><div>>    void ParseTypeofSpecifier(DeclSpec &DS);</div><div>>    SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);</div><div>> -  void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, </div>
<div>> +  void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,</div><div>>                                           SourceLocation StartLoc,</div><div>>                                           SourceLocation EndLoc);</div>
<div>>    void ParseUnderlyingTypeSpecifier(DeclSpec &DS);</div><div>> Index: include/clang/Serialization/ASTBitCodes.h</div><div>> ===================================================================</div><div>
> --- include/clang/Serialization/ASTBitCodes.h<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 154056)</div><div>> +++ include/clang/Serialization/ASTBitCodes.h<span class="Apple-tab-span" style="white-space:pre">  </span>(working copy)</div>
<div>> @@ -964,6 +964,8 @@</div><div>>        STMT_DEFAULT,</div><div>>        /// \brief A LabelStmt record.</div><div>>        STMT_LABEL,</div><div>> +      /// \brief An AttributedStmt record.</div><div>
> +      STMT_ATTRIBUTED,</div><div>>        /// \brief An IfStmt record.</div><div>>        STMT_IF,</div><div>>        /// \brief A SwitchStmt record.</div><div>> Index: include/clang/Serialization/ASTWriter.h</div>
<div>> ===================================================================</div><div>> --- include/clang/Serialization/ASTWriter.h<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 154056)</div><div>
> +++ include/clang/Serialization/ASTWriter.h<span class="Apple-tab-span" style="white-space:pre"> </span>(working copy)</div><div>> @@ -76,6 +76,7 @@</div><div>>    typedef SmallVectorImpl<uint64_t> RecordDataImpl;</div>
<div>>  </div><div>>    friend class ASTDeclWriter;</div><div>> +  friend class ASTStmtWriter;</div><div>>  private:</div><div>>    /// \brief Map that provides the ID numbers of each type within the</div><div>
>    /// output stream, plus those deserialized from a chained PCH.</div><div>> Index: tools/libclang/CXCursor.cpp</div><div>> ===================================================================</div><div>> --- tools/libclang/CXCursor.cpp<span class="Apple-tab-span" style="white-space:pre">   </span>(revision 154056)</div>
<div>> +++ tools/libclang/CXCursor.cpp<span class="Apple-tab-span" style="white-space:pre">  </span>(working copy)</div><div>> @@ -247,19 +247,23 @@</div><div>>    case Stmt::CompoundStmtClass:</div><div>>      K = CXCursor_CompoundStmt;</div>
<div>>      break;</div><div>> -      </div><div>> +</div><div>>    case Stmt::NullStmtClass:</div><div>>      K = CXCursor_NullStmt;</div><div>>      break;</div><div>> -      </div><div>> +</div>
<div>>    case Stmt::LabelStmtClass:</div><div>>      K = CXCursor_LabelStmt;</div><div>>      break;</div><div>> -  </div><div>> +</div><div>> +  case Stmt::AttributedStmtClass:</div><div>> +    K = CXCursor_UnexposedStmt;</div>
<div>> +    break;</div><div>> +</div><div>>    case Stmt::DeclStmtClass:</div><div>>      K = CXCursor_DeclStmt;</div><div>>      break;</div><div>> - </div><div>> +</div><div>>    case Stmt::IntegerLiteralClass:</div>
<div>>      K = CXCursor_IntegerLiteral;</div><div>>      break;</div><div>> @@ -287,7 +291,7 @@</div><div>>    case Stmt::UnaryOperatorClass:</div><div>>      K = CXCursor_UnaryOperator;</div><div>>      break;</div>
<div>> -  </div><div>> +</div><div>>    case Stmt::CXXNoexceptExprClass:</div><div>>      K = CXCursor_UnaryExpr;</div><div>>      break;</div><div>> Index: lib/Analysis/CFG.cpp</div><div>> ===================================================================</div>
<div>> --- lib/Analysis/CFG.cpp<span class="Apple-tab-span" style="white-space:pre"> </span>(revision 154056)</div><div>> +++ lib/Analysis/CFG.cpp<span class="Apple-tab-span" style="white-space:pre">       </span>(working copy)</div>
<div>> @@ -18,6 +18,7 @@</div><div>>  #include "clang/AST/StmtVisitor.h"</div><div>>  #include "clang/AST/PrettyPrinter.h"</div><div>>  #include "clang/AST/CharUnits.h"</div><div>
> +#include "clang/Basic/AttrKinds.h"</div><div>>  #include "llvm/Support/GraphWriter.h"</div><div>>  #include "llvm/Support/Allocator.h"</div><div>>  #include "llvm/Support/Format.h"</div>
<div>> @@ -342,6 +343,7 @@</div><div>>    CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);</div><div>>    CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);</div><div>>    CFGBlock *VisitLabelStmt(LabelStmt *L);</div>
<div>> +  CFGBlock *VisitAttributedStmt(AttributedStmt *L);</div><div>>    CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);</div><div>>    CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);</div><div>
>    CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);</div><div>> @@ -1064,6 +1066,9 @@</div><div>>      case Stmt::LabelStmtClass:</div><div>>        return VisitLabelStmt(cast<LabelStmt>(S));</div>
<div>>  </div><div>> +    case Stmt::AttributedStmtClass:</div><div>> +      return VisitAttributedStmt(cast<AttributedStmt>(S));</div><div><br></div><div>Can you replace these changes with:</div><div>         return Visit(cast<AttributedStmt>(S)->getSubStmt(), ast);</div>
<div>? (That is, make AttributedStmt invisible to CFG building.)</div><div><br></div><div>> +</div><div>>      case Stmt::MemberExprClass:</div><div>>        return VisitMemberExpr(cast<MemberExpr>(S), asc);</div>
<div>>  </div><div>> @@ -1126,7 +1131,7 @@</div><div>>  </div><div>>  /// VisitChildren - Visit the children of a Stmt.</div><div>>  CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) {</div><div>> -  CFGBlock *lastBlock = Block;  </div>
<div>> +  CFGBlock *lastBlock = Block;</div><div>>    for (Stmt::child_range I = Terminator->children(); I; ++I)</div><div>>      if (Stmt *child = *I)</div><div>>        if (CFGBlock *b = Visit(child))</div>
<div>> @@ -1716,6 +1721,29 @@</div><div>>    return LabelBlock;</div><div>>  }</div><div>>  </div><div>> +CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *L) {</div><div>> +  // Get the block of the labeled statement.  Add it to our map.</div>
<div>> +  addStmt(L->getSubStmt());</div><div>> +  CFGBlock *InnerBlock = Block;</div><div>> +</div><div>> +  if (!InnerBlock)              // This can happen when the body is empty, i.e.</div><div>> +    InnerBlock = createBlock(); // scopes that only contains NullStmts.</div>
<div>> +</div><div>> +  // we could add AttributedStmt to CFGBlock as a label or as an element</div><div>> +  // currently we don't do this as it is not necessary</div><div>> +  // InnerBlock->setLabel(L);</div>
<div>> +  if (badCFG)</div><div>> +    return 0;</div><div>> +</div><div>> +  // We set Block to NULL to allow lazy creation of a new block (if necessary);</div><div>> +  Block = NULL;</div><div>> +</div>
<div>> +  // This block is now the implicit successor of other blocks.</div><div>> +  Succ = InnerBlock;</div><div>> +</div><div>> +  return InnerBlock;</div><div>> +}</div><div>> +</div><div>>  CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {</div>
<div>>    // Goto is a control-flow statement.  Thus we stop processing the current</div><div>>    // block and create a new one.</div><div>> Index: lib/Sema/TreeTransform.h</div><div>> ===================================================================</div>
<div>> --- lib/Sema/TreeTransform.h<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 154056)</div><div>> +++ lib/Sema/TreeTransform.h<span class="Apple-tab-span" style="white-space:pre">   </span>(working copy)</div>
<div>> @@ -1044,6 +1044,15 @@</div><div>>      return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);</div><div>>    }</div><div>>  </div><div>> +  /// \brief Build a new label statement.</div><div>
> +  ///</div><div>> +  /// By default, performs semantic analysis to build the new statement.</div><div>> +  /// Subclasses may override this routine to provide different behavior.</div><div>> +  StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,</div>
<div>> +                              Stmt *SubStmt) {</div><div>> +    return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);</div><div>> +  }</div><div>> +</div><div>>    /// \brief Build a new "if" statement.</div>
<div>>    ///</div><div>>    /// By default, performs semantic analysis to build the new statement.</div><div>> @@ -5154,8 +5163,8 @@</div><div>>                                          S->getDecl());</div>
<div>>    if (!LD)</div><div>>      return StmtError();</div><div>> -  </div><div>> -  </div><div>> +</div><div>> +</div><div>>    // FIXME: Pass the real colon location in.</div><div>>    return getDerived().RebuildLabelStmt(S->getIdentLoc(),</div>
<div>>                                         cast<LabelDecl>(LD), SourceLocation(),</div><div>> @@ -5164,6 +5173,22 @@</div><div>>  </div><div>>  template<typename Derived></div><div>>  StmtResult</div>
<div>> +TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {</div><div>> +  StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());</div><div>> +  if (SubStmt.isInvalid())</div>
<div>> +    return StmtError();</div><div>> +</div><div>> +  // !!! TODO: transform attributes?</div><div><br></div><div>We'll need to do this eventually (but it need not be done in the initial commit</div><div>
for statement attributes).</div><div><br></div><div>> +  if (SubStmt.get() == S->getSubStmt() /* && attrs are the same */)</div><div>> +    return S;</div><div>> +</div><div>> +  return getDerived().RebuildAttributedStmt(S->getAttrLoc(),</div>
<div>> +                                            S->getAttrs(), // SourceLocation(),</div><div><br></div><div>Remove the commented-out code here.</div><div><br></div><div>> +                                            SubStmt.get());</div>
<div>> +}</div><div>> +</div><div>> +template<typename Derived></div><div>> +StmtResult</div><div>>  TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {</div><div>>    // Transform the condition</div>
<div>>    ExprResult Cond;</div><div>> Index: lib/Sema/SemaStmtAttr.cpp</div><div>> ===================================================================</div><div>> --- lib/Sema/SemaStmtAttr.cpp<span class="Apple-tab-span" style="white-space:pre">  </span>(revision 0)</div>
<div>> +++ lib/Sema/SemaStmtAttr.cpp<span class="Apple-tab-span" style="white-space:pre">    </span>(revision 0)</div><div>> @@ -0,0 +1,44 @@</div><div>> +//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//</div>
<div>> +//</div><div>> +//                     The LLVM Compiler Infrastructure</div><div>> +//</div><div>> +// This file is distributed under the University of Illinois Open Source</div><div>> +// License. See LICENSE.TXT for details.</div>
<div>> +//</div><div>> +//===----------------------------------------------------------------------===//</div><div>> +//</div><div>> +//  This file implements stmt-related attribute processing.</div><div>> +//</div>
<div>> +//===----------------------------------------------------------------------===//</div><div>> +</div><div>> +#include "clang/Sema/SemaInternal.h"</div><div>> +#include "TargetAttributesSema.h"</div>
<div>> +#include "clang/AST/ASTContext.h"</div><div>> +#include "clang/Basic/SourceManager.h"</div><div>> +#include "clang/Sema/DelayedDiagnostic.h"</div><div>> +#include "clang/Sema/Lookup.h"</div>
<div>> +#include "llvm/ADT/StringExtras.h"</div><div>> +using namespace clang;</div><div>> +using namespace sema;</div><div>> +</div><div>> +</div><div>> +static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A) {</div>
<div>> +  switch (A.getKind()) {</div><div>> +    default:</div><div><br></div><div>case/default labels in switches are usually not indented in clang.</div><div><br></div><div>> +      return 0;</div><div><br></div>
<div>You should issue a diag::warn_unknown_attribute_ignored diagnostic in this case</div><div>for a GNU attribute, and an error for a C++11 attribute.</div><div><br></div><div>> +  }</div><div>> +}</div><div>> +</div>
<div>> +StmtResult Sema::ProcessStmtAttributes(StmtResult S, AttributeList *AttrList,</div><div>> +                                  SourceRange Range) {</div><div><br></div><div>Please line up this parameter declaration.</div>
<div><br></div><div>> +  AttrVec Attrs;</div><div>> +  for (const AttributeList* l = AttrList; l; l = l->getNext()) {</div><div>> +    if (Attr *a = ProcessStmtAttribute(*this, S.get(), *l))</div><div>> +      Attrs.push_back(a);</div>
<div>> +  }</div><div>> +</div><div>> +  if (Attrs.empty())</div><div>> +    return S;</div><div>> +</div><div>> +  return ActOnAttributedStmt(Range.getBegin(), Attrs, S.get());</div><div>> +}</div><div>
> Index: lib/Sema/CMakeLists.txt</div><div>> ===================================================================</div><div>> --- lib/Sema/CMakeLists.txt<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 154056)</div>
<div>> +++ lib/Sema/CMakeLists.txt<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div><div>> @@ -40,6 +40,7 @@</div><div>>    SemaOverload.cpp</div><div>>    SemaPseudoObject.cpp</div>
<div>>    SemaStmt.cpp</div><div>> +  SemaStmtAttr.cpp</div><div>>    SemaTemplate.cpp</div><div>>    SemaTemplateDeduction.cpp</div><div>>    SemaTemplateInstantiate.cpp</div><div>> Index: lib/Sema/SemaStmt.cpp</div>
<div>> ===================================================================</div><div>> --- lib/Sema/SemaStmt.cpp<span class="Apple-tab-span" style="white-space:pre"> </span>(revision 154056)</div><div>> +++ lib/Sema/SemaStmt.cpp<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div>
<div>> @@ -345,7 +345,6 @@</div><div>>  StmtResult</div><div>>  Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,</div><div>>                       SourceLocation ColonLoc, Stmt *SubStmt) {</div>
<div>> -  </div><div>>    // If the label was multiply defined, reject it now.</div><div>>    if (TheDecl->getStmt()) {</div><div>>      Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();</div>
<div>> @@ -362,6 +361,15 @@</div><div>>  }</div><div>>  </div><div>>  StmtResult</div><div>> +Sema::ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs /* !!! TODO: replace with ArrayRef<Attr*> Attrs */,</div>
<div><br></div><div>Please remove the comment prior to checkin. Switching this over to ArrayRef can</div><div>wait until you start using a variable-length allocation for AttributedStmt (at</div><div>which point TreeTransform will need it).</div>
<div><br></div><div>> +                          Stmt *SubStmt) {</div><div>> +  // Fill in the declaration and return it. Variable length will require to</div><div>> +  // change this to AttributedStmt::Create(Context, ....);</div>
<div>> +  AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);</div><div>> +  return Owned(LS);</div><div>> +}</div><div>> +</div><div>> +StmtResult</div><div>>  Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,</div>
<div>>                    Stmt *thenStmt, SourceLocation ElseLoc,</div><div>>                    Stmt *elseStmt) {</div><div>> Index: lib/AST/Stmt.cpp</div><div>> ===================================================================</div>
<div>> --- lib/AST/Stmt.cpp<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 154056)</div><div>> +++ lib/AST/Stmt.cpp<span class="Apple-tab-span" style="white-space:pre">   </span>(working copy)</div>
<div>> @@ -106,6 +106,8 @@</div><div>>        S = LS->getSubStmt();</div><div>>      else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))</div><div>>        S = SC->getSubStmt();</div><div>> +    else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S))</div>
<div>> +      S = AS->getSubStmt();</div><div><br></div><div>Please update the doxygen comment for this function.</div><div><br></div><div>>      else</div><div>>        return S;</div><div>>    }</div><div>
> Index: lib/AST/StmtPrinter.cpp</div><div>> ===================================================================</div><div>> --- lib/AST/StmtPrinter.cpp<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 154056)</div>
<div>> +++ lib/AST/StmtPrinter.cpp<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div><div>> @@ -169,6 +169,23 @@</div><div>>    PrintStmt(Node->getSubStmt(), 0);</div><div>>  }</div>
<div>>  </div><div>> +void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {</div><div>> +  OS << "[[";</div><div>> +  bool first = true;</div><div>> +  for (AttrVec::const_iterator it = Node->getAttrs().begin(),</div>
<div>> +                               end = Node->getAttrs().end();</div><div>> +                               it != end; ++it) {</div><div>> +    if (!first) {</div><div>> +      OS << ", ";</div>
<div>> +      first = false;</div><div>> +    }</div><div>> +    // !!! TODO: check this</div><div>> +    (*it)->printPretty(OS, Context);</div><div>> +  }</div><div>> +  OS << "]] ";</div>
<div>> +  PrintStmt(Node->getSubStmt(), 0);</div><div>> +}</div><div>> +</div><div>>  void StmtPrinter::PrintRawIfStmt(IfStmt *If) {</div><div>>    OS << "if (";</div><div>>    PrintExpr(If->getCond());</div>
<div>> Index: lib/AST/StmtProfile.cpp</div><div>> ===================================================================</div><div>> --- lib/AST/StmtProfile.cpp<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 154056)</div>
<div>> +++ lib/AST/StmtProfile.cpp<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div><div>> @@ -109,6 +109,11 @@</div><div>>    VisitDecl(S->getDecl());</div><div>>  }</div><div>
>  </div><div>> +void StmtProfiler::VisitAttributedStmt(const AttributedStmt *S) {</div><div>> +  VisitStmt(S);</div><div>> +  // !!!! TODO: maybe visit attributes?</div><div><br></div><div>Hmm, tricky. So long as we don't have any statement attributes which affect</div>
<div>the semantics of the program, I think this should be OK. Eventually, we should</div><div>probably generate profiling code for attributes.</div><div><br></div><div>> +}</div><div>> +</div><div>>  void StmtProfiler::VisitIfStmt(const IfStmt *S) {</div>
<div>>    VisitStmt(S);</div><div>>    VisitDecl(S->getConditionVariable());</div><div>> Index: lib/StaticAnalyzer/Core/ExprEngine.cpp</div><div>> ===================================================================</div>
<div>> --- lib/StaticAnalyzer/Core/ExprEngine.cpp<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 154056)</div><div>> +++ lib/StaticAnalyzer/Core/ExprEngine.cpp<span class="Apple-tab-span" style="white-space:pre">     </span>(working copy)</div>
<div>> @@ -536,6 +536,7 @@</div><div>>      case Stmt::IfStmtClass:</div><div>>      case Stmt::IndirectGotoStmtClass:</div><div>>      case Stmt::LabelStmtClass:</div><div>> +    case Stmt::AttributedStmtClass:</div>
<div>>      case Stmt::NoStmtClass:</div><div>>      case Stmt::NullStmtClass:</div><div>>      case Stmt::SwitchStmtClass:</div><div>> Index: lib/CodeGen/CGStmt.cpp</div><div>> ===================================================================</div>
<div>> --- lib/CodeGen/CGStmt.cpp<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 154056)</div><div>> +++ lib/CodeGen/CGStmt.cpp<span class="Apple-tab-span" style="white-space:pre">     </span>(working copy)</div>
<div>> @@ -79,6 +79,7 @@</div><div>>    case Stmt::CompoundStmtClass:</div><div>>    case Stmt::DeclStmtClass:</div><div>>    case Stmt::LabelStmtClass:</div><div>> +  case Stmt::AttributedStmtClass:</div><div>
>    case Stmt::GotoStmtClass:</div><div>>    case Stmt::BreakStmtClass:</div><div>>    case Stmt::ContinueStmtClass:</div><div>> @@ -173,6 +174,8 @@</div><div>>    case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;</div>
<div>>    case Stmt::DeclStmtClass:     EmitDeclStmt(cast<DeclStmt>(*S));         break;</div><div>>    case Stmt::LabelStmtClass:    EmitLabelStmt(cast<LabelStmt>(*S));       break;</div><div>> +  case Stmt::AttributedStmtClass:</div>
<div>> +                            EmitAttributedStmt(cast<AttributedStmt>(*S)); break;</div><div>>    case Stmt::GotoStmtClass:     EmitGotoStmt(cast<GotoStmt>(*S));         break;</div><div>>    case Stmt::BreakStmtClass:    EmitBreakStmt(cast<BreakStmt>(*S));       break;</div>
<div>>    case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;</div><div>> @@ -332,6 +335,10 @@</div><div>>    EmitStmt(S.getSubStmt());</div><div>>  }</div><div>>  </div><div>
> +void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {</div><div>> +  EmitStmt(S.getSubStmt());</div><div>> +}</div><div>> +</div><div>>  void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {</div>
<div>>    // If this code is reachable then emit a stop point (if generating</div><div>>    // debug info). We have to do this ourselves because we are on the</div><div>> Index: lib/CodeGen/CodeGenFunction.h</div>
<div>> ===================================================================</div><div>> --- lib/CodeGen/CodeGenFunction.h<span class="Apple-tab-span" style="white-space:pre"> </span>(revision 154056)</div><div>> +++ lib/CodeGen/CodeGenFunction.h<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div>
<div>> @@ -1948,6 +1948,7 @@</div><div>>    void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt.</div><div>>  </div><div>>    void EmitLabelStmt(const LabelStmt &S);</div><div>> +  void EmitAttributedStmt(const AttributedStmt &S);</div>
<div>>    void EmitGotoStmt(const GotoStmt &S);</div><div>>    void EmitIndirectGotoStmt(const IndirectGotoStmt &S);</div><div>>    void EmitIfStmt(const IfStmt &S);</div><div>> Index: lib/Parse/ParseExpr.cpp</div>
<div>> ===================================================================</div><div>> --- lib/Parse/ParseExpr.cpp<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 154056)</div><div>> +++ lib/Parse/ParseExpr.cpp<span class="Apple-tab-span" style="white-space:pre">    </span>(working copy)</div>
<div>> @@ -1918,11 +1918,9 @@</div><div>>    // unless they've already reported an error.</div><div>>    if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {</div><div>>      Diag(Tok, diag::ext_gnu_statement_expr);</div>
<div>> -</div><div>>      Actions.ActOnStartStmtExpr();</div><div>>  </div><div>> -    ParsedAttributes attrs(AttrFactory);</div><div>> -    StmtResult Stmt(ParseCompoundStatement(attrs, true));</div><div>> +    StmtResult Stmt(ParseCompoundStatement(true));</div>
<div>>      ExprType = CompoundStmt;</div><div>>  </div><div>>      // If the substmt parsed correctly, build the AST node.</div><div>> Index: lib/Parse/ParseStmt.cpp</div><div>> ===================================================================</div>
<div>> --- lib/Parse/ParseStmt.cpp<span class="Apple-tab-span" style="white-space:pre">      </span>(revision 154056)</div><div>> +++ lib/Parse/ParseStmt.cpp<span class="Apple-tab-span" style="white-space:pre">    </span>(working copy)</div>
<div>> @@ -78,14 +78,28 @@</div><div>>  StmtResult</div><div>>  Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,</div><div>>                                      SourceLocation *TrailingElseLoc) {</div>
<div>> -  const char *SemiError = 0;</div><div>> -  StmtResult Res;</div><div>>  </div><div>>    ParenBraceBracketBalancer BalancerRAIIObj(*this);</div><div>>  </div><div>> -  ParsedAttributesWithRange attrs(AttrFactory);</div>
<div>> -  MaybeParseCXX0XAttributes(attrs);</div><div>> +  ParsedAttributesWithRange Attrs(AttrFactory);</div><div>> +  MaybeParseCXX0XAttributes(Attrs);</div><div>>  </div><div>> +  StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,</div>
<div>> +                                 OnlyStatement, TrailingElseLoc, Attrs);</div><div>> +</div><div>> +  if (Attrs.empty() || Res.isInvalid() || !Res.isUsable())</div><div><br></div><div>Res.isInvalid() is covered by !Res.isUsable(); you don't need both.</div>
<div><br></div><div>If Res is null but valid, and we have attributes, then something has gone</div><div>wrong somewhere. Can you add an assert for that case? (But see below...)</div><div><br></div><div>> +    return Res;</div>
<div>> +</div><div>> +  return Actions.ProcessStmtAttributes(Res, Attrs.getList(), Attrs.Range);</div><div>> +}</div><div>> +</div><div>> +StmtResult</div><div>> +Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,</div>
<div>> +          bool OnlyStatement, SourceLocation *TrailingElseLoc,</div><div>> +          ParsedAttributesWithRange &Attrs) {</div><div>> +  const char *SemiError = 0;</div><div>> +  StmtResult Res;</div>
<div>> +</div><div>>    // Cases in this switch statement should fall through if the parser expects</div><div>>    // the token to end in a semicolon (in which case SemiError should be set),</div><div>>    // or they directly 'return;' if not.</div>
<div>> @@ -95,6 +109,7 @@</div><div>>    switch (Kind) {</div><div>>    case tok::at: // May be a @try or @throw statement</div><div>>      {</div><div>> +      ProhibitAttributes(Attrs); // TODO: is it correct?</div>
<div>>        AtLoc = ConsumeToken();  // consume @</div><div>>        return ParseObjCAtStatement(AtLoc);</div><div>>      }</div><div>> @@ -108,7 +123,7 @@</div><div>>      Token Next = NextToken();</div>
<div>>      if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement</div><div>>        // identifier ':' statement</div><div>> -      return ParseLabeledStatement(attrs);</div><div>> +      return ParseLabeledStatement(Attrs);</div>
<div><br></div><div>We should be clearing Attrs somewhere (either here or in ParseLabeledStatement)</div><div>so we don't attach them to both the label declaration and the label statement.</div><div><br></div><div>I would prefer to see them cleared in ParseLabeledStatement, since that's where</div>
<div>they're consumed.</div><div><br></div><div>>      }</div><div>>  </div><div>>      if (Next.isNot(tok::coloncolon)) {</div><div>> @@ -208,9 +223,10 @@</div><div>>  </div><div>>    default: {</div>
<div>>      if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {</div><div>> +      ProhibitAttributes(Attrs);</div><div>>        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;</div>
<div>>        DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext,</div><div>> -                                             DeclEnd, attrs);</div><div>> +                                             DeclEnd, Attrs);</div>
<div><br></div><div>Likewise here, we don't want to attach the attributes to both the declarations</div><div>and the declaration statement.</div><div><br></div><div>>        return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);</div>
<div>>      }</div><div>>  </div><div>> @@ -219,54 +235,54 @@</div><div>>        return StmtError();</div><div>>      }</div><div>>  </div><div>> -    return ParseExprStatement(attrs);</div><div>> +    return ParseExprStatement();</div>
<div>>    }</div><div>>  </div><div>>    case tok::kw_case:                // C99 6.8.1: labeled-statement</div><div>> -    return ParseCaseStatement(attrs);</div><div>> +    return ParseCaseStatement();</div>
<div>>    case tok::kw_default:             // C99 6.8.1: labeled-statement</div><div>> -    return ParseDefaultStatement(attrs);</div><div>> +    return ParseDefaultStatement();</div><div>>  </div><div>>    case tok::l_brace:                // C99 6.8.2: compound-statement</div>
<div>> -    return ParseCompoundStatement(attrs);</div><div>> +    return ParseCompoundStatement();</div><div>>    case tok::semi: {                 // C99 6.8.3p3: expression[opt] ';'</div><div>>      bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();</div>
<div>>      return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);</div><div>>    }</div><div>>  </div><div>>    case tok::kw_if:                  // C99 <a href="http://6.8.4.1">6.8.4.1</a>: if-statement</div>
<div>> -    return ParseIfStatement(attrs, TrailingElseLoc);</div><div>> +    return ParseIfStatement(TrailingElseLoc);</div><div>>    case tok::kw_switch:              // C99 <a href="http://6.8.4.2">6.8.4.2</a>: switch-statement</div>
<div>> -    return ParseSwitchStatement(attrs, TrailingElseLoc);</div><div>> +    return ParseSwitchStatement(TrailingElseLoc);</div><div>>  </div><div>>    case tok::kw_while:               // C99 <a href="http://6.8.5.1">6.8.5.1</a>: while-statement</div>
<div>> -    return ParseWhileStatement(attrs, TrailingElseLoc);</div><div>> +    return ParseWhileStatement(TrailingElseLoc);</div><div>>    case tok::kw_do:                  // C99 <a href="http://6.8.5.2">6.8.5.2</a>: do-statement</div>
<div>> -    Res = ParseDoStatement(attrs);</div><div>> +    Res = ParseDoStatement();</div><div>>      SemiError = "do/while";</div><div>>      break;</div><div>>    case tok::kw_for:                 // C99 <a href="http://6.8.5.3">6.8.5.3</a>: for-statement</div>
<div>> -    return ParseForStatement(attrs, TrailingElseLoc);</div><div>> +    return ParseForStatement(TrailingElseLoc);</div><div>>  </div><div>>    case tok::kw_goto:                // C99 <a href="http://6.8.6.1">6.8.6.1</a>: goto-statement</div>
<div>> -    Res = ParseGotoStatement(attrs);</div><div>> +    Res = ParseGotoStatement();</div><div>>      SemiError = "goto";</div><div>>      break;</div><div>>    case tok::kw_continue:            // C99 <a href="http://6.8.6.2">6.8.6.2</a>: continue-statement</div>
<div>> -    Res = ParseContinueStatement(attrs);</div><div>> +    Res = ParseContinueStatement();</div><div>>      SemiError = "continue";</div><div>>      break;</div><div>>    case tok::kw_break:               // C99 <a href="http://6.8.6.3">6.8.6.3</a>: break-statement</div>
<div>> -    Res = ParseBreakStatement(attrs);</div><div>> +    Res = ParseBreakStatement();</div><div>>      SemiError = "break";</div><div>>      break;</div><div>>    case tok::kw_return:              // C99 <a href="http://6.8.6.4">6.8.6.4</a>: return-statement</div>
<div>> -    Res = ParseReturnStatement(attrs);</div><div>> +    Res = ParseReturnStatement();</div><div>>      SemiError = "return";</div><div>>      break;</div><div>>  </div><div>>    case tok::kw_asm: {</div>
<div>> -    ProhibitAttributes(attrs);</div><div>> +    ProhibitAttributes(Attrs);</div><div>>      bool msAsm = false;</div><div>>      Res = ParseAsmStatement(msAsm);</div><div>>      Res = Actions.ActOnFinishFullStmt(Res.get());</div>
<div>> @@ -276,16 +292,19 @@</div><div>>    }</div><div>>  </div><div>>    case tok::kw_try:                 // C++ 15: try-block</div><div>> -    return ParseCXXTryBlock(attrs);</div><div>> +    return ParseCXXTryBlock();</div>
<div>>  </div><div>>    case tok::kw___try:</div><div>> -    return ParseSEHTryBlock(attrs);</div><div>> +    ProhibitAttributes(Attrs); // TODO: is it correct?</div><div>> +    return ParseSEHTryBlock();</div>
<div>>  </div><div>>    case tok::annot_pragma_vis:</div><div>> +    ProhibitAttributes(Attrs); // TODO: is it correct?</div><div>>      HandlePragmaVisibility();</div><div>>      return StmtEmpty();</div><div>
>  </div><div>>    case tok::annot_pragma_pack:</div><div>> +    ProhibitAttributes(Attrs); // TODO: is it correct?</div><div><br></div><div>These last two, at least, are correct to prohibit attributes. But they should</div>
<div>also be clearing Attrs, since we can't build an AttributedStmt for these</div><div>annotations.</div><div><br></div><div>>      HandlePragmaPack();</div><div>>      return StmtEmpty();</div><div>>    }</div>
<div>> @@ -306,11 +325,10 @@</div><div>>  }</div><div>>  </div><div>>  /// \brief Parse an expression statement.</div><div>> -StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {</div><div>> +StmtResult Parser::ParseExprStatement() {</div>
<div>>    // If a case keyword is missing, this is where it should be inserted.</div><div>>    Token OldToken = Tok;</div><div>>  </div><div>> -  // FIXME: Use the attributes</div><div>>    // expression[opt] ';'</div>
<div>>    ExprResult Expr(ParseExpression());</div><div>>    if (Expr.isInvalid()) {</div><div>> @@ -331,7 +349,7 @@</div><div>>        << FixItHint::CreateInsertion(OldToken.getLocation(), "case ");</div>
<div>>  </div><div>>      // Recover parsing as a case statement.</div><div>> -    return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr);</div><div>> +    return ParseCaseStatement(/*MissingCase=*/true, Expr);</div>
<div>>    }</div><div>>  </div><div>>    // Otherwise, eat the semicolon.</div><div>> @@ -339,7 +357,7 @@</div><div>>    return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get()));</div><div>>  }</div>
<div>>  </div><div>> -StmtResult Parser::ParseSEHTryBlock(ParsedAttributes & Attrs) {</div><div>> +StmtResult Parser::ParseSEHTryBlock() {</div><div>>    assert(Tok.is(tok::kw___try) && "Expected '__try'");</div>
<div>>    SourceLocation Loc = ConsumeToken();</div><div>>    return ParseSEHTryBlockCommon(Loc);</div><div>> @@ -358,13 +376,12 @@</div><div>>    if(Tok.isNot(tok::l_brace))</div><div>>      return StmtError(Diag(Tok,diag::err_expected_lbrace));</div>
<div>>  </div><div>> -  ParsedAttributesWithRange attrs(AttrFactory);</div><div>> -  StmtResult TryBlock(ParseCompoundStatement(attrs));</div><div>> +  StmtResult TryBlock(ParseCompoundStatement());</div><div>
>    if(TryBlock.isInvalid())</div><div>>      return move(TryBlock);</div><div>>  </div><div>>    StmtResult Handler;</div><div>> -  if (Tok.is(tok::identifier) && </div><div>> +  if (Tok.is(tok::identifier) &&</div>
<div>>        Tok.getIdentifierInfo() == getSEHExceptKeyword()) {</div><div>>      SourceLocation Loc = ConsumeToken();</div><div>>      Handler = ParseSEHExceptBlock(Loc);</div><div>> @@ -418,8 +435,7 @@</div>
<div>>    if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen))</div><div>>      return StmtError();</div><div>>  </div><div>> -  ParsedAttributesWithRange attrs(AttrFactory);</div><div>> -  StmtResult Block(ParseCompoundStatement(attrs));</div>
<div>> +  StmtResult Block(ParseCompoundStatement());</div><div>>  </div><div>>    if(Block.isInvalid())</div><div>>      return move(Block);</div><div>> @@ -437,8 +453,7 @@</div><div>>      raii2(Ident___abnormal_termination, false),</div>
<div>>      raii3(Ident_AbnormalTermination, false);</div><div>>  </div><div>> -  ParsedAttributesWithRange attrs(AttrFactory);</div><div>> -  StmtResult Block(ParseCompoundStatement(attrs));</div><div>> +  StmtResult Block(ParseCompoundStatement());</div>
<div>>    if(Block.isInvalid())</div><div>>      return move(Block);</div><div>>  </div><div>> @@ -486,10 +501,8 @@</div><div>>  ///         'case' constant-expression ':' statement</div><div>
>  /// [GNU]   'case' constant-expression '...' constant-expression ':' statement</div><div>>  ///</div><div>> -StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase,</div>
<div>> -                                      ExprResult Expr) {</div><div>> +StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {</div><div>>    assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");</div>
<div>> -  // FIXME: Use attributes?</div><div>>  </div><div>>    // It is very very common for code to contain many case statements recursively</div><div>>    // nested, as in (but usually without indentation):</div>
<div>> @@ -625,9 +638,7 @@</div><div>>  ///         'default' ':' statement</div><div>>  /// Note that this does not parse the 'statement' at the end.</div><div>>  ///</div><div>> -StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {</div>
<div>> -  //FIXME: Use attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseDefaultStatement() {</div><div>>    assert(Tok.is(tok::kw_default) && "Not a default stmt!");</div><div>>    SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.</div>
<div>>  </div><div>> @@ -668,9 +679,8 @@</div><div>>                                    SubStmt.get(), getCurScope());</div><div>>  }</div><div>>  </div><div>> -StmtResult Parser::ParseCompoundStatement(ParsedAttributes &Attr,</div>
<div>> -                                          bool isStmtExpr) {</div><div>> -  return ParseCompoundStatement(Attr, isStmtExpr, Scope::DeclScope);</div><div>> +StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {</div>
<div>> +  return ParseCompoundStatement(isStmtExpr, Scope::DeclScope);</div><div>>  }</div><div>>  </div><div>>  /// ParseCompoundStatement - Parse a "{}" block.</div><div>> @@ -700,11 +710,8 @@</div>
<div>>  /// [OMP]   barrier-directive</div><div>>  /// [OMP]   flush-directive</div><div>>  ///</div><div>> -StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs,</div><div>> -                                          bool isStmtExpr,</div>
<div>> +StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,</div><div>>                                            unsigned ScopeFlags) {</div><div>> -  //FIXME: Use attributes?</div><div>> -</div><div>
>    assert(Tok.is(tok::l_brace) && "Not a compount stmt!");</div><div>>  </div><div>>    // Enter a scope to hold everything within the compound stmt.  Compound</div><div>> @@ -894,10 +901,7 @@</div>
<div>>  /// [C++]   'if' '(' condition ')' statement</div><div>>  /// [C++]   'if' '(' condition ')' statement 'else' statement</div><div>>  ///</div><div>> -StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs,</div>
<div>> -                                    SourceLocation *TrailingElseLoc) {</div><div>> -  // FIXME: Use attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {</div>
<div>>    assert(Tok.is(tok::kw_if) && "Not an if stmt!");</div><div>>    SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.</div><div>>  </div><div>> @@ -1028,10 +1032,7 @@</div>
<div>>  ///       switch-statement:</div><div>>  ///         'switch' '(' expression ')' statement</div><div>>  /// [C++]   'switch' '(' condition ')' statement</div>
<div>> -StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs,</div><div>> -                                        SourceLocation *TrailingElseLoc) {</div><div>> -  // FIXME: Use attributes?</div><div>
> -</div><div>> +StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {</div><div>>    assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");</div><div>>    SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.</div>
<div>>  </div><div>> @@ -1119,10 +1120,7 @@</div><div>>  ///       while-statement: [C99 6.8.5.1]</div><div>>  ///         'while' '(' expression ')' statement</div><div>>  /// [C++]   'while' '(' condition ')' statement</div>
<div>> -StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs,</div><div>> -                                       SourceLocation *TrailingElseLoc) {</div><div>> -  // FIXME: Use attributes?</div><div>
> -</div><div>> +StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {</div><div>>    assert(Tok.is(tok::kw_while) && "Not a while stmt!");</div><div>>    SourceLocation WhileLoc = Tok.getLocation();</div>
<div>>    ConsumeToken();  // eat the 'while'.</div><div>> @@ -1194,9 +1192,7 @@</div><div>>  ///       do-statement: [C99 6.8.5.2]</div><div>>  ///         'do' statement 'while' '(' expression ')' ';'</div>
<div>>  /// Note: this lets the caller parse the end ';'.</div><div>> -StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {</div><div>> -  // FIXME: Use attributes?</div><div>> -</div><div>
> +StmtResult Parser::ParseDoStatement() {</div><div>>    assert(Tok.is(tok::kw_do) && "Not a do stmt!");</div><div>>    SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.</div><div>
>  </div><div>> @@ -1277,10 +1273,7 @@</div><div>>  /// [C++0x] for-range-initializer:</div><div>>  /// [C++0x]   expression</div><div>>  /// [C++0x]   braced-init-list            [TODO]</div><div>> -StmtResult Parser::ParseForStatement(ParsedAttributes &attrs,</div>
<div>> -                                     SourceLocation *TrailingElseLoc) {</div><div>> -  // FIXME: Use attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {</div>
<div>>    assert(Tok.is(tok::kw_for) && "Not a for stmt!");</div><div>>    SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.</div><div>>  </div><div>> @@ -1535,9 +1528,7 @@</div>
<div>>  ///</div><div>>  /// Note: this lets the caller parse the end ';'.</div><div>>  ///</div><div>> -StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {</div><div>> -  // FIXME: Use attributes?</div>
<div>> -</div><div>> +StmtResult Parser::ParseGotoStatement() {</div><div>>    assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");</div><div>>    SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.</div>
<div>>  </div><div>> @@ -1571,9 +1562,7 @@</div><div>>  ///</div><div>>  /// Note: this lets the caller parse the end ';'.</div><div>>  ///</div><div>> -StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {</div>
<div>> -  // FIXME: Use attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseContinueStatement() {</div><div>>    SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.</div><div>
>    return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());</div><div>>  }</div><div>> @@ -1584,9 +1573,7 @@</div><div>>  ///</div><div>>  /// Note: this lets the caller parse the end ';'.</div>
<div>>  ///</div><div>> -StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {</div><div>> -  // FIXME: Use attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseBreakStatement() {</div>
<div>>    SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.</div><div>>    return Actions.ActOnBreakStmt(BreakLoc, getCurScope());</div><div>>  }</div><div>> @@ -1594,9 +1581,7 @@</div><div>
>  /// ParseReturnStatement</div><div>>  ///       jump-statement:</div><div>>  ///         'return' expression[opt] ';'</div><div>> -StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) {</div>
<div>> -  // FIXME: Use attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseReturnStatement() {</div><div>>    assert(Tok.is(tok::kw_return) && "Not a return stmt!");</div><div>>    SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.</div>
<div>>  </div><div>> @@ -2047,9 +2032,7 @@</div><div>>  ///       try-block:</div><div>>  ///         'try' compound-statement handler-seq</div><div>>  ///</div><div>> -StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) {</div>
<div>> -  // FIXME: Add attributes?</div><div>> -</div><div>> +StmtResult Parser::ParseCXXTryBlock() {</div><div>>    assert(Tok.is(tok::kw_try) && "Expected 'try'");</div><div>>  </div>
<div>>    SourceLocation TryLoc = ConsumeToken();</div><div>> @@ -2075,17 +2058,16 @@</div><div>>  StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {</div><div>>    if (Tok.isNot(tok::l_brace))</div>
<div>>      return StmtError(Diag(Tok, diag::err_expected_lbrace));</div><div>> -  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?</div><div><br></div><div>Please keep this comment: it's weird that we aren't allowed an</div>
<div>attribute-specifier on the compound-statement in a try block.</div><div><br></div><div>> -  ParsedAttributesWithRange attrs(AttrFactory);</div><div>> -  StmtResult TryBlock(ParseCompoundStatement(attrs, /*isStmtExpr=*/false,</div>
<div>> +</div><div>> +  StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,</div><div>>                                               Scope::DeclScope|Scope::TryScope));</div><div>>    if (TryBlock.isInvalid())</div>
<div>>      return move(TryBlock);</div><div>>  </div><div>>    // Borland allows SEH-handlers with 'try'</div><div>>    </div><div>> -  if((Tok.is(tok::identifier) && </div><div>> -      Tok.getIdentifierInfo() == getSEHExceptKeyword()) || </div>
<div>> +  if((Tok.is(tok::identifier) &&</div><div>> +      Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||</div><div>>       Tok.is(tok::kw___finally)) {</div><div>>      // TODO: Factor into common return ParseSEHHandlerCommon(...)</div>
<div>>      StmtResult Handler;</div><div>> @@ -2107,6 +2089,7 @@</div><div>>    }</div><div>>    else {</div><div>>      StmtVector Handlers(Actions);</div><div>> +    ParsedAttributesWithRange attrs(AttrFactory);</div>
<div>>      MaybeParseCXX0XAttributes(attrs);</div><div>>      ProhibitAttributes(attrs);</div><div>>  </div><div>> @@ -2171,9 +2154,7 @@</div><div>>    if (Tok.isNot(tok::l_brace))</div><div>>      return StmtError(Diag(Tok, diag::err_expected_lbrace));</div>
<div>>  </div><div>> -  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?</div><div><br></div><div>Please keep this comment too.</div><div><br></div><div>> -  ParsedAttributes attrs(AttrFactory);</div>
<div>> -  StmtResult Block(ParseCompoundStatement(attrs));</div><div>> +  StmtResult Block(ParseCompoundStatement());</div><div>>    if (Block.isInvalid())</div><div>>      return move(Block);</div><div>>  </div>
<div>> @@ -2192,24 +2173,23 @@</div><div>>    if (Result.Behavior == IEB_Dependent) {</div><div>>      if (!Tok.is(tok::l_brace)) {</div><div>>        Diag(Tok, diag::err_expected_lbrace);</div><div>> -      return;      </div>
<div>> +      return;</div><div>>      }</div><div>> -    </div><div>> -    ParsedAttributes Attrs(AttrFactory);</div><div>> -    StmtResult Compound = ParseCompoundStatement(Attrs);</div><div>> +</div><div>
> +    StmtResult Compound = ParseCompoundStatement();</div><div>>      if (Compound.isInvalid())</div><div>>        return;</div><div>> -    </div><div>> +</div><div>>      StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,</div>
<div>>                                                                Result.IsIfExists,</div><div>> -                                                              Result.SS, </div><div>> +                                                              Result.SS,</div>
<div>>                                                                Result.Name,</div><div>>                                                                Compound.get());</div><div>>      if (DepResult.isUsable())</div>
<div>>        Stmts.push_back(DepResult.get());</div><div>>      return;</div><div>>    }</div><div>> -  </div><div>> +</div><div>>    BalancedDelimiterTracker Braces(*this, tok::l_brace);</div><div>>    if (Braces.consumeOpen()) {</div>
<div>>      Diag(Tok, diag::err_expected_lbrace);</div><div>> Index: lib/Serialization/ASTReaderStmt.cpp</div><div>> ===================================================================</div><div>> --- lib/Serialization/ASTReaderStmt.cpp<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 154056)</div>
<div>> +++ lib/Serialization/ASTReaderStmt.cpp<span class="Apple-tab-span" style="white-space:pre">  </span>(working copy)</div><div>> @@ -159,9 +159,18 @@</div><div>>    S->setIdentLoc(ReadSourceLocation(Record, Idx));</div>
<div>>  }</div><div>>  </div><div>> +void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {</div><div>> +  VisitStmt(S);</div><div>> +  AttrVec Attrs;</div><div>> +  Reader.ReadAttributes(F, Attrs, Record, Idx);</div>
<div>> +  S->Attrs = Attrs;</div><div>> +  S->SubStmt = Reader.ReadSubStmt();</div><div>> +  S->AttrLoc = ReadSourceLocation(Record, Idx);</div><div>> +}</div><div>> +</div><div>>  void ASTStmtReader::VisitIfStmt(IfStmt *S) {</div>
<div>>    VisitStmt(S);</div><div>> -  S->setConditionVariable(Reader.getContext(), </div><div>> +  S->setConditionVariable(Reader.getContext(),</div><div>>                            ReadDeclAs<VarDecl>(Record, Idx));</div>
<div>>    S->setCond(Reader.ReadSubExpr());</div><div>>    S->setThen(Reader.ReadSubStmt());</div><div>> @@ -1639,6 +1648,10 @@</div><div>>        S = new (Context) LabelStmt(Empty);</div><div>>        break;</div>
<div>>  </div><div>> +    case STMT_ATTRIBUTED:</div><div>> +      S = new (Context) AttributedStmt(Empty);</div><div>> +      break;</div><div>> +</div><div>>      case STMT_IF:</div><div>>        S = new (Context) IfStmt(Empty);</div>
<div>>        break;</div><div>> Index: lib/Serialization/ASTWriter.cpp</div><div>> ===================================================================</div><div>> --- lib/Serialization/ASTWriter.cpp<span class="Apple-tab-span" style="white-space:pre">    </span>(revision 154056)</div>
<div>> +++ lib/Serialization/ASTWriter.cpp<span class="Apple-tab-span" style="white-space:pre">      </span>(working copy)</div><div>> @@ -651,6 +651,7 @@</div><div>>    RECORD(STMT_CASE);</div><div>>    RECORD(STMT_DEFAULT);</div>
<div>>    RECORD(STMT_LABEL);</div><div>> +  RECORD(STMT_ATTRIBUTED);</div><div>>    RECORD(STMT_IF);</div><div>>    RECORD(STMT_SWITCH);</div><div>>    RECORD(STMT_WHILE);</div><div>> Index: lib/Serialization/ASTWriterStmt.cpp</div>
<div>> ===================================================================</div><div>> --- lib/Serialization/ASTWriterStmt.cpp<span class="Apple-tab-span" style="white-space:pre">   </span>(revision 154056)</div><div>
> +++ lib/Serialization/ASTWriterStmt.cpp<span class="Apple-tab-span" style="white-space:pre">     </span>(working copy)</div><div>> @@ -106,6 +106,14 @@</div><div>>    Code = serialization::STMT_LABEL;</div><div>>  }</div>
<div>>  </div><div>> +void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) {</div><div>> +  VisitStmt(S);</div><div>> +  Writer.WriteAttributes(S->getAttrs(), Record);</div><div>> +  Writer.AddStmt(S->getSubStmt());</div>
<div>> +  Writer.AddSourceLocation(S->getAttrLoc(), Record);</div><div>> +  Code = serialization::STMT_ATTRIBUTED;</div><div>> +}</div><div>> +</div><div>>  void ASTStmtWriter::VisitIfStmt(IfStmt *S) {</div>
<div>>    VisitStmt(S);</div><div>>    Writer.AddDeclRef(S->getConditionVariable(), Record);</div>