]> granicus.if.org Git - clang/commitdiff
Handle deprecation diagnostics correctly for C struct fields and Objective-C properti...
authorEli Friedman <eli.friedman@gmail.com>
Wed, 8 Aug 2012 23:04:35 +0000 (23:04 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 8 Aug 2012 23:04:35 +0000 (23:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161534 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
include/clang/Sema/DeclSpec.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/RAIIObjectsForParser.h
test/Sema/attr-deprecated.c
test/SemaObjC/attr-deprecated.m

index e874e382ced5d738a1089202ec0157777eb9a90e..f02abc60fdf1ca34f60425d8e2a4c257696b2274 100644 (file)
@@ -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();
index 48f7d80167ba2a37248c27ed75c719d272343987..792b0c643d8d521fde7c2b322cddfe6b9d96daf1 100644 (file)
@@ -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.
index 328345413f2b1cd9b1a81ff2283efcfe867af4bc..5cb03632c3aae1433baa15d5a5baa7c884dff53a 100644 (file)
@@ -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();
index 5872e1dc8a227806ee20575bfd043c7cf6a4f31b..ec1dbad688a308597db87fccf0f650fdbc16efac 100644 (file)
@@ -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)) {
index e13c4cfeb31574c3f568cb3dd45e216ac1353d2f..455c4af2ffaec0baa3a2320f955be346f0959b28 100644 (file)
@@ -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
index 7984d566317de7a647d700cd0483906501a35b78..565be7ff59975fb99f5c8817722f56ba60c81cec 100644 (file)
@@ -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;
+};
index d6a56e53c071a63a34367af43379115d8e63050a..260462abc0b8719625d1d823d20e8c375ebd261e 100644 (file)
@@ -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