aaron.ballman created this revision.
aaron.ballman added a reviewer: rsmith.
One plausible use for the new double square-bracket attribute support in C are
attributes appertaining to Objective-C constructs. This patch adds parsing
support for such attributes and exposes a handful of ObjC attributes under the
new syntax.
https://reviews.llvm.org/D41553
Files:
include/clang/Basic/Attr.td
include/clang/Sema/Sema.h
lib/Parse/ParseObjc.cpp
lib/Sema/SemaObjCProperty.cpp
test/Misc/ast-dump-attr.m
test/Parser/objc-attr.m
test/Sema/annotate.c
utils/TableGen/ClangAttrEmitter.cpp
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));
}
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: 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/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: 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<ObjCInterfaceDecl>(ClassDecl) ||
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<DeclaratorChunk::ParamInfo, 8> 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: 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: 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<name> and CXX11<"clang", name>. This spelling
-// should be used for any Clang-specific attributes.
-class Clang<string name> : Spelling<name, "Clang">;
+// The Clang spelling implies GNU<name>, CXX11<"clang", name>, and optionally,
+// C2x<"clang", name>. This spelling should be used for any Clang-specific
+// attributes.
+class Clang<string name, bit includeC = 0> : Spelling<name, "Clang"> {
+ bit IncludeC = includeC;
+}
class Accessor<string name, list<Spelling> 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];
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits