summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-08-08 23:04:35 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-08-08 23:04:35 +0000
commit89b1f2c7e101f2263b35d0ea5013ed7a39015b26 (patch)
tree02fc081479f7a7f5e0b4e6daa3756d6ca7c5ef9c
parentfcde4fad2beacb271a9fcf921daba93c5bd06919 (diff)
downloadbcm5719-llvm-89b1f2c7e101f2263b35d0ea5013ed7a39015b26.tar.gz
bcm5719-llvm-89b1f2c7e101f2263b35d0ea5013ed7a39015b26.zip
Handle deprecation diagnostics correctly for C struct fields and Objective-C properties/ivars. <rdar://problem/6642337>.
llvm-svn: 161534
-rw-r--r--clang/include/clang/Parse/Parser.h5
-rw-r--r--clang/include/clang/Sema/DeclSpec.h5
-rw-r--r--clang/lib/Parse/ParseDecl.cpp17
-rw-r--r--clang/lib/Parse/ParseObjc.cpp10
-rw-r--r--clang/lib/Parse/RAIIObjectsForParser.h22
-rw-r--r--clang/test/Sema/attr-deprecated.c9
-rw-r--r--clang/test/SemaObjC/attr-deprecated.m13
7 files changed, 63 insertions, 18 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index e874e382ced..f02abc60fdf 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/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/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 48f7d80167b..792b0c643d8 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 328345413f2..5cb03632c3a 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/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/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 5872e1dc8a2..ec1dbad688a 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/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/clang/lib/Parse/RAIIObjectsForParser.h b/clang/lib/Parse/RAIIObjectsForParser.h
index e13c4cfeb31..455c4af2ffa 100644
--- a/clang/lib/Parse/RAIIObjectsForParser.h
+++ b/clang/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/clang/test/Sema/attr-deprecated.c b/clang/test/Sema/attr-deprecated.c
index 7984d566317..565be7ff599 100644
--- a/clang/test/Sema/attr-deprecated.c
+++ b/clang/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/clang/test/SemaObjC/attr-deprecated.m b/clang/test/SemaObjC/attr-deprecated.m
index d6a56e53c07..260462abc0b 100644
--- a/clang/test/SemaObjC/attr-deprecated.m
+++ b/clang/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
OpenPOWER on IntegriCloud