Parse attributes on enumerators and instantiate attributes on enum decls.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117182 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 7670316..5e790e2 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -882,6 +882,7 @@
 
   Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
                           SourceLocation IdLoc, IdentifierInfo *Id,
+                          AttributeList *Attrs,
                           SourceLocation EqualLoc, Expr *Val);
   void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
                      SourceLocation RBraceLoc, Decl *EnumDecl,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 35a35f3..9e430a4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2124,6 +2124,11 @@
     IdentifierInfo *Ident = Tok.getIdentifierInfo();
     SourceLocation IdentLoc = ConsumeToken();
 
+    // If attributes exist after the enumerator, parse them.
+    llvm::OwningPtr<AttributeList> Attr;
+    if (Tok.is(tok::kw___attribute))
+      Attr.reset(ParseGNUAttributes());
+
     SourceLocation EqualLoc;
     ExprResult AssignedVal;
     if (Tok.is(tok::equal)) {
@@ -2137,7 +2142,7 @@
     Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
                                                     LastEnumConstDecl,
                                                     IdentLoc, Ident,
-                                                    EqualLoc,
+                                                    Attr.get(), EqualLoc,
                                                     AssignedVal.release());
     EnumConstantDecls.push_back(EnumConstDecl);
     LastEnumConstDecl = EnumConstDecl;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f1045d3..de3a4f9 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7229,11 +7229,10 @@
 }
 
 
-Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl,
-                                        Decl *lastEnumConst,
-                                        SourceLocation IdLoc,
-                                        IdentifierInfo *Id,
-                                        SourceLocation EqualLoc, ExprTy *val) {
+Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
+                              SourceLocation IdLoc, IdentifierInfo *Id,
+                              AttributeList *Attr,
+                              SourceLocation EqualLoc, ExprTy *val) {
   EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
   EnumConstantDecl *LastEnumConst =
     cast_or_null<EnumConstantDecl>(lastEnumConst);
@@ -7280,11 +7279,14 @@
     if (Record->getIdentifier() && Record->getIdentifier() == Id)
       Diag(IdLoc, diag::err_member_name_of_class) << Id;
   
-  EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst,
-                                            IdLoc, Id, Val);
+  EnumConstantDecl *New =
+    CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
 
-  // Register this decl in the current scope stack.
   if (New) {
+    // Process attributes.
+    if (Attr) ProcessDeclAttributeList(S, New, Attr);
+
+    // Register this decl in the current scope stack.
     New->setAccess(TheEnumDecl->getAccess());
     PushOnScopeChains(New, S);
   }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ce69b64..6a713d7 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -619,6 +619,8 @@
     }
   }
 
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Enum);
+
   Enum->setInstantiationOfMemberEnum(D);
   Enum->setAccess(D->getAccess());
   if (SubstQualifier(D, Enum)) return 0;
@@ -663,6 +665,8 @@
     }
 
     if (EnumConst) {
+      SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst);
+
       EnumConst->setAccess(Enum->getAccess());
       Enum->addDecl(EnumConst);
       Enumerators.push_back(EnumConst);
diff --git a/test/Sema/attr-deprecated.c b/test/Sema/attr-deprecated.c
index e7c997f..f9cdaf0 100644
--- a/test/Sema/attr-deprecated.c
+++ b/test/Sema/attr-deprecated.c
@@ -98,3 +98,14 @@
 foo_dep test17, // expected-warning {{'foo_dep' is deprecated}}
         test18 __attribute__((deprecated)),
         test19;
+
+// rdar://problem/8518751
+enum __attribute__((deprecated)) Test20 {
+  test20_a __attribute__((deprecated)),
+  test20_b
+};
+void test20() {
+  enum Test20 f; // expected-warning {{'Test20' is deprecated}}
+  f = test20_a; // expected-warning {{'test20_a' is deprecated}}
+  f = test20_b;
+}
diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp
index 2164f9d..fe7c833 100644
--- a/test/SemaCXX/attr-deprecated.cpp
+++ b/test/SemaCXX/attr-deprecated.cpp
@@ -190,3 +190,46 @@
     {}
   };
 }
+
+// rdar://problem/8518751
+namespace test6 {
+  enum __attribute__((deprecated)) A {
+    a0
+  };
+  void testA() {
+    A x; // expected-warning {{'A' is deprecated}}
+    x = a0;
+  }
+  
+  enum B {
+    b0 __attribute__((deprecated)),
+    b1
+  };
+  void testB() {
+    B x;
+    x = b0; // expected-warning {{'b0' is deprecated}}
+    x = b1;
+  }
+
+  template <class T> struct C {
+    enum __attribute__((deprecated)) Enum {
+      c0
+    };
+  };
+  void testC() {
+    C<int>::Enum x; // expected-warning {{'Enum' is deprecated}}
+    x = C<int>::c0;
+  }
+
+  template <class T> struct D {
+    enum Enum {
+      d0,
+      d1 __attribute__((deprecated)),
+    };
+  };
+  void testD() {
+    D<int>::Enum x;
+    x = D<int>::d0;
+    x = D<int>::d1; // expected-warning {{'d1' is deprecated}}
+  }
+}