diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-08-08 23:04:35 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-08-08 23:04:35 +0000 |
commit | f66a0dda541cd859a928193efba6dc5d7ba8fe54 (patch) | |
tree | df2d36115fb8c411de5b5c4a37772e282722a33d | |
parent | 6cd4420945489e7331012103048f162288a6c7d8 (diff) |
Handle deprecation diagnostics correctly for C struct fields and Objective-C properties/ivars. <rdar://problem/6642337>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161534 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 5 | ||||
-rw-r--r-- | include/clang/Sema/DeclSpec.h | 5 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 17 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 10 | ||||
-rw-r--r-- | lib/Parse/RAIIObjectsForParser.h | 22 | ||||
-rw-r--r-- | test/Sema/attr-deprecated.c | 9 | ||||
-rw-r--r-- | test/SemaObjC/attr-deprecated.m | 13 |
7 files changed, 63 insertions, 18 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e874e382ce..f02abc60fd 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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(); diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 48f7d80167..792b0c643d 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -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. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 328345413f..5cb03632c3 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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(); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 5872e1dc8a..ec1dbad688 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -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)) { diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h index e13c4cfeb3..455c4af2ff 100644 --- a/lib/Parse/RAIIObjectsForParser.h +++ b/lib/Parse/RAIIObjectsForParser.h @@ -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 diff --git a/test/Sema/attr-deprecated.c b/test/Sema/attr-deprecated.c index 7984d56631..565be7ff59 100644 --- a/test/Sema/attr-deprecated.c +++ b/test/Sema/attr-deprecated.c @@ -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; +}; diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m index d6a56e53c0..260462abc0 100644 --- a/test/SemaObjC/attr-deprecated.m +++ b/test/SemaObjC/attr-deprecated.m @@ -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 |