[cfe-commits] r154723 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ lib/StaticAnalyzer/Core/ test/Parser/ tools/libclang/

Richard Smith richard-llvm at metafoo.co.uk
Fri Apr 13 17:33:13 PDT 2012


Author: rsmith
Date: Fri Apr 13 19:33:13 2012
New Revision: 154723

URL: http://llvm.org/viewvc/llvm-project?rev=154723&view=rev
Log:
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!

Added:
    cfe/trunk/lib/Sema/SemaStmtAttr.cpp
    cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Parser/objcxx11-attributes.mm
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Apr 13 19:33:13 2012
@@ -861,7 +861,6 @@
   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);

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Apr 13 19:33:13 2012
@@ -1870,6 +1870,7 @@
 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, { })

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri Apr 13 19:33:13 2012
@@ -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 @@
 };
 
 
+/// \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 {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Apr 13 19:33:13 2012
@@ -1563,6 +1563,9 @@
 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<

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Fri Apr 13 19:33:13 2012
@@ -12,6 +12,7 @@
 def NullStmt : Stmt;
 def CompoundStmt : Stmt;
 def LabelStmt : Stmt;
+def AttributedStmt : Stmt;
 def IfStmt : Stmt;
 def SwitchStmt : Stmt;
 def WhileStmt : Stmt;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Apr 13 19:33:13 2012
@@ -1517,42 +1517,40 @@
   //===--------------------------------------------------------------------===//
   // 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 @@
     /// \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 @@
   //===--------------------------------------------------------------------===//
   // 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 @@
   void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
     if (!attrs.Range.isValid()) return;
     DiagnoseProhibitedAttributes(attrs);
+    attrs.clear();
   }
   void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
 
@@ -1967,7 +1966,7 @@
 
   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);

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Apr 13 19:33:13 2012
@@ -1974,6 +1974,10 @@
   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 @@
   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,

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Apr 13 19:33:13 2012
@@ -964,6 +964,8 @@
       STMT_DEFAULT,
       /// \brief A LabelStmt record.
       STMT_LABEL,
+      /// \brief An AttributedStmt record.
+      STMT_ATTRIBUTED,
       /// \brief An IfStmt record.
       STMT_IF,
       /// \brief A SwitchStmt record.

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Fri Apr 13 19:33:13 2012
@@ -76,6 +76,7 @@
   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.

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Fri Apr 13 19:33:13 2012
@@ -97,8 +97,8 @@
 
 /// \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 @@
       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;
   }

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Apr 13 19:33:13 2012
@@ -169,6 +169,23 @@
   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());

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Apr 13 19:33:13 2012
@@ -109,6 +109,11 @@
   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());

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Fri Apr 13 19:33:13 2012
@@ -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 @@
     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 @@
 
 /// 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))

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Fri Apr 13 19:33:13 2012
@@ -79,6 +79,7 @@
   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 @@
   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 @@
   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

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Apr 13 19:33:13 2012
@@ -1948,6 +1948,7 @@
   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);

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Apr 13 19:33:13 2012
@@ -958,7 +958,7 @@
 /// [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,

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Apr 13 19:33:13 2012
@@ -1926,11 +1926,9 @@
   // 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.

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Fri Apr 13 19:33:13 2012
@@ -78,13 +78,30 @@
 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 @@
   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 @@
     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 @@
     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 @@
       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 @@
   }
 
   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 @@
 }
 
 /// \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 @@
       << 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 @@
   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 @@
   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 @@
   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 @@
     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 @@
 ///         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 @@
   // 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 @@
 
   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 @@
 ///         '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 @@
 ///         '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 @@
                                   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 @@
 /// [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 @@
 /// [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 @@
 ///       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 @@
 ///       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 @@
 ///       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 @@
 /// [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 @@
 ///
 /// 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 @@
 ///
 /// 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 @@
 ///
 /// 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 @@
 /// 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 @@
 ///       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 @@
   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 @@
   }
   else {
     StmtVector Handlers(Actions);
+    ParsedAttributesWithRange attrs(AttrFactory);
     MaybeParseCXX0XAttributes(attrs);
     ProhibitAttributes(attrs);
 
@@ -2168,8 +2157,7 @@
     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 @@
   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);

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Apr 13 19:33:13 2012
@@ -40,6 +40,7 @@
   SemaOverload.cpp
   SemaPseudoObject.cpp
   SemaStmt.cpp
+  SemaStmtAttr.cpp
   SemaTemplate.cpp
   SemaTemplateDeduction.cpp
   SemaTemplateInstantiate.cpp

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Apr 13 19:33:13 2012
@@ -345,7 +345,6 @@
 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 @@
   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,

Added: cfe/trunk/lib/Sema/SemaStmtAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=154723&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (added)
+++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Fri Apr 13 19:33:13 2012
@@ -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);
+}

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Apr 13 19:33:13 2012
@@ -1044,6 +1044,15 @@
     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,8 +5163,8 @@
                                         S->getDecl());
   if (!LD)
     return StmtError();
-  
-  
+
+
   // FIXME: Pass the real colon location in.
   return getDerived().RebuildLabelStmt(S->getIdentLoc(),
                                        cast<LabelDecl>(LD), SourceLocation(),
@@ -5164,6 +5173,22 @@
 
 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) {
   // Transform the condition
   ExprResult Cond;

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Apr 13 19:33:13 2012
@@ -159,9 +159,18 @@
   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 @@
       S = new (Context) LabelStmt(Empty);
       break;
 
+    case STMT_ATTRIBUTED:
+      S = new (Context) AttributedStmt(Empty);
+      break;
+
     case STMT_IF:
       S = new (Context) IfStmt(Empty);
       break;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Apr 13 19:33:13 2012
@@ -651,6 +651,7 @@
   RECORD(STMT_CASE);
   RECORD(STMT_DEFAULT);
   RECORD(STMT_LABEL);
+  RECORD(STMT_ATTRIBUTED);
   RECORD(STMT_IF);
   RECORD(STMT_SWITCH);
   RECORD(STMT_WHILE);

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Apr 13 19:33:13 2012
@@ -106,6 +106,14 @@
   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);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Apr 13 19:33:13 2012
@@ -536,6 +536,7 @@
     case Stmt::IfStmtClass:
     case Stmt::IndirectGotoStmtClass:
     case Stmt::LabelStmtClass:
+    case Stmt::AttributedStmtClass:
     case Stmt::NoStmtClass:
     case Stmt::NullStmtClass:
     case Stmt::SwitchStmtClass:

Added: cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp?rev=154723&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp (added)
+++ cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp Fri Apr 13 19:33:13 2012
@@ -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
+}

Modified: cfe/trunk/test/Parser/objcxx11-attributes.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-attributes.mm?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/test/Parser/objcxx11-attributes.mm (original)
+++ cfe/trunk/test/Parser/objcxx11-attributes.mm Fri Apr 13 19:33:13 2012
@@ -31,15 +31,17 @@
 
   // 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]);

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=154723&r1=154722&r2=154723&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Fri Apr 13 19:33:13 2012
@@ -247,19 +247,23 @@
   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 @@
   case Stmt::UnaryOperatorClass:
     K = CXCursor_UnaryOperator;
     break;
-  
+
   case Stmt::CXXNoexceptExprClass:
     K = CXCursor_UnaryExpr;
     break;





More information about the cfe-commits mailing list