From dc011c9015ff0d9465ba7e807c6e6d76eefe9aad Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 12 Feb 2018 13:38:25 +0000 Subject: [PATCH] Allow the NS, CF, and ObjC attributes to be used with -fdouble-square-bracket-attributes. The syntactic locations for such attributes on ObjC constructs have been specifically chosen to follow the GNU attribute syntactic locations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324890 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Attr.td | 68 ++++++++++++++++++------------------ include/clang/Parse/Parser.h | 2 +- lib/Parse/ParseObjc.cpp | 27 +++++++------- lib/Parse/Parser.cpp | 2 +- test/Misc/ast-dump-attr.m | 57 ++++++++++++++++++++++++++++++ test/Parser/objc-attr.m | 28 +++++++++++++++ 6 files changed, 134 insertions(+), 50 deletions(-) create mode 100644 test/Misc/ast-dump-attr.m create mode 100644 test/Parser/objc-attr.m diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 651132a86d..c3a4d4b058 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -754,7 +754,7 @@ def CDecl : InheritableAttr { // cf_returns_retained attributes. It is generally applied by // '#pragma clang arc_cf_code_audited' rather than explicitly. def CFAuditedTransfer : InheritableAttr { - let Spellings = [Clang<"cf_audited_transfer">]; + let Spellings = [Clang<"cf_audited_transfer", 1>]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } @@ -763,25 +763,25 @@ def CFAuditedTransfer : InheritableAttr { // It indicates that the function has unknown or unautomatable // transfer semantics. def CFUnknownTransfer : InheritableAttr { - let Spellings = [Clang<"cf_unknown_transfer">]; + let Spellings = [Clang<"cf_unknown_transfer", 1>]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } def CFReturnsRetained : InheritableAttr { - let Spellings = [Clang<"cf_returns_retained">]; + let Spellings = [Clang<"cf_returns_retained", 1>]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def CFReturnsNotRetained : InheritableAttr { - let Spellings = [Clang<"cf_returns_not_retained">]; + let Spellings = [Clang<"cf_returns_not_retained", 1>]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def CFConsumed : InheritableParamAttr { - let Spellings = [Clang<"cf_consumed">]; + let Spellings = [Clang<"cf_consumed", 1>]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [Undocumented]; } @@ -1118,7 +1118,7 @@ def Hot : InheritableAttr { } def IBAction : InheritableAttr { - let Spellings = [Clang<"ibaction">]; + let Spellings = [Clang<"ibaction", 1>]; let Subjects = SubjectList<[ObjCInstanceMethod]>; // An AST node is created for this attribute, but is not used by other parts // of the compiler. However, this node needs to exist in the AST because @@ -1127,13 +1127,13 @@ def IBAction : InheritableAttr { } def IBOutlet : InheritableAttr { - let Spellings = [Clang<"iboutlet">]; + let Spellings = [Clang<"iboutlet", 1>]; // let Subjects = [ObjCIvar, ObjCProperty]; let Documentation = [Undocumented]; } def IBOutletCollection : InheritableAttr { - let Spellings = [Clang<"iboutletcollection">]; + let Spellings = [Clang<"iboutletcollection", 1>]; let Args = [TypeArgument<"Interface", 1>]; // let Subjects = [ObjCIvar, ObjCProperty]; let Documentation = [Undocumented]; @@ -1428,7 +1428,7 @@ def ObjCKindOf : TypeAttr { } def NoEscape : Attr { - let Spellings = [Clang<"noescape">]; + let Spellings = [Clang<"noescape", 1>]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [NoEscapeDocs]; } @@ -1480,14 +1480,14 @@ def NvWeak : IgnoredAttr { } def ObjCBridge : InheritableAttr { - let Spellings = [Clang<"objc_bridge">]; + let Spellings = [Clang<"objc_bridge", 1>]; let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>; let Args = [IdentifierArgument<"BridgedType">]; let Documentation = [Undocumented]; } def ObjCBridgeMutable : InheritableAttr { - let Spellings = [Clang<"objc_bridge_mutable">]; + let Spellings = [Clang<"objc_bridge_mutable", 1>]; let Subjects = SubjectList<[Record], ErrorDiag>; let Args = [IdentifierArgument<"BridgedType">]; let Documentation = [Undocumented]; @@ -1506,43 +1506,43 @@ def ObjCBridgeRelated : InheritableAttr { } def NSReturnsRetained : InheritableAttr { - let Spellings = [Clang<"ns_returns_retained">]; + let Spellings = [Clang<"ns_returns_retained", 1>]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def NSReturnsNotRetained : InheritableAttr { - let Spellings = [Clang<"ns_returns_not_retained">]; + let Spellings = [Clang<"ns_returns_not_retained", 1>]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def NSReturnsAutoreleased : InheritableAttr { - let Spellings = [Clang<"ns_returns_autoreleased">]; + let Spellings = [Clang<"ns_returns_autoreleased", 1>]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def NSConsumesSelf : InheritableAttr { - let Spellings = [Clang<"ns_consumes_self">]; + let Spellings = [Clang<"ns_consumes_self", 1>]; let Subjects = SubjectList<[ObjCMethod]>; let Documentation = [Undocumented]; } def NSConsumed : InheritableParamAttr { - let Spellings = [Clang<"ns_consumed">]; + let Spellings = [Clang<"ns_consumed", 1>]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [Undocumented]; } def ObjCException : InheritableAttr { - let Spellings = [Clang<"objc_exception">]; + let Spellings = [Clang<"objc_exception", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCMethodFamily : InheritableAttr { - let Spellings = [Clang<"objc_method_family">]; + let Spellings = [Clang<"objc_method_family", 1>]; let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Args = [EnumArgument<"Family", "FamilyKind", ["none", "alloc", "copy", "init", "mutableCopy", "new"], @@ -1552,72 +1552,72 @@ def ObjCMethodFamily : InheritableAttr { } def ObjCNSObject : InheritableAttr { - let Spellings = [Clang<"NSObject">]; + let Spellings = [Clang<"NSObject", 1>]; let Documentation = [Undocumented]; } def ObjCIndependentClass : InheritableAttr { - let Spellings = [Clang<"objc_independent_class">]; + let Spellings = [Clang<"objc_independent_class", 1>]; let Documentation = [Undocumented]; } def ObjCPreciseLifetime : InheritableAttr { - let Spellings = [Clang<"objc_precise_lifetime">]; + let Spellings = [Clang<"objc_precise_lifetime", 1>]; let Subjects = SubjectList<[Var], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCReturnsInnerPointer : InheritableAttr { - let Spellings = [Clang<"objc_returns_inner_pointer">]; + let Spellings = [Clang<"objc_returns_inner_pointer", 1>]; let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCRequiresSuper : InheritableAttr { - let Spellings = [Clang<"objc_requires_super">]; + let Spellings = [Clang<"objc_requires_super", 1>]; let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Documentation = [ObjCRequiresSuperDocs]; } def ObjCRootClass : InheritableAttr { - let Spellings = [Clang<"objc_root_class">]; + let Spellings = [Clang<"objc_root_class", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCSubclassingRestricted : InheritableAttr { - let Spellings = [Clang<"objc_subclassing_restricted">]; + let Spellings = [Clang<"objc_subclassing_restricted", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCSubclassingRestrictedDocs]; } def ObjCExplicitProtocolImpl : InheritableAttr { - let Spellings = [Clang<"objc_protocol_requires_explicit_implementation">]; + let Spellings = [Clang<"objc_protocol_requires_explicit_implementation", 1>]; let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCDesignatedInitializer : Attr { - let Spellings = [Clang<"objc_designated_initializer">]; + let Spellings = [Clang<"objc_designated_initializer", 1>]; let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCRuntimeName : Attr { - let Spellings = [Clang<"objc_runtime_name">]; + let Spellings = [Clang<"objc_runtime_name", 1>]; let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>; let Args = [StringArgument<"MetadataName">]; let Documentation = [ObjCRuntimeNameDocs]; } def ObjCRuntimeVisible : Attr { - let Spellings = [Clang<"objc_runtime_visible">]; + let Spellings = [Clang<"objc_runtime_visible", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCRuntimeVisibleDocs]; } def ObjCBoxable : Attr { - let Spellings = [Clang<"objc_boxable">]; + let Spellings = [Clang<"objc_boxable", 1>]; let Subjects = SubjectList<[Record], ErrorDiag>; let Documentation = [ObjCBoxableDocs]; } @@ -1950,26 +1950,26 @@ def DiagnoseIf : InheritableAttr { } def ArcWeakrefUnavailable : InheritableAttr { - let Spellings = [Clang<"objc_arc_weak_reference_unavailable">]; + let Spellings = [Clang<"objc_arc_weak_reference_unavailable", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCGC : TypeAttr { - let Spellings = [Clang<"objc_gc">]; + let Spellings = [Clang<"objc_gc", 1>]; let Args = [IdentifierArgument<"Kind">]; let Documentation = [Undocumented]; } def ObjCOwnership : InheritableAttr { - let Spellings = [Clang<"objc_ownership">]; + let Spellings = [Clang<"objc_ownership", 1>]; let Args = [IdentifierArgument<"Kind">]; let ASTNode = 0; let Documentation = [Undocumented]; } def ObjCRequiresPropertyDefs : InheritableAttr { - let Spellings = [Clang<"objc_requires_property_definitions">]; + let Spellings = [Clang<"objc_requires_property_definitions", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 93b9356e3a..ec8e60815a 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1340,7 +1340,7 @@ private: // Objective-C External Declarations void MaybeSkipAttributes(tok::ObjCKeywordKind Kind); - DeclGroupPtrTy ParseObjCAtDirectives(); + DeclGroupPtrTy ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs); DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &prefixAttrs); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 688376ca28..13f968fa5e 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -45,7 +45,8 @@ void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { /// [OBJC] objc-protocol-definition /// [OBJC] objc-method-definition /// [OBJC] '@' 'end' -Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { +Parser::DeclGroupPtrTy +Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) { SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { @@ -58,15 +59,11 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { switch (Tok.getObjCKeywordID()) { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); - case tok::objc_interface: { - ParsedAttributes attrs(AttrFactory); - SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs); + case tok::objc_interface: + SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs); break; - } - case tok::objc_protocol: { - ParsedAttributes attrs(AttrFactory); - return ParseObjCAtProtocolDeclaration(AtLoc, attrs); - } + case tok::objc_protocol: + return ParseObjCAtProtocolDeclaration(AtLoc, Attrs); case tok::objc_implementation: return ParseObjCAtImplementationDeclaration(AtLoc); case tok::objc_end: @@ -1359,6 +1356,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParsedAttributes methodAttrs(AttrFactory); if (getLangOpts().ObjC2) MaybeParseGNUAttributes(methodAttrs); + MaybeParseCXX11Attributes(methodAttrs); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, @@ -1385,6 +1383,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist after the method, parse them. if (getLangOpts().ObjC2) MaybeParseGNUAttributes(methodAttrs); + MaybeParseCXX11Attributes(methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result @@ -1421,11 +1420,10 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist before the argument name, parse them. // Regardless, collect all the attributes we've parsed so far. - ArgInfo.ArgAttrs = nullptr; - if (getLangOpts().ObjC2) { + if (getLangOpts().ObjC2) MaybeParseGNUAttributes(paramAttrs); - ArgInfo.ArgAttrs = paramAttrs.getList(); - } + MaybeParseCXX11Attributes(paramAttrs); + ArgInfo.ArgAttrs = paramAttrs.getList(); // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { @@ -1508,7 +1506,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist after the method, parse them. if (getLangOpts().ObjC2) MaybeParseGNUAttributes(methodAttrs); - + MaybeParseCXX11Attributes(methodAttrs); + if (KeyIdents.size() == 0) return nullptr; diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index a6f966eda1..ce5a479b4b 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -741,7 +741,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, break; } case tok::at: - return ParseObjCAtDirectives(); + return ParseObjCAtDirectives(attrs); case tok::minus: case tok::plus: if (!getLangOpts().ObjC1) { diff --git a/test/Misc/ast-dump-attr.m b/test/Misc/ast-dump-attr.m new file mode 100644 index 0000000000..8775d40d99 --- /dev/null +++ b/test/Misc/ast-dump-attr.m @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fdouble-square-bracket-attributes -triple x86_64-apple-macosx10.10.0 -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s + +@interface NSObject +@end + +[[clang::objc_exception]] +@interface Test1 { +// CHECK: ObjCInterfaceDecl{{.*}} Test1 +// CHECK-NEXT: ObjCExceptionAttr{{.*}} + [[clang::iboutlet]] NSObject *Test2; +// CHECK: ObjCIvarDecl{{.*}} Test2 +// CHECK-NEXT: IBOutletAttr +} +@property (readonly) [[clang::objc_returns_inner_pointer]] void *Test3, *Test4; +// CHECK: ObjCPropertyDecl{{.*}} Test3 'void *' readonly +// CHECK-NEXT: ObjCReturnsInnerPointerAttr +// CHECK-NEXT: ObjCPropertyDecl{{.*}} Test4 'void *' readonly +// CHECK-NEXT: ObjCReturnsInnerPointerAttr + +@property (readonly) [[clang::iboutlet]] NSObject *Test5; +// CHECK: ObjCPropertyDecl{{.*}} Test5 'NSObject *' readonly +// CHECK-NEXT: IBOutletAttr + +// CHECK: ObjCMethodDecl{{.*}} implicit{{.*}} Test3 +// CHECK-NEXT: ObjCReturnsInnerPointerAttr +// CHECK: ObjCMethodDecl{{.*}} implicit{{.*}} Test4 +// CHECK-NEXT: ObjCReturnsInnerPointerAttr +// CHECK: ObjCMethodDecl{{.*}} implicit{{.*}} Test5 +// CHECK-NOT: IBOutletAttr +@end + +[[clang::objc_runtime_name("name")]] @protocol Test6; +// CHECK: ObjCProtocolDecl{{.*}} Test6 +// CHECK-NEXT: ObjCRuntimeNameAttr{{.*}} "name" + +[[clang::objc_protocol_requires_explicit_implementation]] +@protocol Test7 +// CHECK: ObjCProtocolDecl{{.*}} Test7 +// CHECK-NEXT: ObjCExplicitProtocolImplAttr +@end + +@interface Test8 +// CHECK: ObjCInterfaceDecl{{.*}} Test8 +-(void)Test9 [[clang::ns_consumes_self]]; +// CHECK: ObjCMethodDecl{{.*}} Test9 'void' +// CHECK-NEXT: NSConsumesSelfAttr +-(void) [[clang::ns_consumes_self]] Test10: (int)Test11; +// CHECK: ObjCMethodDecl{{.*}} Test10: 'void' +// CHECK-NEXT: |-ParmVarDecl{{.*}} Test11 'int' +// CHECK-NEXT: `-NSConsumesSelfAttr +-(void)Test12: (int *) [[clang::noescape]] Test13 to:(int)Test14 [[clang::ns_consumes_self]]; +// CHECK: ObjCMethodDecl{{.*}} Test12:to: 'void' +// CHECK-NEXT: |-ParmVarDecl{{.*}} Test13 'int *' +// CHECK-NEXT: | `-NoEscapeAttr +// CHECK-NEXT: |-ParmVarDecl{{.*}} Test14 'int' +// CHECK-NEXT: `-NSConsumesSelfAttr +@end diff --git a/test/Parser/objc-attr.m b/test/Parser/objc-attr.m new file mode 100644 index 0000000000..7e65eff745 --- /dev/null +++ b/test/Parser/objc-attr.m @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes -triple x86_64-apple-macosx10.10.0 -verify %s +// expected-no-diagnostics + +@interface NSObject +@end + +[[clang::objc_exception]] +@interface Foo { + [[clang::iboutlet]] NSObject *h; +} +@property (readonly) [[clang::objc_returns_inner_pointer]] void *i, *j; +@property (readonly) [[clang::iboutlet]] NSObject *k; +@end + +[[clang::objc_runtime_name("name")]] @protocol Bar; + +[[clang::objc_protocol_requires_explicit_implementation]] +@protocol Baz +@end + +@interface Quux +-(void)g1 [[clang::ns_consumes_self]]; +-(void)g2 __attribute__((ns_consumes_self)); +-(void)h1: (int)x [[clang::ns_consumes_self]]; +-(void)h2: (int)x __attribute__((ns_consumes_self)); +-(void) [[clang::ns_consumes_self]] i1; +-(void) __attribute__((ns_consumes_self)) i2; +@end -- 2.40.0