Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -3915,7 +3915,7 @@ def EnforceTCB : InheritableAttr { let Spellings = [Clang<"enforce_tcb">]; - let Subjects = SubjectList<[Function]>; + let Subjects = SubjectList<[Function, ObjCMethod]>; let Args = [StringArgument<"TCBName">]; let Documentation = [EnforceTCBDocs]; bit InheritEvenIfAlreadyPresent = 1; @@ -3923,7 +3923,7 @@ def EnforceTCBLeaf : InheritableAttr { let Spellings = [Clang<"enforce_tcb_leaf">]; - let Subjects = SubjectList<[Function]>; + let Subjects = SubjectList<[Function, ObjCMethod]>; let Args = [StringArgument<"TCBName">]; let Documentation = [EnforceTCBLeafDocs]; bit InheritEvenIfAlreadyPresent = 1; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -12965,7 +12965,8 @@ /// attempts to add itself into the container void CheckObjCCircularContainer(ObjCMessageExpr *Message); - void CheckTCBEnforcement(const CallExpr *TheCall, const FunctionDecl *Callee); + void CheckTCBEnforcement(const SourceLocation ExprLoc, + const NamedDecl *Callee); void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE); void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -5497,7 +5497,7 @@ if (!FnInfo) return false; - CheckTCBEnforcement(TheCall, FDecl); + CheckTCBEnforcement(TheCall->getExprLoc(), FDecl); CheckAbsoluteValueFunction(TheCall, FDecl); CheckMaxUnsignedZero(TheCall, FDecl); @@ -5537,6 +5537,8 @@ /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), CallType); + CheckTCBEnforcement(lbrac, Method); + return false; } @@ -17359,13 +17361,14 @@ /// CheckTCBEnforcement - Enforces that every function in a named TCB only /// directly calls other functions in the same TCB as marked by the enforce_tcb /// and enforce_tcb_leaf attributes. -void Sema::CheckTCBEnforcement(const CallExpr *TheCall, - const FunctionDecl *Callee) { - const FunctionDecl *Caller = getCurFunctionDecl(); +void Sema::CheckTCBEnforcement(const SourceLocation ExprLoc, + const NamedDecl *Callee) { + const NamedDecl *Caller = getCurFunctionOrMethodDecl(); // Calls to builtins are not enforced. if (!Caller || !Caller->hasAttr() || - Callee->getBuiltinID() != 0) + (isa(Callee) && + cast(Callee)->getBuiltinID() != 0)) return; // Search through the enforce_tcb and enforce_tcb_leaf attributes to find @@ -17383,9 +17386,8 @@ [&](const auto *A) { StringRef CallerTCB = A->getTCBName(); if (CalleeTCBs.count(CallerTCB) == 0) { - this->Diag(TheCall->getExprLoc(), - diag::warn_tcb_enforcement_violation) << Callee - << CallerTCB; + this->Diag(ExprLoc, diag::warn_tcb_enforcement_violation) + << Callee << CallerTCB; } }); } 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 @@ -61,8 +61,8 @@ // CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: EnableIf (SubjectMatchRule_function) -// CHECK-NEXT: EnforceTCB (SubjectMatchRule_function) -// CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function) +// CHECK-NEXT: EnforceTCB (SubjectMatchRule_function, SubjectMatchRule_objc_method) +// CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum) // CHECK-NEXT: Error (SubjectMatchRule_function) // CHECK-NEXT: ExcludeFromExplicitInstantiation (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) Index: clang/test/Sema/attr-enforce-tcb.m =================================================================== --- /dev/null +++ clang/test/Sema/attr-enforce-tcb.m @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define PLACE_IN_TCB(NAME) __attribute__((enforce_tcb(NAME))) +#define PLACE_IN_TCB_LEAF(NAME) __attribute__((enforce_tcb_leaf(NAME))) + +__attribute__((objc_root_class)) +@interface AClass +@property(readonly) id propertyNotInAnyTCB; +@end + +@implementation AClass +- (void)inTCBFoo PLACE_IN_TCB("foo") { + [self notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}} +} +- (void)inTCBFooAsLeaf PLACE_IN_TCB_LEAF("foo") { + [self notInAnyTCB]; // no-warning +} +- (void)notInAnyTCB { +} ++ (void)classMethodNotInAnyTCB { +} ++ (void)classMethodInTCBFoo PLACE_IN_TCB("foo") { + [self inTCBFoo]; // no-warning + [self inTCBFooAsLeaf]; // no-warning + [self notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}} +} +@end + +PLACE_IN_TCB("foo") +void call_objc_method(AClass *object) { + [object inTCBFoo]; // no-warning + [object inTCBFooAsLeaf]; // no-warning + [object notInAnyTCB]; // expected-warning{{calling 'notInAnyTCB' is a violation of trusted computing base 'foo'}} + [AClass classMethodNotInAnyTCB]; // expected-warning{{calling 'classMethodNotInAnyTCB' is a violation of trusted computing base 'foo'}} + [AClass classMethodInTCBFoo]; // no-warning + (void)object.propertyNotInAnyTCB; // expected-warning{{calling 'propertyNotInAnyTCB' is a violation of trusted computing base 'foo'}} +}