Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -231,9 +231,12 @@ let KnownToGCC = 1; } -// The Clang spelling implies GNU and CXX11<"clang", name>. This spelling -// should be used for any Clang-specific attributes. -class Clang : Spelling; +// The Clang spelling implies GNU, CXX11<"clang", name>, and optionally, +// C2x<"clang", name>. This spelling should be used for any Clang-specific +// attributes. +class Clang : Spelling { + bit IncludeC = includeC; +} class Accessor spellings> { string Name = name; @@ -604,7 +607,7 @@ } def Annotate : InheritableParamAttr { - let Spellings = [Clang<"annotate">]; + let Spellings = [Clang<"annotate", 1>]; let Args = [StringArgument<"Annotation">]; // Ensure that the annotate attribute can be used with // '#pragma clang attribute' even though it has no subject list. @@ -1109,13 +1112,13 @@ } 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]; @@ -1403,7 +1406,7 @@ } def NoEscape : Attr { - let Spellings = [Clang<"noescape">]; + let Spellings = [Clang<"noescape", 1>]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [NoEscapeDocs]; } @@ -1455,14 +1458,14 @@ } 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]; @@ -1499,7 +1502,7 @@ } def NSConsumesSelf : InheritableAttr { - let Spellings = [Clang<"ns_consumes_self">]; + let Spellings = [Clang<"ns_consumes_self", 1>]; let Subjects = SubjectList<[ObjCMethod]>; let Documentation = [Undocumented]; } @@ -1511,7 +1514,7 @@ } def ObjCException : InheritableAttr { - let Spellings = [Clang<"objc_exception">]; + let Spellings = [Clang<"objc_exception", 1>]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } @@ -1543,7 +1546,7 @@ } 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]; } @@ -1555,19 +1558,19 @@ } 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]; } @@ -1579,20 +1582,20 @@ } 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]; } @@ -1910,7 +1913,7 @@ } 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]; } @@ -1929,7 +1932,7 @@ } 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]; } Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -8016,7 +8016,7 @@ FieldDeclarator &FD, ObjCDeclSpec &ODS, Selector GetterSel, Selector SetterSel, tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = nullptr); + AttributeList *Attrs, DeclContext *lexicalDC = nullptr); Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, Index: lib/Parse/ParseObjc.cpp =================================================================== --- lib/Parse/ParseObjc.cpp +++ lib/Parse/ParseObjc.cpp @@ -191,7 +191,7 @@ /// objc-category-interface /// /// objc-class-interface: -/// '@' 'interface' identifier objc-type-parameter-list[opt] +/// '@' 'interface' attributes[opt] identifier objc-type-parameter-list[opt] /// objc-superclass[opt] objc-protocol-refs[opt] /// objc-class-instance-variables[opt] /// objc-interface-decl-list @@ -228,6 +228,7 @@ return nullptr; } + MaybeParseCXX11Attributes(attrs); MaybeSkipAttributes(tok::objc_interface); if (expectIdentifier()) @@ -721,6 +722,9 @@ if (!getLangOpts().ObjC2) Diag(AtLoc, diag::err_objc_properties_require_objc2); + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + ObjCDeclSpec OCDS; SourceLocation LParenLoc; // Parse property attribute list, if any. @@ -764,7 +768,7 @@ FD.D.getIdentifier()); Decl *Property = Actions.ActOnProperty( getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel, - MethodImplKind); + MethodImplKind, Attrs.getList()); FD.complete(Property); }; @@ -1380,6 +1384,9 @@ return nullptr; } + // Parse square bracket attributes after the method name. + MaybeParseCXX11Attributes(methodAttrs); + SmallVector CParamInfo; if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. @@ -1424,7 +1431,6 @@ ArgInfo.ArgAttrs = nullptr; if (getLangOpts().ObjC2) { MaybeParseGNUAttributes(paramAttrs); - ArgInfo.ArgAttrs = paramAttrs.getList(); } // Code completion for the next piece of the selector. @@ -1445,6 +1451,10 @@ ArgInfo.NameLoc = Tok.getLocation(); ConsumeToken(); // Eat the identifier. + // Parse attributes written on the parameter name. + MaybeParseCXX11Attributes(paramAttrs); + ArgInfo.ArgAttrs = paramAttrs.getList(); + ArgInfos.push_back(ArgInfo); KeyIdents.push_back(SelIdent); KeyLocs.push_back(selLoc); @@ -2004,13 +2014,13 @@ /// objc-protocol-forward-reference /// /// objc-protocol-definition: -/// \@protocol identifier +/// \@protocol attributes[opt] identifier /// objc-protocol-refs[opt] /// objc-interface-decl-list /// \@end /// /// objc-protocol-forward-reference: -/// \@protocol identifier-list ';' +/// \@protocol attributes[opt] identifier-list ';' /// /// "\@protocol identifier ;" should be resolved as "\@protocol /// identifier-list ;": objc-interface-decl-list may not start with a @@ -2028,6 +2038,7 @@ return nullptr; } + MaybeParseCXX11Attributes(attrs); MaybeSkipAttributes(tok::objc_protocol); if (expectIdentifier()) Index: lib/Sema/SemaObjCProperty.cpp =================================================================== --- lib/Sema/SemaObjCProperty.cpp +++ lib/Sema/SemaObjCProperty.cpp @@ -182,6 +182,7 @@ Selector GetterSel, Selector SetterSel, tok::ObjCKeywordKind MethodImplKind, + AttributeList *Attrs, DeclContext *lexicalDC) { unsigned Attributes = ODS.getPropertyAttributes(); FD.D.setObjCWeakProperty((Attributes & ObjCDeclSpec::DQ_PR_weak) != 0); @@ -221,6 +222,9 @@ Res->setLexicalDeclContext(lexicalDC); } + if (Attrs) + ProcessDeclAttributeList(S, Res, Attrs); + // Validate the attributes on the @property. CheckObjCPropertyAttributes(Res, AtLoc, Attributes, (isa(ClassDecl) || Index: test/Misc/ast-dump-attr.m =================================================================== --- test/Misc/ast-dump-attr.m +++ test/Misc/ast-dump-attr.m @@ -0,0 +1,56 @@ +// 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 + +@interface [[clang::objc_exception]] Test1 { +// CHECK: ObjCInterfaceDecl{{.*}} Test1 +// CHECK-NEXT: ObjCExceptionAttr{{.*}} + [[clang::iboutlet]] NSObject *Test2; +// CHECK: ObjCIvarDecl{{.*}} Test2 +// CHECK-NEXT: IBOutletAttr +} +@property [[clang::objc_returns_inner_pointer]] (readonly) void *Test3, *Test4; +// CHECK: ObjCPropertyDecl{{.*}} Test3 'void *' readonly +// CHECK-NEXT: ObjCReturnsInnerPointerAttr +// CHECK-NEXT: ObjCPropertyDecl{{.*}} Test4 'void *' readonly +// CHECK-NEXT: ObjCReturnsInnerPointerAttr + +@property [[clang::iboutlet]] (readonly) 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 + +@protocol [[clang::objc_runtime_name("name")]] Test6; +// CHECK: ObjCProtocolDecl{{.*}} Test6 +// CHECK-NEXT: ObjCRuntimeNameAttr{{.*}} "name" + +@protocol [[clang::objc_protocol_requires_explicit_implementation]] 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)Test10 [[clang::ns_consumes_self]]: (int)Test11; +// CHECK: ObjCMethodDecl{{.*}} Test10: 'void' +// CHECK-NEXT: |-ParmVarDecl{{.*}} Test11 'int' +// CHECK-NEXT: `-NSConsumesSelfAttr +-(void)Test12 [[clang::ns_consumes_self]]: (int *)Test13 [[clang::noescape]] to:(int)Test14; +// CHECK: ObjCMethodDecl{{.*}} Test12:to: 'void' +// CHECK-NEXT: |-ParmVarDecl{{.*}} Test13 'int *' +// CHECK-NEXT: `-NoEscapeAttr +// CHECK-NEXT: |-ParmVarDecl{{.*}} Test14 'int' +// CHECK-NEXT: `-NSConsumesSelfAttr + +@end Index: test/Parser/objc-attr.m =================================================================== --- test/Parser/objc-attr.m +++ test/Parser/objc-attr.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -fdouble-square-bracket-attributes -triple x86_64-apple-macosx10.10.0 -verify %s +// expected-no-diagnostics + +@interface NSObject +@end + +@interface [[clang::objc_exception]] Foo { + [[clang::iboutlet]] NSObject *h; +} +@property [[clang::objc_returns_inner_pointer]] (readonly) void *i, *j; +@property [[clang::iboutlet]] (readonly) NSObject *k; +@end + +@protocol [[clang::objc_runtime_name("name")]] Bar; + +@protocol [[clang::objc_protocol_requires_explicit_implementation]] Baz +@end + +@interface Quux +-(void)g [[clang::ns_consumes_self]]; +-(void)h [[clang::ns_consumes_self]]: (int)x; +-(void)i [[clang::ns_consumes_self]]: (int *)x [[clang::noescape]] to:(int)y; +@end Index: test/Sema/annotate.c =================================================================== --- test/Sema/annotate.c +++ test/Sema/annotate.c @@ -1,9 +1,13 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify +// RUN: %clang_cc1 %s -fsyntax-only -fdouble-square-bracket-attributes -verify void __attribute__((annotate("foo"))) foo(float *a) { __attribute__((annotate("bar"))) int x; + [[clang::annotate("bar")]] int x2; __attribute__((annotate(1))) int y; // expected-error {{'annotate' attribute requires a string}} + [[clang::annotate(1)]] int y2; // expected-error {{'annotate' attribute requires a string}} __attribute__((annotate("bar", 1))) int z; // expected-error {{'annotate' attribute takes one argument}} + [[clang::annotate("bar", 1)]] int z2; // expected-error {{'annotate' attribute takes one argument}} + int u = __builtin_annotation(z, (char*) 0); // expected-error {{second argument to __builtin_annotation must be a non-wide string constant}} int v = __builtin_annotation(z, (char*) L"bar"); // expected-error {{second argument to __builtin_annotation must be a non-wide string constant}} int w = __builtin_annotation(z, "foo"); Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -87,6 +87,8 @@ } else if (Variety == "Clang") { Ret.emplace_back("GNU", Name, "", false); Ret.emplace_back("CXX11", Name, "clang", false); + if (Spelling->getValueAsBit("IncludeC")) + Ret.emplace_back("C2x", Name, "clang", false); } else Ret.push_back(FlattenedSpelling(*Spelling)); }