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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to