From 9f4f5f1ca1e1967daf64d5422717c9b1e75eeb9e Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 3 Apr 2013 17:36:11 +0000 Subject: Emit a nicer diagnostic for misplaced attributes on ObjC directives. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178670 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticParseKinds.td | 2 ++ include/clang/Parse/Parser.h | 1 + lib/Parse/ParseObjc.cpp | 15 +++++++++++++++ test/Parser/attributes.mm | 25 +++++++++++++++++++++++++ test/Parser/prefix-attributes.m | 8 -------- 5 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 test/Parser/attributes.mm delete mode 100644 test/Parser/prefix-attributes.m diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index d0bddae1e0..26820dbddf 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -399,6 +399,8 @@ def err_objc_properties_require_objc2 : Error< "properties are an Objective-C 2 feature">; def err_objc_unexpected_attr : Error< "prefix attribute must be followed by an interface or protocol">; +def err_objc_postfix_attribute : Error < + "postfix attributes are not allowed on Objective-C directives">; def err_objc_directive_only_in_protocol : Error< "directive may only be specified in protocols only">; def err_missing_catch_finally : Error< diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 11a3bdbd50..7ff6f96ff9 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1113,6 +1113,7 @@ private: ExprResult ParseAsmStringLiteral(); // Objective-C External Declarations + void MaybeSkipAttributes(); DeclGroupPtrTy ParseObjCAtDirectives(); DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index fb0237ac05..844a3d12e9 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -22,6 +22,14 @@ #include "llvm/ADT/StringExtras.h" using namespace clang; +/// Skips attributes after an Objective-C @ directive. Emits a diagnostic. +void Parser::MaybeSkipAttributes() { + ParsedAttributes attrs(AttrFactory); + if (Tok.is(tok::kw___attribute)) { + Diag(Tok, diag::err_objc_postfix_attribute); + ParseGNUAttributes(attrs); + } +} /// ParseObjCAtDirectives - Handle parts of the external-declaration production: /// external-declaration: [C99 6.9] @@ -93,6 +101,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { while (1) { + MaybeSkipAttributes(); if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); SkipUntil(tok::semi); @@ -179,6 +188,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, return 0; } + MaybeSkipAttributes(); + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing class or category name. return 0; @@ -1397,6 +1408,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, return DeclGroupPtrTy(); } + MaybeSkipAttributes(); + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing protocol name. return DeclGroupPtrTy(); @@ -1488,6 +1501,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { return DeclGroupPtrTy(); } + MaybeSkipAttributes(); + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing class or category name. return DeclGroupPtrTy(); diff --git a/test/Parser/attributes.mm b/test/Parser/attributes.mm new file mode 100644 index 0000000000..812d543e3e --- /dev/null +++ b/test/Parser/attributes.mm @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wno-objc-root-class %s + +__attribute__((deprecated)) @class B; // expected-error {{prefix attribute must be followed by an interface or protocol}} + +__attribute__((deprecated)) @interface A @end +__attribute__((deprecated)) @protocol P0; +__attribute__((deprecated)) @protocol P1 +@end + +#define EXP __attribute__((visibility("default"))) +class EXP C {}; +EXP class C2 {}; // expected-warning {{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} + +@interface EXP I @end // expected-error {{postfix attributes are not allowed on Objective-C directives}} +EXP @interface I2 @end + +@implementation EXP I @end // expected-error {{postfix attributes are not allowed on Objective-C directives}} +// FIXME: Prefix attribute recovery skips until ';' +EXP @implementation I2 @end; // expected-error{{prefix attribute must be followed by an interface or protocol}} + +@class EXP OC; // expected-error {{postfix attributes are not allowed on Objective-C directives}} +EXP @class OC2; // expected-error {{prefix attribute must be followed by an interface or protocol}} + +@protocol EXP P @end // expected-error {{postfix attributes are not allowed on Objective-C directives}} +EXP @protocol P2 @end diff --git a/test/Parser/prefix-attributes.m b/test/Parser/prefix-attributes.m deleted file mode 100644 index 399421fd72..0000000000 --- a/test/Parser/prefix-attributes.m +++ /dev/null @@ -1,8 +0,0 @@ -// RUN: %clang_cc1 -verify -fsyntax-only %s - -__attribute__((deprecated)) @class B; // expected-error {{prefix attribute must be followed by an interface or protocol}} - -__attribute__((deprecated)) @interface A @end -__attribute__((deprecated)) @protocol P0; -__attribute__((deprecated)) @protocol P1 -@end -- cgit v1.2.3-18-g5258