[cfe-commits] r89543 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Parse/ lib/Sema/ test/Parser/ test/SemaCXX/

Sean Hunt rideau3 at gmail.com
Sat Nov 21 00:43:18 PST 2009


Author: coppro
Date: Sat Nov 21 02:43:09 2009
New Revision: 89543

URL: http://llvm.org/viewvc/llvm-project?rev=89543&view=rev
Log:
Added rudimentary C++0x attribute support.
The following attributes are currently supported in C++0x attribute
lists (and in GNU ones as well):
 - align() - semantics believed to be conformant to n3000, except for
   redeclarations and what entities it may apply to
 - final - semantics believed to be conformant to CWG issue 817's proposed
   wording, except for redeclarations
 - noreturn - semantics believed to be conformant to n3000, except for
   redeclarations
 - carries_dependency - currently ignored (this is an optimization hint)

Added:
    cfe/trunk/test/Parser/cxx0x-attributes.cpp
    cfe/trunk/test/SemaCXX/attr-cxx0x.cpp
Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/AttributeList.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Parse/AttributeList.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Sat Nov 21 02:43:09 2009
@@ -59,6 +59,7 @@
     Deprecated,
     Destructor,
     FastCall,
+    Final,
     Format,
     FormatArg,
     GNUInline,
@@ -184,12 +185,24 @@
 class AlignedAttr : public Attr {
   unsigned Alignment;
 public:
-  AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
+  AlignedAttr(unsigned alignment)
+    : Attr(Aligned), Alignment(alignment) {}
 
   /// getAlignment - The specified alignment in bits.
   unsigned getAlignment() const { return Alignment; }
+  
+  /// getMaxAlignment - Get the maximum alignment of attributes on this list.
+  unsigned getMaxAlignment() const {
+    const AlignedAttr *Next = getNext<AlignedAttr>();
+    if (Next)
+      return std::max(Next->getMaxAlignment(), Alignment);
+    else
+      return Alignment;
+  }
 
-  virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); }
+  virtual Attr* clone(ASTContext &C) const {
+    return ::new (C) AlignedAttr(Alignment);
+  }
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Attr *A) {
@@ -304,6 +317,7 @@
 DEF_SIMPLE_ATTR(NoReturn);
 DEF_SIMPLE_ATTR(AnalyzerNoReturn);
 DEF_SIMPLE_ATTR(Deprecated);
+DEF_SIMPLE_ATTR(Final);
 
 class SectionAttr : public Attr {
   std::string Name;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sat Nov 21 02:43:09 2009
@@ -75,6 +75,7 @@
 def err_expected_lbrace : Error<"expected '{'">;
 def err_expected_lparen : Error<"expected '('">;
 def err_expected_rparen : Error<"expected ')'">;
+def err_expected_lsquare : Error<"expected '['">;
 def err_expected_rsquare : Error<"expected ']'">;
 def err_expected_rbrace : Error<"expected '}'">;
 def err_expected_greater : Error<"expected '>'">;
@@ -245,6 +246,11 @@
 def err_anon_type_definition : Error<
   "declaration of anonymous %0 must be a definition">;
 
+def err_cxx0x_attribute_forbids_arguments : Error<
+  "C++0x attribute '%0' cannot have an argument list">;
+def err_cxx0x_attribute_requires_arguments : Error<
+  "C++0x attribute '%0' must have an argument list">;
+def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
 
 /// C++ Templates
 def err_expected_template : Error<"expected template">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Nov 21 02:43:09 2009
@@ -551,6 +551,12 @@
   "|class member|exception declaration|template parameter|block literal}0">;
 def err_auto_var_requires_init : Error<
   "declaration of variable %0 with type %1 requires an initializer">;
+
+// C++0x [[final]]
+def err_final_function_overridden : Error<
+  "declaration of %0 overrides a 'final' function">;
+def err_final_base : Error<
+  "derivation from 'final' %0">;
   
 // Objective-C++
 def err_objc_decls_may_only_appear_in_global_scope : Error<
@@ -638,8 +644,14 @@
   "'weak_import' attribute cannot be specified on a definition">;
 def warn_attribute_wrong_decl_type : Warning<
   "%0 attribute only applies to %select{function|union|"
-  "variable and function|function or method|parameter|parameter or Objective-C method |"
-  "function, method or block}1 types">;
+  "variable and function|function or method|parameter|"
+  "parameter or Objective-C method |function, method or block|"
+  "virtual method or class|function, method, or parameter}1 types">;
+def err_attribute_wrong_decl_type : Error<
+  "%0 attribute only applies to %select{function|union|"
+  "variable and function|function or method|parameter|"
+  "parameter or Objective-C method |function, method or block|"
+  "virtual method or class|function, method, or parameter}1 types">;
 def warn_gnu_inline_attribute_requires_inline : Warning<
   "'gnu_inline' attribute requires function to be marked 'inline',"
   " attribute ignored">;

Modified: cfe/trunk/include/clang/Parse/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/AttributeList.h?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/AttributeList.h (original)
+++ cfe/trunk/include/clang/Parse/AttributeList.h Sat Nov 21 02:43:09 2009
@@ -33,19 +33,22 @@
 class AttributeList {
   IdentifierInfo *AttrName;
   SourceLocation AttrLoc;
+  IdentifierInfo *ScopeName;
+  SourceLocation ScopeLoc;
   IdentifierInfo *ParmName;
   SourceLocation ParmLoc;
   ActionBase::ExprTy **Args;
   unsigned NumArgs;
   AttributeList *Next;
-  bool DeclspecAttribute;
+  bool DeclspecAttribute, CXX0XAttribute;
   AttributeList(const AttributeList &); // DO NOT IMPLEMENT
   void operator=(const AttributeList &); // DO NOT IMPLEMENT
 public:
   AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+                IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
                 IdentifierInfo *ParmName, SourceLocation ParmLoc,
                 ActionBase::ExprTy **args, unsigned numargs,
-                AttributeList *Next, bool declspec = false);
+                AttributeList *Next, bool declspec = false, bool cxx0x = false);
   ~AttributeList();
 
   enum Kind {              // Please keep this list alphabetized.
@@ -57,6 +60,7 @@
     AT_analyzer_noreturn,
     AT_annotate,
     AT_blocks,
+    AT_carries_dependency,
     AT_cdecl,
     AT_cleanup,
     AT_const,
@@ -67,6 +71,7 @@
     AT_dllimport,
     AT_ext_vector_type,
     AT_fastcall,
+    AT_final,
     AT_format,
     AT_format_arg,
     AT_gnu_inline,
@@ -106,8 +111,15 @@
 
   IdentifierInfo *getName() const { return AttrName; }
   SourceLocation getLoc() const { return AttrLoc; }
+  
+  bool hasScope() const { return ScopeName; }
+  IdentifierInfo *getScopeName() const { return ScopeName; }
+  SourceLocation getScopeLoc() const { return ScopeLoc; }
+  
   IdentifierInfo *getParameterName() const { return ParmName; }
+
   bool isDeclspecAttribute() const { return DeclspecAttribute; }
+  bool isCXX0XAttribute() const { return CXX0XAttribute; }
 
   Kind getKind() const { return getKind(getName()); }
   static Kind getKind(const IdentifierInfo *Name);
@@ -181,6 +193,22 @@
   return Left;
 }
 
+/// CXX0XAttributeList - A wrapper around a C++0x attribute list.
+/// Stores, in addition to the list proper, whether or not an actual list was
+/// (as opposed to an empty list, which may be ill-formed in some places) and
+/// the source range of the list.
+struct CXX0XAttributeList { 
+  AttributeList *AttrList;
+  SourceRange Range;
+  bool HasAttr;
+  CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
+    : AttrList(attrList), Range(range), HasAttr (hasAttr) {
+  }
+  CXX0XAttributeList ()
+    : AttrList(0), Range(), HasAttr(false) {
+  }
+};
+
 }  // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Nov 21 02:43:09 2009
@@ -24,6 +24,7 @@
 
 namespace clang {
   class AttributeList;
+  struct CXX0XAttributeList;
   class PragmaHandler;
   class Scope;
   class DiagnosticBuilder;
@@ -753,10 +754,10 @@
 
   //===--------------------------------------------------------------------===//
   // C99 6.9: External Definitions.
-  DeclGroupPtrTy ParseExternalDeclaration();
+  DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr);
   bool isDeclarationAfterDeclarator();
   bool isStartOfFunctionDefinition();
-  DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
+  DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
             AccessSpecifier AS = AS_none);
 
   DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
@@ -994,24 +995,25 @@
     return ParseStatementOrDeclaration(true);
   }
   OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
-  OwningStmtResult ParseLabeledStatement();
-  OwningStmtResult ParseCaseStatement();
-  OwningStmtResult ParseDefaultStatement();
-  OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false);
+  OwningStmtResult ParseLabeledStatement(AttributeList *Attr);
+  OwningStmtResult ParseCaseStatement(AttributeList *Attr);
+  OwningStmtResult ParseDefaultStatement(AttributeList *Attr);
+  OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
+                                          bool isStmtExpr = false);
   OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
   bool ParseParenExprOrCondition(OwningExprResult &CondExp,
                                  bool OnlyAllowCondition = false,
                                  SourceLocation *LParenLoc = 0,
                                  SourceLocation *RParenLoc = 0);
-  OwningStmtResult ParseIfStatement();
-  OwningStmtResult ParseSwitchStatement();
-  OwningStmtResult ParseWhileStatement();
-  OwningStmtResult ParseDoStatement();
-  OwningStmtResult ParseForStatement();
-  OwningStmtResult ParseGotoStatement();
-  OwningStmtResult ParseContinueStatement();
-  OwningStmtResult ParseBreakStatement();
-  OwningStmtResult ParseReturnStatement();
+  OwningStmtResult ParseIfStatement(AttributeList *Attr);
+  OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
+  OwningStmtResult ParseWhileStatement(AttributeList *Attr);
+  OwningStmtResult ParseDoStatement(AttributeList *Attr);
+  OwningStmtResult ParseForStatement(AttributeList *Attr);
+  OwningStmtResult ParseGotoStatement(AttributeList *Attr);
+  OwningStmtResult ParseContinueStatement(AttributeList *Attr);
+  OwningStmtResult ParseBreakStatement(AttributeList *Attr);
+  OwningStmtResult ParseReturnStatement(AttributeList *Attr);
   OwningStmtResult ParseAsmStatement(bool &msAsm);
   OwningStmtResult FuzzyParseMicrosoftAsmStatement();
   bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
@@ -1021,7 +1023,7 @@
   //===--------------------------------------------------------------------===//
   // C++ 6: Statements and Blocks
 
-  OwningStmtResult ParseCXXTryBlock();
+  OwningStmtResult ParseCXXTryBlock(AttributeList *Attr);
   OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
   OwningStmtResult ParseCXXCatchBlock();
 
@@ -1045,9 +1047,11 @@
     DSC_class   // class context, enables 'friend'
   };
 
-  DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
+  DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
+                                  CXX0XAttributeList Attr);
   DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
-                                        SourceLocation &DeclEnd);
+                                        SourceLocation &DeclEnd,
+                                        AttributeList *Attr);
   DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
                                 bool AllowFunctionDefinitions,
                                 SourceLocation *DeclEnd = 0);
@@ -1217,11 +1221,14 @@
   void ParseBlockId();
   // EndLoc, if non-NULL, is filled with the location of the last token of
   // the attribute list.
-  AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
+  CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0);
+  AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
   AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
   AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
   void ParseTypeofSpecifier(DeclSpec &DS);
   void ParseDecltypeSpecifier(DeclSpec &DS);
+  
+  OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start);
 
   /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
   /// enter a new C++ declarator scope and exit it when the function is
@@ -1265,7 +1272,8 @@
   typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
   void ParseDeclaratorInternal(Declarator &D,
                                DirectDeclParseFunction DirectDeclParser);
-  void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true);
+  void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true,
+                                 bool CXX0XAttributesAllowed = true);
   void ParseDirectDeclarator(Declarator &D);
   void ParseParenDeclarator(Declarator &D);
   void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
@@ -1278,12 +1286,17 @@
   //===--------------------------------------------------------------------===//
   // C++ 7: Declarations [dcl.dcl]
 
+  bool isCXX0XAttributeSpecifier(bool FullLookahead = false, 
+                                 tok::TokenKind *After = 0);
+  
   DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
   DeclPtrTy ParseLinkage(unsigned Context);
   DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
-                                             SourceLocation &DeclEnd);
+                                             SourceLocation &DeclEnd,
+                                             CXX0XAttributeList Attrs);
   DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
-                                SourceLocation &DeclEnd);
+                                SourceLocation &DeclEnd,
+                                AttributeList *Attr);
   DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
                                   SourceLocation &DeclEnd,
                                   AccessSpecifier AS = AS_none);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Nov 21 02:43:09 2009
@@ -521,7 +521,7 @@
   unsigned Align = Target.getCharWidth();
 
   if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
-    Align = std::max(Align, AA->getAlignment());
+    Align = std::max(Align, AA->getMaxAlignment());
 
   if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
     QualType T = VD->getType();
@@ -761,7 +761,8 @@
   case Type::Typedef: {
     const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
     if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
-      Align = Aligned->getAlignment();
+      Align = std::max(Aligned->getMaxAlignment(),
+                       getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
       Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
     } else
       return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Nov 21 02:43:09 2009
@@ -448,7 +448,7 @@
     MaxFieldAlignment = PPA->getAlignment();
 
   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-    UpdateAlignment(AA->getAlignment());
+    UpdateAlignment(AA->getMaxAlignment());
 
   // If this is a C++ class, lay out the vtable and the non-virtual bases.
   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
@@ -498,7 +498,7 @@
     MaxFieldAlignment = PPA->getAlignment();
 
   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-    UpdateAlignment(AA->getAlignment());
+    UpdateAlignment(AA->getMaxAlignment());
 
   // Layout each ivar sequentially.
   llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
@@ -539,8 +539,9 @@
 
     if (FieldPacked)
       FieldAlign = 1;
-    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-      FieldAlign = std::max(FieldAlign, AA->getAlignment());
+    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+      FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+    }
     // The maximum field alignment overrides the aligned attribute.
     if (MaxFieldAlignment)
       FieldAlign = std::min(FieldAlign, MaxFieldAlignment);
@@ -574,8 +575,9 @@
 
     if (FieldPacked)
       FieldAlign = 8;
-    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-      FieldAlign = std::max(FieldAlign, AA->getAlignment());
+    if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+      FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+    }
     // The maximum field alignment overrides the aligned attribute.
     if (MaxFieldAlignment)
       FieldAlign = std::min(FieldAlign, MaxFieldAlignment);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Nov 21 02:43:09 2009
@@ -353,8 +353,12 @@
   else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
     F->addFnAttr(llvm::Attribute::StackProtectReq);
   
-  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
-    F->setAlignment(AA->getAlignment()/8);
+  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
+    unsigned width = Context.Target.getCharWidth();
+    F->setAlignment(AA->getAlignment() / width);
+    while ((AA = AA->getNext<AlignedAttr>()))
+      F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width));
+  }
   // C++ ABI requires 2-byte alignment for member functions.
   if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
     F->setAlignment(2);

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Sat Nov 21 02:43:09 2009
@@ -461,6 +461,7 @@
     SIMPLE_ATTR(Deprecated);
     UNSIGNED_ATTR(Destructor);
     SIMPLE_ATTR(FastCall);
+    SIMPLE_ATTR(Final);
 
     case Attr::Format: {
       std::string Type = ReadString(Record, Idx);

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Sat Nov 21 02:43:09 2009
@@ -1792,6 +1792,7 @@
       break;
 
     case Attr::FastCall:
+    case Attr::Final:
       break;
 
     case Attr::Format: {

Modified: cfe/trunk/lib/Parse/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/AttributeList.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/AttributeList.cpp (original)
+++ cfe/trunk/lib/Parse/AttributeList.cpp Sat Nov 21 02:43:09 2009
@@ -17,11 +17,13 @@
 using namespace clang;
 
 AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
+                             IdentifierInfo *sName, SourceLocation sLoc,
                              IdentifierInfo *pName, SourceLocation pLoc,
                              ActionBase::ExprTy **ExprList, unsigned numArgs,
-                             AttributeList *n, bool declspec)
-  : AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
-    NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) {
+                             AttributeList *n, bool declspec, bool cxx0x)
+  : AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc),
+    ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n),
+    DeclspecAttribute(declspec), CXX0XAttribute(cxx0x) {
 
   if (numArgs == 0)
     Args = 0;
@@ -59,6 +61,8 @@
     .Case("mode", AT_mode)
     .Case("used", AT_used)
     .Case("alias", AT_alias)
+    .Case("align", AT_aligned)
+    .Case("final", AT_final)
     .Case("cdecl", AT_cdecl)
     .Case("const", AT_const)
     .Case("packed", AT_packed)
@@ -103,6 +107,7 @@
     .Case("transparent_union", AT_transparent_union)
     .Case("analyzer_noreturn", AT_analyzer_noreturn)
     .Case("warn_unused_result", AT_warn_unused_result)
+    .Case("carries_dependency", AT_carries_dependency)
     .Case("ns_returns_retained", AT_ns_returns_retained)
     .Case("cf_returns_retained", AT_cf_returns_retained)
     .Case("reqd_work_group_size", AT_reqd_wg_size)

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Nov 21 02:43:09 2009
@@ -1,3 +1,4 @@
+
 //===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
 //
 //                     The LLVM Compiler Infrastructure
@@ -45,7 +46,7 @@
   return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
 }
 
-/// ParseAttributes - Parse a non-empty attributes list.
+/// ParseGNUAttributes - Parse a non-empty attributes list.
 ///
 /// [GNU] attributes:
 ///         attribute
@@ -81,8 +82,8 @@
 /// attributes are very simple in practice. Until we find a bug, I don't see
 /// a pressing need to implement the 2 token lookahead.
 
-AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
-  assert(Tok.is(tok::kw___attribute) && "Not an attribute list!");
+AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
+  assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
 
   AttributeList *CurrAttr = 0;
 
@@ -121,7 +122,7 @@
           if (Tok.is(tok::r_paren)) {
             // __attribute__(( mode(byte) ))
             ConsumeParen(); // ignore the right paren loc for now
-            CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
                                          ParmName, ParmLoc, 0, 0, CurrAttr);
           } else if (Tok.is(tok::comma)) {
             ConsumeToken();
@@ -145,8 +146,10 @@
             }
             if (ArgExprsOk && Tok.is(tok::r_paren)) {
               ConsumeParen(); // ignore the right paren loc for now
-              CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
-                           ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr);
+              CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+                                           AttrNameLoc, ParmName, ParmLoc,
+                                           ArgExprs.take(), ArgExprs.size(),
+                                           CurrAttr);
             }
           }
         } else { // not an identifier
@@ -155,7 +158,7 @@
           // parse a possibly empty comma separated list of expressions
             // __attribute__(( nonnull() ))
             ConsumeParen(); // ignore the right paren loc for now
-            CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
                                          0, SourceLocation(), 0, 0, CurrAttr);
             break;
           case tok::kw_char:
@@ -175,7 +178,7 @@
             // If it's a builtin type name, eat it and expect a rparen
             // __attribute__(( vec_type_hint(char) ))
             ConsumeToken();
-            CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+            CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
                                          0, SourceLocation(), 0, 0, CurrAttr);
             if (Tok.is(tok::r_paren))
               ConsumeParen();
@@ -203,20 +206,21 @@
             if (ArgExprsOk && Tok.is(tok::r_paren)) {
               ConsumeParen(); // ignore the right paren loc for now
               CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
-                           SourceLocation(), ArgExprs.take(), ArgExprs.size(),
+                           AttrNameLoc, 0, SourceLocation(), ArgExprs.take(),
+                           ArgExprs.size(),
                            CurrAttr);
             }
             break;
           }
         }
       } else {
-        CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+        CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
                                      0, SourceLocation(), 0, 0, CurrAttr);
       }
     }
     if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
       SkipUntil(tok::r_paren, false);
-    SourceLocation Loc = Tok.getLocation();;
+    SourceLocation Loc = Tok.getLocation();
     if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
       SkipUntil(tok::r_paren, false);
     }
@@ -254,15 +258,15 @@
       OwningExprResult ArgExpr(ParseAssignmentExpression());
       if (!ArgExpr.isInvalid()) {
         ExprTy* ExprList = ArgExpr.take();
-        CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+        CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
                                      SourceLocation(), &ExprList, 1,
                                      CurrAttr, true);
       }
       if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
         SkipUntil(tok::r_paren, false);
     } else {
-      CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(),
-                                   0, 0, CurrAttr, true);
+      CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+                                   0, SourceLocation(), 0, 0, CurrAttr, true);
     }
   }
   if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
@@ -281,7 +285,7 @@
     if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
       // FIXME: Support these properly!
       continue;
-    CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+    CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
                                  SourceLocation(), 0, 0, CurrAttr, true);
   }
   return CurrAttr;
@@ -304,26 +308,36 @@
 ///         others... [FIXME]
 ///
 Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
-                                                SourceLocation &DeclEnd) {
+                                                SourceLocation &DeclEnd,
+                                                CXX0XAttributeList Attr) {
   DeclPtrTy SingleDecl;
   switch (Tok.getKind()) {
   case tok::kw_template:
   case tok::kw_export:
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
     SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
     break;
   case tok::kw_namespace:
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
     SingleDecl = ParseNamespace(Context, DeclEnd);
     break;
   case tok::kw_using:
-    SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd);
+    SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr);
     break;
   case tok::kw_static_assert:
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
     SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
     break;
   default:
-    return ParseSimpleDeclaration(Context, DeclEnd);
+    return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList);
   }
-
+  
   // This routine returns a DeclGroup, if the thing we parsed only contains a
   // single decl, convert it now.
   return Actions.ConvertDeclToDeclGroup(SingleDecl);
@@ -337,9 +351,12 @@
 /// If RequireSemi is false, this does not check for a ';' at the end of the
 /// declaration.
 Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
-                                                      SourceLocation &DeclEnd) {
+                                                      SourceLocation &DeclEnd,
+                                                      AttributeList *Attr) {
   // Parse the common declaration-specifiers piece.
   ParsingDeclSpec DS(*this);
+  if (Attr)
+    DS.AddAttributes(Attr);
   ParseDeclarationSpecifiers(DS);
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -422,7 +439,7 @@
     //    short x, __attribute__((common)) var;    -> declarator
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       D.AddAttributes(AttrList, Loc);
     }
 
@@ -491,7 +508,7 @@
   // If attributes are present, parse them.
   if (Tok.is(tok::kw___attribute)) {
     SourceLocation Loc;
-    AttributeList *AttrList = ParseAttributes(&Loc);
+    AttributeList *AttrList = ParseGNUAttributes(&Loc);
     D.AddAttributes(AttrList, Loc);
   }
 
@@ -988,7 +1005,7 @@
 
     // GNU attributes support.
     case tok::kw___attribute:
-      DS.AddAttributes(ParseAttributes());
+      DS.AddAttributes(ParseGNUAttributes());
       continue;
 
     // Microsoft declspec support.
@@ -1522,7 +1539,7 @@
     // Attributes are only allowed here on successive declarators.
     if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       DeclaratorInfo.D.AddAttributes(AttrList, Loc);
     }
 
@@ -1543,7 +1560,7 @@
     // If attributes exist after the declarator, parse them.
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       DeclaratorInfo.D.AddAttributes(AttrList, Loc);
     }
 
@@ -1667,7 +1684,7 @@
   AttributeList *AttrList = 0;
   // If attributes exist after struct contents, parse them.
   if (Tok.is(tok::kw___attribute))
-    AttrList = ParseAttributes();
+    AttrList = ParseGNUAttributes();
 
   Actions.ActOnFields(CurScope,
                       RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
@@ -1702,7 +1719,7 @@
   AttributeList *Attr = 0;
   // If attributes exist after tag, parse them.
   if (Tok.is(tok::kw___attribute))
-    Attr = ParseAttributes();
+    Attr = ParseGNUAttributes();
 
   CXXScopeSpec SS;
   if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
@@ -1833,7 +1850,7 @@
   AttributeList *Attr = 0;
   // If attributes exist after the identifier list, parse them.
   if (Tok.is(tok::kw___attribute))
-    Attr = ParseAttributes();
+    Attr = ParseGNUAttributes(); // FIXME: where do they do?
 
   Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
                         EnumConstantDecls.data(), EnumConstantDecls.size(),
@@ -2049,8 +2066,20 @@
 /// [GNU]   attributes                        [ only if AttributesAllowed=true ]
 ///         type-qualifier-list type-qualifier
 /// [GNU]   type-qualifier-list attributes    [ only if AttributesAllowed=true ]
+/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
+///           if CXX0XAttributesAllowed = true
 ///
-void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) {
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
+                                       bool CXX0XAttributesAllowed) {
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    SourceLocation Loc = Tok.getLocation();
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    if (CXX0XAttributesAllowed)
+      DS.AddAttributes(Attr.AttrList);
+    else
+      Diag(Loc, diag::err_attributes_not_allowed);
+  }
+  
   while (1) {
     bool isInvalid = false;
     const char *PrevSpec = 0;
@@ -2075,14 +2104,14 @@
     case tok::kw___cdecl:
     case tok::kw___stdcall:
     case tok::kw___fastcall:
-      if (AttributesAllowed) {
+      if (GNUAttributesAllowed) {
         DS.AddAttributes(ParseMicrosoftTypeAttributes());
         continue;
       }
       goto DoneWithTypeQuals;
     case tok::kw___attribute:
-      if (AttributesAllowed) {
-        DS.AddAttributes(ParseAttributes());
+      if (GNUAttributesAllowed) {
+        DS.AddAttributes(ParseGNUAttributes());
         continue; // do *not* consume the next token!
       }
       // otherwise, FALL THROUGH!
@@ -2221,7 +2250,8 @@
     //
     // [GNU] Retricted references are allowed.
     // [GNU] Attributes on references are allowed.
-    ParseTypeQualifierListOpt(DS);
+    // [C++0x] Attributes on references are not allowed.
+    ParseTypeQualifierListOpt(DS, true, false);
     D.ExtendWithDeclSpec(DS);
 
     if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
@@ -2362,6 +2392,14 @@
   assert(D.isPastIdentifier() &&
          "Haven't past the location of the identifier yet?");
 
+  // Don't parse attributes unless we have an identifier.
+  if (D.getIdentifier() && getLang().CPlusPlus
+   && isCXX0XAttributeSpecifier(true)) {
+    SourceLocation AttrEndLoc;
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    D.AddAttributes(Attr.AttrList, AttrEndLoc);
+  }
+
   while (1) {
     if (Tok.is(tok::l_paren)) {
       // The paren may be part of a C++ direct initializer, eg. "int x(1);".
@@ -2413,7 +2451,7 @@
   AttributeList *AttrList = 0;
   bool RequiresArg = false;
   if (Tok.is(tok::kw___attribute)) {
-    AttrList = ParseAttributes();
+    AttrList = ParseGNUAttributes();
 
     // We require that the argument list (if this is a non-grouping paren) be
     // present even if the attribute list was empty.
@@ -2618,7 +2656,7 @@
     // Parse GNU attributes, if present.
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       ParmDecl.AddAttributes(AttrList, Loc);
     }
 
@@ -2722,6 +2760,7 @@
   bool hasAnyExceptionSpec = false;
   llvm::SmallVector<TypeTy*, 2> Exceptions;
   llvm::SmallVector<SourceRange, 2> ExceptionRanges;
+  
   if (getLang().CPlusPlus) {
     // Parse cv-qualifier-seq[opt].
     ParseTypeQualifierListOpt(DS, false /*no attributes*/);
@@ -2842,6 +2881,12 @@
   // This code does a fast path to handle some of the most obvious cases.
   if (Tok.getKind() == tok::r_square) {
     SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+    //FIXME: Use these
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) {
+      Attr = ParseCXX0XAttributes();
+    }
+    
     // Remember that we parsed the empty array type.
     OwningExprResult NumElements(Actions);
     D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
@@ -2855,6 +2900,11 @@
     ConsumeToken();
 
     SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
+    //FIXME: Use these
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+      Attr = ParseCXX0XAttributes();
+    }
 
     // If there was an error parsing the assignment-expression, recover.
     if (ExprRes.isInvalid())
@@ -2922,6 +2972,12 @@
 
   SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
 
+  //FIXME: Use these
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    Attr = ParseCXX0XAttributes();
+  }
+
   // Remember that we parsed a array type, and remember its features.
   D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
                                           StaticLoc.isValid(), isStar,

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Nov 21 02:43:09 2009
@@ -69,7 +69,7 @@
     attrTok = Tok;
 
     // FIXME: save these somewhere.
-    AttrList = ParseAttributes();
+    AttrList = ParseGNUAttributes();
   }
 
   if (Tok.is(tok::equal)) {
@@ -97,8 +97,12 @@
                                         PP.getSourceManager(),
                                         "parsing namespace");
 
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
-    ParseExternalDeclaration();
+  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      Attr = ParseCXX0XAttributes();
+    ParseExternalDeclaration(Attr);
+  }
 
   // Leave the namespace scope.
   NamespaceScope.Exit();
@@ -175,15 +179,27 @@
                                        Tok.is(tok::l_brace)? Tok.getLocation()
                                                            : SourceLocation());
 
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    Attr = ParseCXX0XAttributes();
+  }
+  
   if (Tok.isNot(tok::l_brace)) {
-    ParseDeclarationOrFunctionDefinition();
+    ParseDeclarationOrFunctionDefinition(Attr.AttrList);
     return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
                                                    SourceLocation());
   }
 
+  if (Attr.HasAttr)
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
+
   SourceLocation LBrace = ConsumeBrace();
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
-    ParseExternalDeclaration();
+    CXX0XAttributeList Attr;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      Attr = ParseCXX0XAttributes();
+    ParseExternalDeclaration(Attr);
   }
 
   SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
@@ -193,7 +209,8 @@
 /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
 /// using-directive. Assumes that current token is 'using'.
 Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
-                                                     SourceLocation &DeclEnd) {
+                                                     SourceLocation &DeclEnd,
+                                                     CXX0XAttributeList Attr) {
   assert(Tok.is(tok::kw_using) && "Not using token");
 
   // Eat 'using'.
@@ -206,9 +223,14 @@
   
   if (Tok.is(tok::kw_namespace))
     // Next token after 'using' is 'namespace' so it must be using-directive
-    return ParseUsingDirective(Context, UsingLoc, DeclEnd);
+    return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
+
+  if (Attr.HasAttr)
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
 
   // Otherwise, it must be using-declaration.
+  // Ignore illegal attributes (the caller should already have issued an error.
   return ParseUsingDeclaration(Context, UsingLoc, DeclEnd);
 }
 
@@ -224,7 +246,8 @@
 ///
 Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
                                               SourceLocation UsingLoc,
-                                              SourceLocation &DeclEnd) {
+                                              SourceLocation &DeclEnd,
+                                              AttributeList *Attr) {
   assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
 
   // Eat 'namespace'.
@@ -239,7 +262,6 @@
   // Parse (optional) nested-name-specifier.
   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
 
-  AttributeList *AttrList = 0;
   IdentifierInfo *NamespcName = 0;
   SourceLocation IdentLoc = SourceLocation();
 
@@ -257,17 +279,20 @@
   IdentLoc = ConsumeToken();
 
   // Parse (optional) attributes (most likely GNU strong-using extension).
-  if (Tok.is(tok::kw___attribute))
-    AttrList = ParseAttributes();
+  bool GNUAttr = false;
+  if (Tok.is(tok::kw___attribute)) {
+    GNUAttr = true;
+    Attr = addAttributeLists(Attr, ParseGNUAttributes());
+  }
 
   // Eat ';'.
   DeclEnd = Tok.getLocation();
   ExpectAndConsume(tok::semi,
-                   AttrList ? diag::err_expected_semi_after_attribute_list :
+                   GNUAttr ? diag::err_expected_semi_after_attribute_list :
                    diag::err_expected_semi_after_namespace_name, "", tok::semi);
 
   return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
-                                      IdentLoc, NamespcName, AttrList);
+                                      IdentLoc, NamespcName, Attr);
 }
 
 /// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
@@ -323,7 +348,7 @@
   
   // Parse (optional) attributes (most likely GNU strong-using extension).
   if (Tok.is(tok::kw___attribute))
-    AttrList = ParseAttributes();
+    AttrList = ParseGNUAttributes();
 
   // Eat ';'.
   DeclEnd = Tok.getLocation();
@@ -538,14 +563,20 @@
     ConsumeToken();
   }
   
-  AttributeList *Attr = 0;
+  AttributeList *AttrList = 0;
   // If attributes exist after tag, parse them.
   if (Tok.is(tok::kw___attribute))
-    Attr = ParseAttributes();
+    AttrList = ParseGNUAttributes();
 
   // If declspecs exist after tag, parse them.
   if (Tok.is(tok::kw___declspec))
-    Attr = ParseMicrosoftDeclSpec(Attr);
+    AttrList = ParseMicrosoftDeclSpec(AttrList);
+  
+  // If C++0x attributes exist here, parse them.
+  // FIXME: Are we consistent with the ordering of parsing of different
+  // styles of attributes?
+  if (isCXX0XAttributeSpecifier())
+    AttrList = addAttributeLists(AttrList, ParseCXX0XAttributes().AttrList);
 
   if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
     // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
@@ -683,7 +714,6 @@
     Diag(StartLoc, diag::err_anon_type_definition)
       << DeclSpec::getSpecifierName(TagType);
 
-    // Skip the rest of this declarator, up until the comma or semicolon.
     SkipUntil(tok::comma, true);
 
     if (TemplateId)
@@ -720,7 +750,7 @@
                                              TemplateId->LAngleLoc,
                                              TemplateArgsPtr,
                                              TemplateId->RAngleLoc,
-                                             Attr);
+                                             AttrList);
     } else if (TUK == Action::TUK_Reference) {
       TypeResult
         = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
@@ -775,7 +805,7 @@
                        TemplateId->LAngleLoc,
                        TemplateArgsPtr,
                        TemplateId->RAngleLoc,
-                       Attr,
+                       AttrList,
                        Action::MultiTemplateParamsArg(Actions,
                                     TemplateParams? &(*TemplateParams)[0] : 0,
                                  TemplateParams? TemplateParams->size() : 0));
@@ -793,7 +823,7 @@
                                            TemplateInfo.ExternLoc,
                                            TemplateInfo.TemplateLoc,
                                            TagType, StartLoc, SS, Name,
-                                           NameLoc, Attr);
+                                           NameLoc, AttrList);
   } else {
     if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
         TUK == Action::TUK_Definition) {
@@ -804,7 +834,7 @@
 
     // Declaration or definition of a class type
     TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS,
-                                       Name, NameLoc, Attr, AS,
+                                       Name, NameLoc, AttrList, AS,
                                   Action::MultiTemplateParamsArg(Actions,
                                     TemplateParams? &(*TemplateParams)[0] : 0,
                                     TemplateParams? TemplateParams->size() : 0),
@@ -1055,8 +1085,18 @@
     return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
   }
 
+  CXX0XAttributeList AttrList;
+  // Optional C++0x attribute-specifier
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    AttrList = ParseCXX0XAttributes();
+  }
+
   if (Tok.is(tok::kw_using)) {
     // FIXME: Check for template aliases
+    
+    if (AttrList.HasAttr)
+      Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
+        << AttrList.Range;
 
     // Eat 'using'.
     SourceLocation UsingLoc = ConsumeToken();
@@ -1077,6 +1117,7 @@
   // decl-specifier-seq:
   // Parse the common declaration-specifiers piece.
   ParsingDeclSpec DS(*this);
+  DS.AddAttributes(AttrList.AttrList);
   ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
 
   Action::MultiTemplateParamsArg TemplateParams(Actions,
@@ -1139,7 +1180,6 @@
   bool Deleted = false;
 
   while (1) {
-
     // member-declarator:
     //   declarator pure-specifier[opt]
     //   declarator constant-initializer[opt]
@@ -1177,7 +1217,7 @@
     // If attributes exist after the declarator, parse them.
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       DeclaratorInfo.AddAttributes(AttrList, Loc);
     }
 
@@ -1227,7 +1267,7 @@
     // Attributes are only allowed on the second declarator.
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       DeclaratorInfo.AddAttributes(AttrList, Loc);
     }
 
@@ -1326,7 +1366,7 @@
   AttributeList *AttrList = 0;
   // If attributes exist after class contents, parse them.
   if (Tok.is(tok::kw___attribute))
-    AttrList = ParseAttributes(); // FIXME: where should I put them?
+    AttrList = ParseGNUAttributes(); // FIXME: where should I put them?
 
   Actions.ActOnFinishCXXMemberSpecification(CurScope, RecordLoc, TagDecl,
                                             LBraceLoc, RBraceLoc);
@@ -1573,3 +1613,170 @@
   ClassStack.top()->NestedClasses.push_back(Victim);
   Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope();
 }
+
+/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only
+/// parses standard attributes.
+///
+/// [C++0x] attribute-specifier:
+///         '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+///         attribute[opt]
+///         attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+///         attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+///         identifier
+///         attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+///         attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+///         identifier
+///
+/// [C++0x] attribute-argument-clause:
+///         '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+///         balanced-token
+///         balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+///         '(' balanced-token-seq ')'
+///         '[' balanced-token-seq ']'
+///         '{' balanced-token-seq '}'
+///         any token but '(', ')', '[', ']', '{', or '}'
+CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
+  assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
+      && "Not a C++0x attribute list");
+
+  SourceLocation StartLoc = Tok.getLocation(), Loc;
+  AttributeList *CurrAttr = 0;
+
+  ConsumeBracket();
+  ConsumeBracket();
+  
+  if (Tok.is(tok::comma)) {
+    Diag(Tok.getLocation(), diag::err_expected_ident);
+    ConsumeToken();
+  }
+
+  while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
+    // attribute not present
+    if (Tok.is(tok::comma)) {
+      ConsumeToken();
+      continue;
+    }
+
+    IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
+    SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
+    
+    // scoped attribute
+    if (Tok.is(tok::coloncolon)) {
+      ConsumeToken();
+
+      if (!Tok.is(tok::identifier)) {
+        Diag(Tok.getLocation(), diag::err_expected_ident);
+        SkipUntil(tok::r_square, tok::comma, true, true);
+        continue;
+      }
+      
+      ScopeName = AttrName;
+      ScopeLoc = AttrLoc;
+
+      AttrName = Tok.getIdentifierInfo();
+      AttrLoc = ConsumeToken();
+    }
+
+    bool AttrParsed = false;
+    // No scoped names are supported; ideally we could put all non-standard
+    // attributes into namespaces.
+    if (!ScopeName) {
+      switch(AttributeList::getKind(AttrName))
+      {
+      // No arguments
+      case AttributeList::AT_noreturn:
+      case AttributeList::AT_final:
+      case AttributeList::AT_carries_dependency: {
+        if (Tok.is(tok::l_paren)) {
+          Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
+            << AttrName->getName();
+          break;
+        }
+
+        CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc, 0,
+                                     SourceLocation(), 0, 0, CurrAttr, false,
+                                     true);
+        AttrParsed = true;
+        break;
+      }
+
+      // One argument; must be a type-id or assignment-expression
+      case AttributeList::AT_aligned: {
+        if (Tok.isNot(tok::l_paren)) {
+          Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments)
+            << AttrName->getName();
+          break;
+        }
+        SourceLocation ParamLoc = ConsumeParen();
+
+        OwningExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
+
+        MatchRHSPunctuation(tok::r_paren, ParamLoc);
+
+        ExprVector ArgExprs(Actions);
+        ArgExprs.push_back(ArgExpr.release());
+        CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc,
+                                     0, ParamLoc, ArgExprs.take(), 1, CurrAttr,
+                                     false, true);
+
+        AttrParsed = true;
+        break;
+      }
+
+      // Silence warnings
+      default: break;
+      }
+    }
+
+    // Skip the entire parameter clause, if any
+    if (!AttrParsed && Tok.is(tok::l_paren)) {
+      ConsumeParen();
+      // SkipUntil maintains the balancedness of tokens.
+      SkipUntil(tok::r_paren, false);
+    }
+  }
+
+  if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+    SkipUntil(tok::r_square, false);
+  Loc = Tok.getLocation();
+  if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+    SkipUntil(tok::r_square, false);
+
+  CXX0XAttributeList Attr (CurrAttr, SourceRange(StartLoc, Loc), true);
+  return Attr;
+}
+
+/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
+/// attribute.
+///
+/// FIXME: Simply returns an alignof() expression if the argument is a
+/// type. Ideally, the type should be propagated directly into Sema.
+///
+/// [C++0x] 'align' '(' type-id ')'
+/// [C++0x] 'align' '(' assignment-expression ')'
+Parser::OwningExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
+  if (isTypeIdInParens()) {
+    EnterExpressionEvaluationContext Unevaluated(Actions,
+                                                  Action::Unevaluated);
+    SourceLocation TypeLoc = Tok.getLocation();
+    TypeTy *Ty = ParseTypeName().get();
+    SourceRange TypeRange(Start, Tok.getLocation());
+    return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, Ty,
+                                              TypeRange);
+  } else
+    return ParseConstantExpression();
+}

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sat Nov 21 02:43:09 2009
@@ -1315,7 +1315,7 @@
 
   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
     Diag(Tok, diag::ext_gnu_statement_expr);
-    OwningStmtResult Stmt(ParseCompoundStatement(true));
+    OwningStmtResult Stmt(ParseCompoundStatement(0, true));
     ExprType = CompoundStmt;
 
     // If the substmt parsed correctly, build the AST node.
@@ -1503,7 +1503,7 @@
 
   if (Tok.is(tok::kw___attribute)) {
     SourceLocation Loc;
-    AttributeList *AttrList = ParseAttributes(&Loc);
+    AttributeList *AttrList = ParseGNUAttributes(&Loc);
     DeclaratorInfo.AddAttributes(AttrList, Loc);
   }
 
@@ -1565,7 +1565,7 @@
 
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       ParamInfo.AddAttributes(AttrList, Loc);
     }
 
@@ -1586,7 +1586,7 @@
 
     if (Tok.is(tok::kw___attribute)) {
       SourceLocation Loc;
-      AttributeList *AttrList = ParseAttributes(&Loc);
+      AttributeList *AttrList = ParseGNUAttributes(&Loc);
       ParamInfo.AddAttributes(AttrList, Loc);
     }
 

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Nov 21 02:43:09 2009
@@ -568,7 +568,7 @@
   // If attributes are present, parse them.
   if (Tok.is(tok::kw___attribute)) {
     SourceLocation Loc;
-    AttributeList *AttrList = ParseAttributes(&Loc);
+    AttributeList *AttrList = ParseGNUAttributes(&Loc);
     DeclaratorInfo.AddAttributes(AttrList, Loc);
   }
 

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Sat Nov 21 02:43:09 2009
@@ -282,7 +282,7 @@
 
       // FIXME: as the name implies, this rule allows function definitions.
       // We could pass a flag or check for functions during semantic analysis.
-      allTUVariables.push_back(ParseDeclarationOrFunctionDefinition());
+      allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(0));
       continue;
     }
 
@@ -759,7 +759,7 @@
     // If attributes exist after the method, parse them.
     AttributeList *MethodAttrs = 0;
     if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
-      MethodAttrs = ParseAttributes();
+      MethodAttrs = ParseGNUAttributes();
 
     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
     DeclPtrTy Result
@@ -791,7 +791,7 @@
     // If attributes exist before the argument name, parse them.
     ArgInfo.ArgAttrs = 0;
     if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
-      ArgInfo.ArgAttrs = ParseAttributes();
+      ArgInfo.ArgAttrs = ParseGNUAttributes();
 
     if (Tok.isNot(tok::identifier)) {
       Diag(Tok, diag::err_expected_ident); // missing argument name.
@@ -835,7 +835,7 @@
   // If attributes exist after the method, parse them.
   AttributeList *MethodAttrs = 0;
   if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
-    MethodAttrs = ParseAttributes();
+    MethodAttrs = ParseGNUAttributes();
 
   if (KeyIdents.size() == 0)
     return DeclPtrTy();

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sat Nov 21 02:43:09 2009
@@ -78,6 +78,10 @@
   const char *SemiError = 0;
   OwningStmtResult Res(Actions);
 
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    Attr = ParseCXX0XAttributes();
+
   // 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),
   // or they directly 'return;' if not.
@@ -98,14 +102,15 @@
   case tok::identifier:
     if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
       // identifier ':' statement
-      return ParseLabeledStatement();
+      return ParseLabeledStatement(Attr.AttrList);
     }
     // PASS THROUGH.
 
   default: {
     if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd);
+      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+                                             Attr);
       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
     }
 
@@ -114,6 +119,7 @@
       return StmtError();
     }
 
+    // FIXME: Use the attributes
     // expression[opt] ';'
     OwningExprResult Expr(ParseExpression());
     if (Expr.isInvalid()) {
@@ -129,47 +135,50 @@
   }
 
   case tok::kw_case:                // C99 6.8.1: labeled-statement
-    return ParseCaseStatement();
+    return ParseCaseStatement(Attr.AttrList);
   case tok::kw_default:             // C99 6.8.1: labeled-statement
-    return ParseDefaultStatement();
+    return ParseDefaultStatement(Attr.AttrList);
 
   case tok::l_brace:                // C99 6.8.2: compound-statement
-    return ParseCompoundStatement();
+    return ParseCompoundStatement(Attr.AttrList);
   case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
     return Actions.ActOnNullStmt(ConsumeToken());
 
   case tok::kw_if:                  // C99 6.8.4.1: if-statement
-    return ParseIfStatement();
+    return ParseIfStatement(Attr.AttrList);
   case tok::kw_switch:              // C99 6.8.4.2: switch-statement
-    return ParseSwitchStatement();
+    return ParseSwitchStatement(Attr.AttrList);
 
   case tok::kw_while:               // C99 6.8.5.1: while-statement
-    return ParseWhileStatement();
+    return ParseWhileStatement(Attr.AttrList);
   case tok::kw_do:                  // C99 6.8.5.2: do-statement
-    Res = ParseDoStatement();
+    Res = ParseDoStatement(Attr.AttrList);
     SemiError = "do/while";
     break;
   case tok::kw_for:                 // C99 6.8.5.3: for-statement
-    return ParseForStatement();
+    return ParseForStatement(Attr.AttrList);
 
   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
-    Res = ParseGotoStatement();
+    Res = ParseGotoStatement(Attr.AttrList);
     SemiError = "goto";
     break;
   case tok::kw_continue:            // C99 6.8.6.2: continue-statement
-    Res = ParseContinueStatement();
+    Res = ParseContinueStatement(Attr.AttrList);
     SemiError = "continue";
     break;
   case tok::kw_break:               // C99 6.8.6.3: break-statement
-    Res = ParseBreakStatement();
+    Res = ParseBreakStatement(Attr.AttrList);
     SemiError = "break";
     break;
   case tok::kw_return:              // C99 6.8.6.4: return-statement
-    Res = ParseReturnStatement();
+    Res = ParseReturnStatement(Attr.AttrList);
     SemiError = "return";
     break;
 
   case tok::kw_asm: {
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
     bool msAsm = false;
     Res = ParseAsmStatement(msAsm);
     if (msAsm) return move(Res);
@@ -178,7 +187,7 @@
   }
 
   case tok::kw_try:                 // C++ 15: try-block
-    return ParseCXXTryBlock();
+    return ParseCXXTryBlock(Attr.AttrList);
   }
 
   // If we reached this code, the statement must end in a semicolon.
@@ -202,7 +211,7 @@
 ///         identifier ':' statement
 /// [GNU]   identifier ':' attributes[opt] statement
 ///
-Parser::OwningStmtResult Parser::ParseLabeledStatement() {
+Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
          "Not an identifier!");
 
@@ -215,10 +224,8 @@
   SourceLocation ColonLoc = ConsumeToken();
 
   // Read label attributes, if present.
-  Action::AttrTy *AttrList = 0;
   if (Tok.is(tok::kw___attribute))
-    // TODO: save these somewhere.
-    AttrList = ParseAttributes();
+    Attr = addAttributeLists(Attr, ParseGNUAttributes());
 
   OwningStmtResult SubStmt(ParseStatement());
 
@@ -236,8 +243,9 @@
 ///         'case' constant-expression ':' statement
 /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
 ///
-Parser::OwningStmtResult Parser::ParseCaseStatement() {
+Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
   assert(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):
@@ -354,7 +362,8 @@
 ///         'default' ':' statement
 /// Note that this does not parse the 'statement' at the end.
 ///
-Parser::OwningStmtResult Parser::ParseDefaultStatement() {
+Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+  //FIXME: Use attributes?
   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
 
@@ -408,7 +417,9 @@
 /// [OMP]   barrier-directive
 /// [OMP]   flush-directive
 ///
-Parser::OwningStmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
+Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+                                                        bool isStmtExpr) {
+  //FIXME: Use attributes?
   assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
 
   // Enter a scope to hold everything within the compound stmt.  Compound
@@ -449,6 +460,10 @@
       while (Tok.is(tok::kw___extension__))
         ConsumeToken();
 
+      CXX0XAttributeList Attr;
+      if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+        Attr = ParseCXX0XAttributes();
+
       // If this is the start of a declaration, parse it as such.
       if (isDeclarationStatement()) {
         // __extension__ silences extension warnings in the subdeclaration.
@@ -456,7 +471,8 @@
         ExtensionRAIIObject O(Diags);
 
         SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext,DeclEnd);
+        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+                                              Attr);
         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
       } else {
         // Otherwise this was a unary __extension__ marker.
@@ -467,6 +483,7 @@
           continue;
         }
 
+        // FIXME: Use attributes?
         // Eat the semicolon at the end of stmt and convert the expr into a
         // statement.
         ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
@@ -537,7 +554,8 @@
 /// [C++]   'if' '(' condition ')' statement
 /// [C++]   'if' '(' condition ')' statement 'else' statement
 ///
-Parser::OwningStmtResult Parser::ParseIfStatement() {
+Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_if) && "Not an if stmt!");
   SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
 
@@ -659,7 +677,8 @@
 ///       switch-statement:
 ///         'switch' '(' expression ')' statement
 /// [C++]   'switch' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseSwitchStatement() {
+Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
   SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
 
@@ -734,7 +753,8 @@
 ///       while-statement: [C99 6.8.5.1]
 ///         'while' '(' expression ')' statement
 /// [C++]   'while' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseWhileStatement() {
+Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_while) && "Not a while stmt!");
   SourceLocation WhileLoc = Tok.getLocation();
   ConsumeToken();  // eat the 'while'.
@@ -805,7 +825,8 @@
 ///       do-statement: [C99 6.8.5.2]
 ///         'do' statement 'while' '(' expression ')' ';'
 /// Note: this lets the caller parse the end ';'.
-Parser::OwningStmtResult Parser::ParseDoStatement() {
+Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_do) && "Not a do stmt!");
   SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
 
@@ -880,7 +901,8 @@
 /// [C++]   expression-statement
 /// [C++]   simple-declaration
 ///
-Parser::OwningStmtResult Parser::ParseForStatement() {
+Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
   SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
 
@@ -937,8 +959,13 @@
     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
 
+    AttributeList *AttrList = 0;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      AttrList = ParseCXX0XAttributes().AttrList;
+
     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
+    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
+                                               AttrList);
     FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
 
     if (Tok.is(tok::semi)) {  // for (int x = 4;
@@ -1036,7 +1063,8 @@
 ///
 /// Note: this lets the caller parse the end ';'.
 ///
-Parser::OwningStmtResult Parser::ParseGotoStatement() {
+Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
   SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
 
@@ -1069,7 +1097,8 @@
 ///
 /// Note: this lets the caller parse the end ';'.
 ///
-Parser::OwningStmtResult Parser::ParseContinueStatement() {
+Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
   return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
 }
@@ -1080,7 +1109,8 @@
 ///
 /// Note: this lets the caller parse the end ';'.
 ///
-Parser::OwningStmtResult Parser::ParseBreakStatement() {
+Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
   return Actions.ActOnBreakStmt(BreakLoc, CurScope);
 }
@@ -1088,7 +1118,8 @@
 /// ParseReturnStatement
 ///       jump-statement:
 ///         'return' expression[opt] ';'
-Parser::OwningStmtResult Parser::ParseReturnStatement() {
+Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_return) && "Not a return stmt!");
   SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
 
@@ -1164,7 +1195,7 @@
   }
   DeclSpec DS;
   SourceLocation Loc = Tok.getLocation();
-  ParseTypeQualifierListOpt(DS);
+  ParseTypeQualifierListOpt(DS, true, false);
 
   // GNU asms accept, but warn, about type-qualifiers other than volatile.
   if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
@@ -1372,7 +1403,8 @@
 ///       try-block:
 ///         'try' compound-statement handler-seq
 ///
-Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
+Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+  // FIXME: Add attributes?
   assert(Tok.is(tok::kw_try) && "Expected 'try'");
 
   SourceLocation TryLoc = ConsumeToken();
@@ -1394,11 +1426,17 @@
 Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
   if (Tok.isNot(tok::l_brace))
     return StmtError(Diag(Tok, diag::err_expected_lbrace));
-  OwningStmtResult TryBlock(ParseCompoundStatement());
+  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+  OwningStmtResult TryBlock(ParseCompoundStatement(0));
   if (TryBlock.isInvalid())
     return move(TryBlock);
 
   StmtVector Handlers(Actions);
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
+  }
   if (Tok.isNot(tok::kw_catch))
     return StmtError(Diag(Tok, diag::err_expected_catch));
   while (Tok.is(tok::kw_catch)) {
@@ -1458,7 +1496,8 @@
   if (Tok.isNot(tok::l_brace))
     return StmtError(Diag(Tok, diag::err_expected_lbrace));
 
-  OwningStmtResult Block(ParseCompoundStatement());
+  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+  OwningStmtResult Block(ParseCompoundStatement(0));
   if (Block.isInvalid())
     return move(Block);
 

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Sat Nov 21 02:43:09 2009
@@ -192,6 +192,10 @@
 
   // Parse the declaration specifiers.
   ParsingDeclSpec DS(*this);
+
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    DS.AddAttributes(ParseCXX0XAttributes().AttrList);
+
   ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
 
   if (Tok.is(tok::semi)) {

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Sat Nov 21 02:43:09 2009
@@ -55,12 +55,11 @@
     // using-declaration
     // using-directive
   case tok::kw_using:
-    return true;
-  case tok::kw_static_assert:
     // static_assert-declaration
+  case tok::kw_static_assert:
     return true;
-  default:
     // simple-declaration
+  default:
     return isCXXSimpleDeclaration();
   }
 }
@@ -351,6 +350,89 @@
   return TPR == TPResult::True();
 }
 
+/// isCXX0XAttributeSpecifier - returns true if this is a C++0x
+/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
+/// performed that will simply return true if a [[ is seen. Currently C++ has no
+/// syntactical ambiguities from this check, but it may inhibit error recovery.
+/// If CheckClosing is true, a check is made for closing ]] brackets.
+///
+/// If given, After is set to the token after the attribute-specifier so that
+/// appropriate parsing decisions can be made; it is left untouched if false is
+/// returned.
+///
+/// FIXME: If an error is in the closing ]] brackets, the program assumes
+/// the absence of an attribute-specifier, which can cause very yucky errors
+/// to occur.
+///
+/// [C++0x] attribute-specifier:
+///         '[' '[' attribute-list ']' ']'
+///
+/// [C++0x] attribute-list:
+///         attribute[opt]
+///         attribute-list ',' attribute[opt]
+///
+/// [C++0x] attribute:
+///         attribute-token attribute-argument-clause[opt]
+///
+/// [C++0x] attribute-token:
+///         identifier
+///         attribute-scoped-token
+///
+/// [C++0x] attribute-scoped-token:
+///         attribute-namespace '::' identifier
+///
+/// [C++0x] attribute-namespace:
+///         identifier
+///
+/// [C++0x] attribute-argument-clause:
+///         '(' balanced-token-seq ')'
+///
+/// [C++0x] balanced-token-seq:
+///         balanced-token
+///         balanced-token-seq balanced-token
+///
+/// [C++0x] balanced-token:
+///         '(' balanced-token-seq ')'
+///         '[' balanced-token-seq ']'
+///         '{' balanced-token-seq '}'
+///         any token but '(', ')', '[', ']', '{', or '}'
+bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
+                                        tok::TokenKind *After) {
+  if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
+    return false;
+  
+  // No tentative parsing if we don't need to look for ]]
+  if (!CheckClosing && !getLang().ObjC1)
+    return true;
+  
+  struct TentativeReverter {
+    TentativeParsingAction PA;
+
+    TentativeReverter (Parser& P)
+      : PA(P)
+    {}
+    ~TentativeReverter () {
+      PA.Revert();
+    }
+  } R(*this);
+
+  // Opening brackets were checked for above.
+  ConsumeBracket();
+  ConsumeBracket();
+
+  // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
+  SkipUntil(tok::r_square, false);
+
+  if (Tok.isNot(tok::r_square))
+    return false;
+  ConsumeBracket();
+
+  if (After)
+    *After = Tok.getKind();
+
+  return true;
+}
+
 ///         declarator:
 ///           direct-declarator
 ///           ptr-operator declarator

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sat Nov 21 02:43:09 2009
@@ -355,7 +355,10 @@
     return true;
   }
 
-  Result = ParseExternalDeclaration();
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    Attr = ParseCXX0XAttributes();
+  Result = ParseExternalDeclaration(Attr);
   return false;
 }
 
@@ -396,7 +399,7 @@
 ///           ';'
 ///
 /// [C++0x/GNU] 'extern' 'template' declaration
-Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) {
   DeclPtrTy SingleDecl;
   switch (Tok.getKind()) {
   case tok::semi:
@@ -418,9 +421,13 @@
     // __extension__ silences extension warnings in the subexpression.
     ExtensionRAIIObject O(Diags);  // Use RAII to do this.
     ConsumeToken();
-    return ParseExternalDeclaration();
+    return ParseExternalDeclaration(Attr);
   }
   case tok::kw_asm: {
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
+
     OwningExprResult Result(ParseSimpleAsm());
 
     ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
@@ -449,7 +456,7 @@
   case tok::code_completion:
     Actions.CodeCompleteOrdinaryName(CurScope);
     ConsumeToken();
-    return ParseExternalDeclaration();
+    return ParseExternalDeclaration(Attr);
   case tok::kw_using:
   case tok::kw_namespace:
   case tok::kw_typedef:
@@ -459,7 +466,7 @@
     // A function definition cannot start with a these keywords.
     {
       SourceLocation DeclEnd;
-      return ParseDeclaration(Declarator::FileContext, DeclEnd);
+      return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
     }
   case tok::kw_extern:
     if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
@@ -477,7 +484,7 @@
 
   default:
     // We can't tell whether this is a function-definition or declaration yet.
-    return ParseDeclarationOrFunctionDefinition();
+    return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
   }
 
   // This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -525,9 +532,13 @@
 /// [OMP]   threadprivate-directive                              [TODO]
 ///
 Parser::DeclGroupPtrTy
-Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
+Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
+                                             AccessSpecifier AS) {
   // Parse the common declaration-specifiers piece.
   ParsingDeclSpec DS(*this);
+  if (Attr)
+    DS.AddAttributes(Attr);
+
   ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -719,7 +730,7 @@
       // If attributes are present, parse them.
       if (Tok.is(tok::kw___attribute))
         // FIXME: attach attributes too.
-        AttrList = ParseAttributes();
+        AttrList = ParseGNUAttributes();
 
       // Ask the actions module to compute the type for this declarator.
       Action::DeclPtrTy Param =

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Nov 21 02:43:09 2009
@@ -2149,6 +2149,11 @@
   bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
                                             const CXXMethodDecl *Old);
 
+  /// CheckOverridingFunctionAttributes - Checks whether attributes are
+  /// incompatible or prevent overriding.
+  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
+
   //===--------------------------------------------------------------------===//
   // C++ Access Control
   //

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Nov 21 02:43:09 2009
@@ -2613,7 +2613,8 @@
          E = Paths.found_decls_end(); I != E; ++I) {
       if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
         if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
-            !CheckOverridingFunctionExceptionSpec(MD, OldMD))
+            !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
+            !CheckOverridingFunctionAttributes(MD, OldMD))
           MD->addOverriddenMethod(OldMD);
       }
     }
@@ -2883,7 +2884,6 @@
     NewFD->setAccess(AS_public);
   }
 
-
   if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
     AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD);
 

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Sat Nov 21 02:43:09 2009
@@ -464,7 +464,9 @@
   if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
     ValueDecl *VD = dyn_cast<ValueDecl>(d);
     if (VD == 0 || !VD->getType()->isBlockPointerType()) {
-      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      S.Diag(Attr.getLoc(),
+             Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                     : diag::warn_attribute_wrong_decl_type)
         << Attr.getName() << 0 /*function*/;
       return false;
     }
@@ -484,6 +486,15 @@
     d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
 }
 
+static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << Attr.getName() << 8; /*function, method, or parameter*/
+    return;
+  }
+  // FIXME: Actually store the attribute on the declaration
+}
+
 static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // check the attribute arguments.
   if (Attr.getNumArgs() != 0) {
@@ -1516,6 +1527,10 @@
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     return;
   }
+  
+  //FIXME: The C++0x version of this attribute has more limited applicabilty
+  //       than GNU's, and should error out when it is used to specify a
+  //       weaker alignment, rather than being silently ignored.
 
   unsigned Align = 0;
   if (Attr.getNumArgs() == 0) {
@@ -1794,6 +1809,29 @@
   d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
 }
 
+static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  if (!isa<CXXRecordDecl>(d)
+   && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual())) {
+    S.Diag(Attr.getLoc(),
+           Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
+                                   : diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 7 /*virtual method or class*/;
+    return;
+  }
+
+  // FIXME: Check that it's not specified more than once in an attribute-
+  //        specifier and that it conforms to the C++0x rules for
+  //        redeclarations.
+
+  d->addAttr(::new (S.Context) FinalAttr());
+}
+
 //===----------------------------------------------------------------------===//
 // Checker-specific attribute handlers.
 //===----------------------------------------------------------------------===//
@@ -1841,7 +1879,8 @@
 
 /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
 /// the attribute applies to decls.  If the attribute is a type attribute, just
-/// silently ignore it.
+/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
+/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
 static void ProcessDeclAttribute(Scope *scope, Decl *D,
                                  const AttributeList &Attr, Sema &S) {
   if (Attr.isDeclspecAttribute())
@@ -1861,6 +1900,8 @@
   case AttributeList::AT_analyzer_noreturn:
     HandleAnalyzerNoReturnAttr  (D, Attr, S); break;
   case AttributeList::AT_annotate:    HandleAnnotateAttr  (D, Attr, S); break;
+  case AttributeList::AT_carries_dependency:
+                                      HandleDependencyAttr (D, Attr, S); break;
   case AttributeList::AT_cdecl:       HandleCDeclAttr     (D, Attr, S); break;
   case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break;
   case AttributeList::AT_deprecated:  HandleDeprecatedAttr(D, Attr, S); break;
@@ -1871,9 +1912,10 @@
     HandleExtVectorTypeAttr(scope, D, Attr, S);
     break;
   case AttributeList::AT_fastcall:    HandleFastCallAttr  (D, Attr, S); break;
+  case AttributeList::AT_final:       HandleFinalAttr     (D, Attr, S); break;
   case AttributeList::AT_format:      HandleFormatAttr    (D, Attr, S); break;
   case AttributeList::AT_format_arg:  HandleFormatArgAttr (D, Attr, S); break;
-  case AttributeList::AT_gnu_inline:  HandleGNUInlineAttr(D, Attr, S); break;
+  case AttributeList::AT_gnu_inline:  HandleGNUInlineAttr (D, Attr, S); break;
   case AttributeList::AT_mode:        HandleModeAttr      (D, Attr, S); break;
   case AttributeList::AT_malloc:      HandleMallocAttr    (D, Attr, S); break;
   case AttributeList::AT_nonnull:     HandleNonNullAttr   (D, Attr, S); break;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=89543&r1=89542&r2=89543&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Nov 21 02:43:09 2009
@@ -489,6 +489,13 @@
     Class->setEmpty(false);
   if (CXXBaseDecl->isPolymorphic())
     Class->setPolymorphic(true);
+  // C++0x CWG Issue #817 indicates that [[final]] classes shouldn't be bases.
+  if (CXXBaseDecl->hasAttr<FinalAttr>()) {
+    Diag(BaseLoc, diag::err_final_base) << BaseType.getAsString();
+    Diag(CXXBaseDecl->getLocation(), diag::note_previous_class_decl)
+      << BaseType.getAsString();
+    return 0;
+  }
 
   // C++ [dcl.init.aggr]p1:
   //   An aggregate is [...] a class with [...] no base classes [...].
@@ -4896,6 +4903,19 @@
   return false;
 }
 
+bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+                                             const CXXMethodDecl *Old)
+{
+  if (Old->hasAttr<FinalAttr>()) {
+    Diag(New->getLocation(), diag::err_final_function_overridden)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  }
+
+  return false;
+}
+
 /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
 /// initializer for the declaration 'Dcl'.
 /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a

Added: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=89543&view=auto

==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (added)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Sat Nov 21 02:43:09 2009
@@ -0,0 +1,61 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
+// Declaration syntax checks
+[[]] int before_attr;
+int after_attr [[]];
+int * [[]] ptr_attr;
+int array_attr [1] [[]];
+[[align(8)]] int aligned_attr;
+[[test::valid(for 42 [very] **** '+' symbols went on a trip; the end.)]]
+  int garbage_attr;
+void fn_attr () [[]];
+class [[]] class_attr {};
+extern "C++" [[]] int extern_attr;
+template <typename T> [[]] void template_attr ();
+
+int comma_attr [[,]]; // expected-error {{expected identifier}}
+int scope_attr [[foo::]]; // expected-error {{expected identifier}}
+int & [[]] ref_attr = after_attr; // expected-error {{an attribute list cannot appear here}}
+class foo {
+  void after_const_attr () const [[]]; // expected-error {{expected expression}}
+};
+extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
+[[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}
+[[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}}
+[[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}}
+[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
+
+[[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
+[[]] using namespace ns;
+
+// Argument tests
+[[final()]] int final_params; // expected-error {{C++0x attribute 'final' cannot have an argument list}}
+[[align]] int aligned_no_params; // expected-error {{C++0x attribute 'align' must have an argument list}}
+[[align(i)]] int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}}
+
+// Statement tests
+void foo () {
+  [[]] ;
+  [[]] { }
+  [[]] if (0) { }
+  [[]] for (;;);
+  [[]] do {
+    [[]] continue;
+  } while (0);
+  [[]] while (0);
+  
+  [[]] switch (i) {
+    [[]] case 0:
+    [[]] default:
+      [[]] break;
+  }
+  
+  [[]] goto there;
+  [[]] there:
+  
+  [[]] try {
+  } [[]] catch (...) { // expected-error {{an attribute list cannot appear here}}
+  }
+  
+  [[]] return;
+}

Added: cfe/trunk/test/SemaCXX/attr-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-cxx0x.cpp?rev=89543&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/attr-cxx0x.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-cxx0x.cpp Sat Nov 21 02:43:09 2009
@@ -0,0 +1,24 @@
+// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
+
+int final_fail [[final]]; //expected-error {{'final' attribute only applies to virtual method or class types}}
+
+struct [[final]] final_base { }; // expected-note {{struct final_base declared here}}
+struct final_child : final_base { }; // expected-error {{derivation from 'final' struct final_base}}
+
+struct final_member { virtual void quux [[final]] (); }; // expected-note {{overridden virtual function is here}}
+struct final_override : final_member { virtual void quux (); }; // expected-error {{declaration of 'quux' overrides a 'final' function}}
+
+int align_illegal [[align(3)]]; //expected-error {{requested alignment is not a power of 2}}
+char align_big [[align(int)]];
+int align_small [[align(1)]];
+int align_multiple [[align(1), align(8), align(1)]];
+
+struct align_member {
+  int member [[align(8)]];
+};
+
+static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong");
+static_assert(alignof(align_small) == alignof(int), "j's alignment is wrong");
+static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
+static_assert(alignof(align_member) == 8, "quuux's alignment is wrong");
+static_assert(sizeof(align_member) == 8, "quuux's size is wrong");





More information about the cfe-commits mailing list