forked from OSchip/llvm-project
Handle deprecation diagnostics correctly for C struct fields and Objective-C properties/ivars. <rdar://problem/6642337>.
llvm-svn: 161534
This commit is contained in:
parent
fcde4fad2b
commit
89b1f2c7e1
|
@ -36,6 +36,7 @@ namespace clang {
|
|||
class ParsingDeclRAIIObject;
|
||||
class ParsingDeclSpec;
|
||||
class ParsingDeclarator;
|
||||
class ParsingFieldDeclarator;
|
||||
class PragmaUnusedHandler;
|
||||
class ColonProtectionRAIIObject;
|
||||
class InMessageExpressionRAIIObject;
|
||||
|
@ -1559,7 +1560,7 @@ private:
|
|||
Decl *TagDecl);
|
||||
|
||||
struct FieldCallback {
|
||||
virtual Decl *invoke(FieldDeclarator &Field) = 0;
|
||||
virtual Decl *invoke(ParsingFieldDeclarator &Field) = 0;
|
||||
virtual ~FieldCallback() {}
|
||||
|
||||
private:
|
||||
|
@ -1567,7 +1568,7 @@ private:
|
|||
};
|
||||
struct ObjCPropertyCallback;
|
||||
|
||||
void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
|
||||
void ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Callback);
|
||||
|
||||
bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
|
||||
bool isTypeSpecifierQualifier();
|
||||
|
|
|
@ -1932,9 +1932,8 @@ public:
|
|||
struct FieldDeclarator {
|
||||
Declarator D;
|
||||
Expr *BitfieldSize;
|
||||
explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
|
||||
BitfieldSize = 0;
|
||||
}
|
||||
explicit FieldDeclarator(const DeclSpec &DS)
|
||||
: D(DS, Declarator::MemberContext), BitfieldSize(0) { }
|
||||
};
|
||||
|
||||
/// \brief Represents a C++11 virt-specifier-seq.
|
||||
|
|
|
@ -2773,7 +2773,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
|
||||
///
|
||||
void Parser::
|
||||
ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
|
||||
ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) {
|
||||
|
||||
if (Tok.is(tok::kw___extension__)) {
|
||||
// __extension__ silences extension warnings in the subexpression.
|
||||
|
@ -2788,7 +2788,9 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
|
|||
// If there are no declarators, this is a free-standing declaration
|
||||
// specifier. Let the actions module cope with it.
|
||||
if (Tok.is(tok::semi)) {
|
||||
Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, DS);
|
||||
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
|
||||
DS);
|
||||
DS.complete(TheDecl);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2796,8 +2798,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
|
|||
bool FirstDeclarator = true;
|
||||
SourceLocation CommaLoc;
|
||||
while (1) {
|
||||
ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
|
||||
FieldDeclarator DeclaratorInfo(DS);
|
||||
ParsingFieldDeclarator DeclaratorInfo(*this, DS);
|
||||
DeclaratorInfo.D.setCommaLoc(CommaLoc);
|
||||
|
||||
// Attributes are only allowed here on successive declarators.
|
||||
|
@ -2881,9 +2882,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
|||
continue;
|
||||
}
|
||||
|
||||
// Parse all the comma separated declarators.
|
||||
DeclSpec DS(AttrFactory);
|
||||
|
||||
if (!Tok.is(tok::at)) {
|
||||
struct CFieldCallback : FieldCallback {
|
||||
Parser &P;
|
||||
|
@ -2894,16 +2892,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
|||
SmallVectorImpl<Decl *> &FieldDecls) :
|
||||
P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
|
||||
|
||||
virtual Decl *invoke(FieldDeclarator &FD) {
|
||||
virtual Decl *invoke(ParsingFieldDeclarator &FD) {
|
||||
// Install the declarator into the current TagDecl.
|
||||
Decl *Field = P.Actions.ActOnField(P.getCurScope(), TagDecl,
|
||||
FD.D.getDeclSpec().getSourceRange().getBegin(),
|
||||
FD.D, FD.BitfieldSize);
|
||||
FieldDecls.push_back(Field);
|
||||
FD.complete(Field);
|
||||
return Field;
|
||||
}
|
||||
} Callback(*this, TagDecl, FieldDecls);
|
||||
|
||||
// Parse all the comma separated declarators.
|
||||
ParsingDeclSpec DS(*this);
|
||||
ParseStructDeclaration(DS, Callback);
|
||||
} else { // Handle @defs
|
||||
ConsumeToken();
|
||||
|
|
|
@ -308,7 +308,7 @@ public:
|
|||
MethodImplKind(MethodImplKind) {
|
||||
}
|
||||
|
||||
Decl *invoke(FieldDeclarator &FD) {
|
||||
Decl *invoke(ParsingFieldDeclarator &FD) {
|
||||
if (FD.D.getIdentifier() == 0) {
|
||||
P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
|
||||
<< FD.D.getSourceRange();
|
||||
|
@ -344,6 +344,7 @@ public:
|
|||
if (!isOverridingProperty)
|
||||
Props.push_back(Property);
|
||||
|
||||
FD.complete(Property);
|
||||
return Property;
|
||||
}
|
||||
};
|
||||
|
@ -493,7 +494,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
|
|||
OCDS, AtLoc, LParenLoc, MethodImplKind);
|
||||
|
||||
// Parse all the comma separated declarators.
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParsingDeclSpec DS(*this);
|
||||
ParseStructDeclaration(DS, Callback);
|
||||
|
||||
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
|
||||
|
@ -1306,7 +1307,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
|||
P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
|
||||
}
|
||||
|
||||
Decl *invoke(FieldDeclarator &FD) {
|
||||
Decl *invoke(ParsingFieldDeclarator &FD) {
|
||||
P.Actions.ActOnObjCContainerStartDefinition(IDecl);
|
||||
// Install the declarator into the interface decl.
|
||||
Decl *Field
|
||||
|
@ -1316,12 +1317,13 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
|
|||
P.Actions.ActOnObjCContainerFinishDefinition();
|
||||
if (Field)
|
||||
AllIvarDecls.push_back(Field);
|
||||
FD.complete(Field);
|
||||
return Field;
|
||||
}
|
||||
} Callback(*this, interfaceDecl, visibility, AllIvarDecls);
|
||||
|
||||
// Parse all the comma separated declarators.
|
||||
DeclSpec DS(AttrFactory);
|
||||
ParsingDeclSpec DS(*this);
|
||||
ParseStructDeclaration(DS, Callback);
|
||||
|
||||
if (Tok.is(tok::semi)) {
|
||||
|
|
|
@ -218,6 +218,28 @@ namespace clang {
|
|||
}
|
||||
};
|
||||
|
||||
/// A class for parsing a field declarator.
|
||||
class ParsingFieldDeclarator : public FieldDeclarator {
|
||||
ParsingDeclRAIIObject ParsingRAII;
|
||||
|
||||
public:
|
||||
ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS)
|
||||
: FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
|
||||
}
|
||||
|
||||
const ParsingDeclSpec &getDeclSpec() const {
|
||||
return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
|
||||
}
|
||||
|
||||
ParsingDeclSpec &getMutableDeclSpec() const {
|
||||
return const_cast<ParsingDeclSpec&>(getDeclSpec());
|
||||
}
|
||||
|
||||
void complete(Decl *D) {
|
||||
ParsingRAII.complete(D);
|
||||
}
|
||||
};
|
||||
|
||||
/// ExtensionRAIIObject - This saves the state of extension warnings when
|
||||
/// constructed and disables them. When destructed, it restores them back to
|
||||
/// the way they used to be. This is used to handle __extension__ in the
|
||||
|
|
|
@ -41,7 +41,7 @@ void test1(struct foo *F) {
|
|||
struct foo f2 = { 17 }; // expected-warning {{'x' is deprecated}}
|
||||
}
|
||||
|
||||
typedef struct foo foo_dep __attribute__((deprecated)); // expected-note 10 {{declared here}}
|
||||
typedef struct foo foo_dep __attribute__((deprecated)); // expected-note 12 {{declared here}}
|
||||
foo_dep *test2; // expected-warning {{'foo_dep' is deprecated}}
|
||||
|
||||
struct __attribute__((deprecated,
|
||||
|
@ -113,3 +113,10 @@ void test20() {
|
|||
}
|
||||
|
||||
char test21[__has_feature(attribute_deprecated_with_message) ? 1 : -1];
|
||||
|
||||
struct test22 {
|
||||
foo_dep a __attribute((deprecated));
|
||||
foo_dep b; // expected-warning {{'foo_dep' is deprecated}}
|
||||
foo_dep c, d __attribute((deprecated)); // expected-warning {{'foo_dep' is deprecated}}
|
||||
__attribute((deprecated)) foo_dep e, f;
|
||||
};
|
||||
|
|
|
@ -121,3 +121,16 @@ void test(Test2 *foo) {
|
|||
__attribute__((deprecated))
|
||||
@interface A(Blah) // expected-error{{attributes may not be specified on a category}}
|
||||
@end
|
||||
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
} footype __attribute((deprecated)); // expected-note 2 {{declared here}}
|
||||
|
||||
@interface foo {
|
||||
footype a; // expected-warning {{'footype' is deprecated}}
|
||||
footype b __attribute((deprecated));
|
||||
}
|
||||
@property footype c; // expected-warning {{'footype' is deprecated}}
|
||||
@property footype d __attribute((deprecated));
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue