Parse attributes on enumerators and instantiate attributes on enum decls.

llvm-svn: 117182
This commit is contained in:
John McCall 2010-10-22 23:36:17 +00:00
parent 21836f726b
commit 811a0f5578
6 changed files with 75 additions and 9 deletions

View File

@ -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,

View File

@ -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<AttributeList> 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;

View File

@ -7229,10 +7229,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
}
Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl,
Decl *lastEnumConst,
SourceLocation IdLoc,
IdentifierInfo *Id,
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 =
@ -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);
if (New) {
// Process attributes.
if (Attr) ProcessDeclAttributeList(S, New, Attr);
// Register this decl in the current scope stack.
if (New) {
New->setAccess(TheEnumDecl->getAccess());
PushOnScopeChains(New, S);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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 <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}}
}
}