lanza updated this revision to Diff 293944.
lanza added a comment.
Update
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D75574/new/
https://reviews.llvm.org/D75574
Files:
clang/include/clang/AST/DeclObjC.h
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/DeclObjC.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CGObjCGNU.cpp
clang/lib/CodeGen/CGObjCMac.cpp
clang/lib/CodeGen/CGObjCRuntime.h
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaExprObjC.cpp
clang/test/CodeGenObjC/non-runtime-protocol.m
clang/test/Misc/pragma-attribute-supported-attributes-list.test
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -118,6 +118,7 @@
// CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method)
// CHECK-NEXT: ObjCMethodFamily (SubjectMatchRule_objc_method)
// CHECK-NEXT: ObjCNonLazyClass (SubjectMatchRule_objc_interface, SubjectMatchRule_objc_implementation)
+// CHECK-NEXT: ObjCNonRuntimeProtocol (SubjectMatchRule_objc_protocol)
// CHECK-NEXT: ObjCPreciseLifetime (SubjectMatchRule_variable)
// CHECK-NEXT: ObjCRequiresPropertyDefs (SubjectMatchRule_objc_interface)
// CHECK-NEXT: ObjCRequiresSuper (SubjectMatchRule_objc_method)
Index: clang/test/CodeGenObjC/non-runtime-protocol.m
===================================================================
--- /dev/null
+++ clang/test/CodeGenObjC/non-runtime-protocol.m
@@ -0,0 +1,118 @@
+// RUN: not %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DPROTOEXPR -o - 2>&1 \
+// RUN: | FileCheck -check-prefix=PROTOEXPR %s
+
+// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - \
+// RUN: | FileCheck -check-prefix=NONFRAGILE %s
+// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DINHERITANCE -o - \
+// RUN: | FileCheck -check-prefix=INHERITANCE %s
+
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 %s -o - \
+// RUN: | FileCheck -check-prefix=FRAGILE %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 %s -DINHERITANCE -o - \
+// RUN: | FileCheck -check-prefix=FRAGILEINHERITANCE %s
+
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep %s -o - \
+// RUN: | FileCheck -check-prefix=GNU %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep %s -DINHERITANCE -o - \
+// RUN: | FileCheck -check-prefix=GNUINHERITANCE %s
+//
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep-2 %s -o - \
+// RUN: | FileCheck -check-prefix=GNU2 %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep-2 %s -DINHERITANCE -o - \
+// RUN: | FileCheck -check-prefix=GNU2INHERITANCE %s
+
+__attribute__((objc_root_class))
+@interface Root
+@end
+@implementation Root
+@end
+
+#ifndef INHERITANCE
+// Confirm that we're not emitting protocol information for the
+// NONFRAGILE-NOT: OBJC_CLASS_NAME{{.*}}NonRuntimeProtocol
+// NONFRAGILE-NOT: _OBJC_$_PROTOCOL_INSTANCE_METHODS_NonRuntimeProtocol
+// NONFRAGILE-NOT: _OBJC_$_PROTOCOL_CLASS_METHODS_NonRuntimeProtocol
+// NONFRAGILE-NOT: _OBJC_PROTOCOL_$_NonRuntimeProtocol
+// NONFRAGILE-NOT: _OBJC_LABEL_PROTOCOL_$_NonRuntimeProtocol
+// NONFRAGILE-NOT: _OBJC_CLASS_PROTOCOLS_$_NonRuntimeImplementer
+// FRAGILE-NOT: OBJC_CLASS_NAME_.{{.*}}"Runtime\00"
+// FRAGILE-NOT: OBJC_PROTOCOL_NonRuntime
+// FRAGILE_NOT: OBJC_PROTOCOLS_NonRuntimeImplementer
+// GNU-NOT: private unnamed_addr constant {{.*}} c"NonRuntimeProtocol\00"
+// GNU-NOT: @.objc_protocol {{.*}}
+// GNU2-NOT: private unnamed_addr constant {{.*}} c"NonRuntimeProtocol\00"
+// GNU2-NOT: @.objc_protocol {{.*}}
+__attribute__((objc_non_runtime_protocol))
+@protocol NonRuntimeProtocol
+- (void)doThing;
++ (void)doClassThing;
+@end
+// NONFRAGILE: @"_OBJC_METACLASS_RO_$_NonRuntimeImplementer" {{.*}} %struct._objc_protocol_list* null
+// NONFRAGILE: @"_OBJC_CLASS_RO_$_NonRuntimeImplementer" {{.*}} %struct._objc_protocol_list* null
+@interface NonRuntimeImplementer : Root <NonRuntimeProtocol>
+- (void)doThing;
++ (void)doClassThing;
+@end
+
+@implementation NonRuntimeImplementer
+- (void)doThing {
+}
++ (void)doClassThing {
+}
+@end
+
+void useNonRuntime(NonRuntimeImplementer *si) {
+ [si doThing];
+ [NonRuntimeImplementer doClassThing];
+
+#ifdef PROTOEXPR
+ // PROTOEXPR: cannot use a protocol declared 'objc_non_runtime_protocol' in a @protocol expression
+ Protocol *p = @protocol(NonRuntimeProtocol);
+#endif
+}
+#endif
+
+#ifdef INHERITANCE
+// Confirm that we only emit references to the non-runtime protocols and
+// properly walk the DAG to find the right protocols.
+// INHERITANCE: OBJC_PROTOCOL_$_R3{{.*}}
+// INHERITANCE: OBJC_PROTOCOL_$_R2{{.*}}
+// INHERITANCE: @"_OBJC_CLASS_PROTOCOLS_$_Implementer" {{.*}}_OBJC_PROTOCOL_$_R{{[23]}}{{.*}}_OBJC_PROTOCOL_$_R{{[23]}}
+
+// FRAGILEINHERITANCE: OBJC_PROTOCOL_R3
+// FRAGILEINHERITANCE: OBJC_PROTOCOL_R2
+// FRAGILEINHERITANCE: OBJC_CLASS_PROTOCOLS_Implementer{{.*}}OBJC_PROTOCOL_R3{{.*}}OBJC_PROTOCOL_R2
+
+// GNUINHERITANCE-DAG: @[[Proto1:[0-9]]]{{.*}}c"R1\00"
+// GNUINHERITANCE-DAG: [[P1Name:@.objc_protocol.[0-9]*]]{{.*}}@[[Proto1]]
+// GNUINHERITANCE-DAG: @[[Proto2:[0-9]]]{{.*}}c"R2\00"
+// GNUINHERITANCE-DAG: [[P2Name:@.objc_protocol.[0-9]+]]{{.*}}@[[Proto2]]
+// GNUINHERITANCE-DAG: @[[Proto3:[0-9]]]{{.*}}c"R3\00"
+// GNUINHERITANCE-DAG: [[P3Name:@.objc_protocol.[0-9]+]]{{.*}}@[[Proto3]]
+// GNUINHERITANCE-DAG: @.objc_protocol_list{{.*}}
+// GNUINHERITANCE: @.objc_protocol_list{{.*}}[[Proto3]]{{.*}}[[Proto2]]
+
+// GNU2INHERITANCE-DAG: @[[Proto1:[0-9]]]{{.*}}c"R1\00"
+// GNU2INHERITANCE-DAG: _OBJC_PROTOCOL_R1{{.*}}@[[Proto1]]
+// GNU2INHERITANCE-DAG: @[[Proto2:[0-9]]]{{.*}}c"R2\00"
+// GNU2INHERITANCE-DAG: _OBJC_PROTOCOL_R2{{.*}}@[[Proto2]]
+// GNU2INHERITANCE-DAG: @[[Proto3:[0-9]]]{{.*}}c"R3\00"
+// GNU2INHERITANCE-DAG: _OBJC_PROTOCOL_R3{{.*}}@[[Proto3]]
+// GNU2INHERITANCE: @.objc_protocol_list{{.*}}_OBJC_PROTOCOL_R3{{.*}}_OBJC_PROTOCOL_R2
+@protocol R1
+@end
+@protocol R2
+@end
+@protocol R3 <R1>
+@end
+__attribute__((objc_non_runtime_protocol)) @protocol N3
+@end
+__attribute__((objc_non_runtime_protocol)) @protocol N1<R3, R2, N3>
+@end
+__attribute__((objc_non_runtime_protocol)) @protocol N2<N1, R2>
+@end
+@interface Implementer : Root <N2, R2>
+@end
+@implementation Implementer
+@end
+#endif
Index: clang/lib/Sema/SemaExprObjC.cpp
===================================================================
--- clang/lib/Sema/SemaExprObjC.cpp
+++ clang/lib/Sema/SemaExprObjC.cpp
@@ -1394,6 +1394,9 @@
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
return true;
}
+ if (PDecl->isNonRuntimeProtocol())
+ Diag(ProtoLoc, diag::err_objc_non_runtime_protocol_in_protocol_expr)
+ << PDecl;
if (!PDecl->hasDefinition()) {
Diag(ProtoLoc, diag::err_atprotocol_protocol) << PDecl;
Diag(PDecl->getLocation(), diag::note_entity_declared_at) << PDecl;
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -2617,6 +2617,11 @@
D->addAttr(newAttr);
}
+static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL);
+}
+
static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// objc_direct cannot be set on methods declared in the context of a protocol
if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
@@ -7643,6 +7648,9 @@
case ParsedAttr::AT_ObjCDirect:
handleObjCDirectAttr(S, D, AL);
break;
+ case ParsedAttr::AT_ObjCNonRuntimeProtocol:
+ handleObjCNonRuntimeProtocolAttr(S, D, AL);
+ break;
case ParsedAttr::AT_ObjCDirectMembers:
handleObjCDirectMembersAttr(S, D, AL);
handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
Index: clang/lib/CodeGen/CGObjCRuntime.h
===================================================================
--- clang/lib/CodeGen/CGObjCRuntime.h
+++ clang/lib/CodeGen/CGObjCRuntime.h
@@ -20,6 +20,7 @@
#include "CGValue.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h" // Selector
+#include "llvm/ADT/UniqueVector.h"
namespace llvm {
class Constant;
@@ -202,6 +203,13 @@
const CallArgList &CallArgs,
const ObjCMethodDecl *Method = nullptr) = 0;
+ /// Walk the DAG of protocol references from a class, category or
+ /// protocol to find the list of protocols ended at either a runtime
+ /// protocol or a non-runtime protocol with no parents.
+ llvm::UniqueVector<ObjCProtocolDecl *>
+ GetRuntimeProtocolList(ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end);
+
/// Emit the code to return the named protocol as an object, as in a
/// \@protocol expression.
virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
Index: clang/lib/CodeGen/CGObjCMac.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -31,6 +31,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/UniqueVector.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -3202,7 +3203,8 @@
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end) {
// Just return null for empty protocol lists
- if (begin == end)
+ auto PDs = GetRuntimeProtocolList(begin, end);
+ if (PDs.empty())
return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
ConstantInitBuilder builder(CGM);
@@ -3215,9 +3217,9 @@
auto countSlot = values.addPlaceholder();
auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
- for (; begin != end; ++begin) {
- refsArray.add(GetProtocolRef(*begin));
- }
+ for (auto Proto : PDs)
+ refsArray.add(GetProtocolRef(Proto));
+
auto count = refsArray.size();
// This list is null terminated.
@@ -6671,7 +6673,8 @@
// This routine is called for @protocol only. So, we must build definition
// of protocol's meta-data (not a reference to it!)
- //
+ assert(!PD->isNonRuntimeProtocol() &&
+ "attempting to get a protocol ref to a static protocol.");
llvm::Constant *Init =
llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
ObjCTypes.getExternalProtocolPtrTy());
@@ -7028,6 +7031,8 @@
const ObjCProtocolDecl *PD) {
llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
+ assert(!PD->isNonRuntimeProtocol() &&
+ "attempting to GetOrEmit a non-runtime protocol");
if (!Entry) {
// We use the initializer as a marker of whether this is a forward
// reference or not. At module finalization we add the empty
@@ -7171,10 +7176,19 @@
CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end) {
+ // Just return null for empty protocol lists
+ auto Protocols = GetRuntimeProtocolList(begin, end);
+ if (Protocols.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
+
SmallVector<llvm::Constant *, 16> ProtocolRefs;
- // Just return null for empty protocol lists
- if (begin == end)
+ for (auto PD : Protocols)
+ ProtocolRefs.push_back(GetProtocolRef(PD));
+
+ // If all of the protocols in the protocol list are objc_non_runtime_protocol
+ // just return null
+ if (ProtocolRefs.size() == 0)
return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
// FIXME: We shouldn't need to do this lookup here, should we?
@@ -7191,8 +7205,8 @@
// A null-terminated array of protocols.
auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
- for (; begin != end; ++begin)
- array.add(GetProtocolRef(*begin)); // Implemented???
+ for (auto const &proto : ProtocolRefs)
+ array.add(proto);
auto count = array.size();
array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Index: clang/lib/CodeGen/CGObjCGNU.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCGNU.cpp
+++ clang/lib/CodeGen/CGObjCGNU.cpp
@@ -1197,8 +1197,11 @@
}
llvm::Constant *GenerateCategoryProtocolList(const ObjCCategoryDecl *OCD)
override {
- SmallVector<llvm::Constant*, 16> Protocols;
- for (const auto *PI : OCD->getReferencedProtocols())
+ auto &ReferencedProtocols = OCD->getReferencedProtocols();
+ auto RuntimeProtocols = GetRuntimeProtocolList(ReferencedProtocols.begin(),
+ ReferencedProtocols.end());
+ SmallVector<llvm::Constant *, 16> Protocols;
+ for (const auto *PI : RuntimeProtocols)
Protocols.push_back(
llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
ProtocolPtrTy));
@@ -1381,7 +1384,9 @@
}
SmallVector<llvm::Constant*, 16> Protocols;
- for (const auto *PI : PD->protocols())
+ auto RuntimeProtocols =
+ GetRuntimeProtocolList(PD->protocol_begin(), PD->protocol_end());
+ for (const auto *PI : RuntimeProtocols)
Protocols.push_back(
llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
ProtocolPtrTy));
@@ -1920,8 +1925,10 @@
// struct objc_class *sibling_class
classFields.addNullPointer(PtrTy);
// struct objc_protocol_list *protocols;
- SmallVector<llvm::Constant*, 16> Protocols;
- for (const auto *I : classDecl->protocols())
+ auto RuntimeProtocols = GetRuntimeProtocolList(classDecl->protocol_begin(),
+ classDecl->protocol_end());
+ SmallVector<llvm::Constant *, 16> Protocols;
+ for (const auto *I : RuntimeProtocols)
Protocols.push_back(
llvm::ConstantExpr::getBitCast(GenerateProtocolRef(I),
ProtocolPtrTy));
@@ -3088,6 +3095,9 @@
}
void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
+ if (PD->isNonRuntimeProtocol())
+ return;
+
std::string ProtocolName = PD->getNameAsString();
// Use the protocol definition, if there is one.
@@ -3240,8 +3250,10 @@
llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(const
ObjCCategoryDecl *OCD) {
+ auto &RefPro = OCD->getReferencedProtocols();
+ auto RuntimeProtos = GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
SmallVector<std::string, 16> Protocols;
- for (const auto *PD : OCD->getReferencedProtocols())
+ for (const auto *PD : RuntimeProtos)
Protocols.push_back(PD->getNameAsString());
return GenerateProtocolList(Protocols);
}
@@ -3527,8 +3539,11 @@
llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
// Collect the names of referenced protocols
+ auto RefProtocols = ClassDecl->protocols();
+ auto RuntimeProtocols =
+ GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
SmallVector<std::string, 16> Protocols;
- for (const auto *I : ClassDecl->protocols())
+ for (const auto *I : RuntimeProtocols)
Protocols.push_back(I->getNameAsString());
// Get the superclass pointer.
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -445,6 +445,29 @@
Method);
}
+static void
+AppendFirstRuntimeProtocols(ObjCProtocolDecl *PD,
+ llvm::UniqueVector<ObjCProtocolDecl *> &PDs) {
+ if (!PD->isNonRuntimeProtocol()) {
+ PDs.insert(PD);
+ return;
+ }
+
+ for (auto ParentPD : PD->protocols())
+ AppendFirstRuntimeProtocols(ParentPD, PDs);
+}
+
+llvm::UniqueVector<ObjCProtocolDecl *>
+CGObjCRuntime::GetRuntimeProtocolList(ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end) {
+ llvm::UniqueVector<ObjCProtocolDecl *> PDs;
+
+ for (; begin != end; ++begin)
+ AppendFirstRuntimeProtocols(*begin, PDs);
+
+ return PDs;
+}
+
/// Instead of '[[MyClass alloc] init]', try to generate
/// 'objc_alloc_init(MyClass)'. This provides a code size improvement on the
/// caller side, as well as the optimized objc_alloc.
Index: clang/lib/AST/DeclObjC.cpp
===================================================================
--- clang/lib/AST/DeclObjC.cpp
+++ clang/lib/AST/DeclObjC.cpp
@@ -1897,6 +1897,10 @@
return Result;
}
+bool ObjCProtocolDecl::isNonRuntimeProtocol() const {
+ return hasAttr<ObjCNonRuntimeProtocolAttr>();
+}
+
ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
ObjCProtocolDecl *PDecl = this;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1034,6 +1034,8 @@
"string is ill-formed as UTF-8 and will become a null %0 when boxed">,
InGroup<ObjCBoxing>;
+def err_objc_non_runtime_protocol_in_protocol_expr : Error<
+ "cannot use a protocol declared 'objc_non_runtime_protocol' in a @protocol expression">;
def err_objc_direct_on_protocol : Error<
"'objc_direct' attribute cannot be applied to %select{methods|properties}0 "
"declared in an Objective-C protocol">;
@@ -1055,6 +1057,9 @@
def warn_objc_direct_property_ignored : Warning<
"direct attribute on property %0 ignored (not implemented by this Objective-C runtime)">,
InGroup<IgnoredAttributes>;
+def warn_objc_non_runtime_protocol_ignored : Warning<
+ "non_runtime_protocol attribute on protocol %0 ignored (not implemented by this Objective-C runtime)">,
+ InGroup<IgnoredAttributes>;
def err_objc_direct_dynamic_property : Error<
"direct property cannot be @dynamic">;
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -4491,6 +4491,21 @@
}];
}
+def ObjCNonRuntimeProtocolDocs : Documentation {
+ let Category = DocCatDecl;
+ let Content = [{
+The ``objc_non_runtime_protocol`` attribute can be used to mark an Objective-C
+to not generate runtime metadata. A non-runtime protocol is used only to
+perform compile time checks on it's conformances. A standard protocol will emit
+various chunks of metadata to enable dynamic runtime behaviors via, e.g.,
+``@protocol`` and ``objc_getProtocol``. These two tools require metadata
+emitted into the binary that is loaded at runtime. With
+``objc_non_runtime_protocol`` these chunks of metadata are removed. If you only
+intend to use protocols to implement compile time behaviors then the metadata is
+uneeded overhead.
+ }];
+}
+
def SelectAnyDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2024,6 +2024,13 @@
let Documentation = [ObjCDirectMembersDocs];
}
+def ObjCNonRuntimeProtocol : Attr {
+ let Spellings = [Clang<"objc_non_runtime_protocol">];
+ let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
+ let LangOpts = [ObjC];
+ let Documentation = [ObjCNonRuntimeProtocolDocs];
+}
+
def ObjCRuntimeName : Attr {
let Spellings = [Clang<"objc_runtime_name">];
let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>;
Index: clang/include/clang/AST/DeclObjC.h
===================================================================
--- clang/include/clang/AST/DeclObjC.h
+++ clang/include/clang/AST/DeclObjC.h
@@ -2171,6 +2171,10 @@
data().ReferencedProtocols.set(List, Num, Locs, C);
}
+ /// This is true iff the protocol is tagged with the `objc_static_protocol`
+ /// attribute.
+ bool isNonRuntimeProtocol() const;
+
ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
// Lookup a method. First, we search locally. If a method isn't
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits