diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7670316b9d7d..5e790e2da63c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -882,6 +882,7 @@ public: 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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 35a35f33b5c9..9e430a42968f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2124,6 +2124,11 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { IdentifierInfo *Ident = Tok.getIdentifierInfo(); SourceLocation IdentLoc = ConsumeToken(); + // If attributes exist after the enumerator, parse them. + llvm::OwningPtr Attr; + if (Tok.is(tok::kw___attribute)) + Attr.reset(ParseGNUAttributes()); + SourceLocation EqualLoc; ExprResult AssignedVal; if (Tok.is(tok::equal)) { @@ -2137,7 +2142,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - EqualLoc, + Attr.get(), EqualLoc, AssignedVal.release()); EnumConstantDecls.push_back(EnumConstDecl); LastEnumConstDecl = EnumConstDecl; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f1045d3c0b7a..de3a4f963fb1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7229,11 +7229,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, } -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(theEnumDecl); EnumConstantDecl *LastEnumConst = cast_or_null(lastEnumConst); @@ -7280,11 +7279,14 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, 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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index ce69b64f1652..6a713d792667 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -619,6 +619,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } } + SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); + Enum->setInstantiationOfMemberEnum(D); Enum->setAccess(D->getAccess()); if (SubstQualifier(D, Enum)) return 0; @@ -663,6 +665,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } if (EnumConst) { + SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst); + EnumConst->setAccess(Enum->getAccess()); Enum->addDecl(EnumConst); Enumerators.push_back(EnumConst); diff --git a/clang/test/Sema/attr-deprecated.c b/clang/test/Sema/attr-deprecated.c index e7c997f3ee23..f9cdaf067c67 100644 --- a/clang/test/Sema/attr-deprecated.c +++ b/clang/test/Sema/attr-deprecated.c @@ -98,3 +98,14 @@ unsigned long test16 __attribute__((deprecated)) 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/clang/test/SemaCXX/attr-deprecated.cpp b/clang/test/SemaCXX/attr-deprecated.cpp index 2164f9dd17f2..fe7c833d322b 100644 --- a/clang/test/SemaCXX/attr-deprecated.cpp +++ b/clang/test/SemaCXX/attr-deprecated.cpp @@ -190,3 +190,46 @@ namespace test5 { {} }; } + +// 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 struct C { + enum __attribute__((deprecated)) Enum { + c0 + }; + }; + void testC() { + C::Enum x; // expected-warning {{'Enum' is deprecated}} + x = C::c0; + } + + template struct D { + enum Enum { + d0, + d1 __attribute__((deprecated)), + }; + }; + void testD() { + D::Enum x; + x = D::d0; + x = D::d1; // expected-warning {{'d1' is deprecated}} + } +}