This revision was automatically updated to reflect the committed changes.
Closed by commit rL354530: [attributes] Add an attribute for server routines in 
Mach kernel and extensions. (authored by dergachev, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D58365?vs=187656&id=187691#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58365/new/

https://reviews.llvm.org/D58365

Files:
  cfe/trunk/include/clang/Basic/Attr.td
  cfe/trunk/include/clang/Basic/AttrDocs.td
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
  cfe/trunk/lib/Sema/SemaDeclAttr.cpp
  cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test
  cfe/trunk/test/Sema/attr-mig.c
  cfe/trunk/test/Sema/attr-mig.cpp
  cfe/trunk/test/Sema/attr-mig.m

Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8706,6 +8706,11 @@
 def ext_opencl_ext_vector_type_rgba_selector: ExtWarn<
   "vector component name '%0' is an OpenCL version 2.2 feature">,
   InGroup<OpenCLUnsupportedRGBA>;
+
+// MIG routine annotations.
+def warn_mig_server_routine_does_not_return_kern_return_t : Warning<
+  "'mig_server_routine' attribute only applies to routines that return a kern_return_t">,
+  InGroup<IgnoredAttributes>;
 } // end of sema category
 
 let CategoryName = "OpenMP Issue" in {
Index: cfe/trunk/include/clang/Basic/AttrDocs.td
===================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td
+++ cfe/trunk/include/clang/Basic/AttrDocs.td
@@ -4095,3 +4095,24 @@
 
 When compiled without ``-fobjc-arc``, this attribute is ignored.
 }]; }
+
+def MIGConventionDocs : Documentation {
+  let Category = DocCatType;
+  let Content = [{
+  The Mach Interface Generator release-on-success convention dictates
+functions that follow it to only release arguments passed to them when they
+return "success" (a ``kern_return_t`` error code that indicates that
+no errors have occured). Otherwise the release is performed by the MIG client
+that called the function. The annotation ``__attribute__((mig_server_routine))``
+is applied in order to specify which functions are expected to follow the
+convention. This allows the Static Analyzer to find bugs caused by violations of
+that convention. The attribute would normally appear on the forward declaration
+of the actual server routine in the MIG server header, but it may also be
+added to arbitrary functions that need to follow the same convention - for
+example, a user can add them to auxiliary functions called by the server routine
+that have their return value of type ``kern_return_t`` unconditionally returned
+from the routine. The attribute can be applied to C++ methods, and in this case
+it will be automatically applied to overrides if the method is virtual. The
+attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``.
+}];
+}
Index: cfe/trunk/include/clang/Basic/Attr.td
===================================================================
--- cfe/trunk/include/clang/Basic/Attr.td
+++ cfe/trunk/include/clang/Basic/Attr.td
@@ -1300,6 +1300,12 @@
   let Documentation = [Undocumented];
 }
 
+def MIGServerRoutine : InheritableAttr {
+  let Spellings = [Clang<"mig_server_routine">];
+  let Subjects = SubjectList<[Function, ObjCMethod, Block]>;
+  let Documentation = [MIGConventionDocs];
+}
+
 def MSABI : DeclOrTypeAttr {
   let Spellings = [GCC<"ms_abi">];
 //  let Subjects = [Function, ObjCMethod];
Index: cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test
+++ cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -61,6 +61,7 @@
 // CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
 // CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
+// CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
 // CHECK-NEXT: MinSize (SubjectMatchRule_function, SubjectMatchRule_objc_method)
Index: cfe/trunk/test/Sema/attr-mig.cpp
===================================================================
--- cfe/trunk/test/Sema/attr-mig.cpp
+++ cfe/trunk/test/Sema/attr-mig.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef int kern_return_t;
+typedef kern_return_t IOReturn;
+#define KERN_SUCCESS 0
+#define kIOReturnSuccess KERN_SUCCESS
+
+class MyServer {
+public:
+  virtual __attribute__((mig_server_routine)) IOReturn externalMethod();
+  virtual __attribute__((mig_server_routine)) void anotherMethod(); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+  virtual __attribute__((mig_server_routine)) int yetAnotherMethod(); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+  [[clang::mig_server_routine]] virtual IOReturn cppAnnotatedMethod();
+  [[clang::mig_server_routine("arg")]] virtual IOReturn cppAnnotatedMethodWithInvalidArgs(); // expected-error{{'mig_server_routine' attribute takes no arguments}}
+  [[clang::mig_server_routine]] virtual int cppInvalidAnnotatedMethod(); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+};
+
+IOReturn MyServer::externalMethod() {
+  return kIOReturnSuccess;
+}
Index: cfe/trunk/test/Sema/attr-mig.m
===================================================================
--- cfe/trunk/test/Sema/attr-mig.m
+++ cfe/trunk/test/Sema/attr-mig.m
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+
+typedef int kern_return_t;
+#define KERN_SUCCESS 0
+
+@interface NSObject
+@end
+
+@interface I: NSObject
+- (kern_return_t)foo __attribute__((mig_server_routine)); // no-warning
+- (void) bar_void __attribute__((mig_server_routine)); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+- (int) bar_int __attribute__((mig_server_routine)); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+@end
+
+@implementation I
+- (kern_return_t)foo {
+  kern_return_t (^block)() = ^ __attribute__((mig_server_routine)) { // no-warning
+    return KERN_SUCCESS;
+  };
+
+  // FIXME: Warn that this block doesn't return a kern_return_t.
+  void (^invalid_block)() = ^ __attribute__((mig_server_routine)) {};
+
+  return block();
+}
+- (void)bar_void {
+}
+- (int)bar_int {
+  return 0;
+}
+@end
Index: cfe/trunk/test/Sema/attr-mig.c
===================================================================
--- cfe/trunk/test/Sema/attr-mig.c
+++ cfe/trunk/test/Sema/attr-mig.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef int kern_return_t;
+#define KERN_SUCCESS 0
+
+__attribute__((mig_server_routine)) kern_return_t var = KERN_SUCCESS; // expected-warning{{'mig_server_routine' attribute only applies to functions, Objective-C methods, and blocks}}
+
+__attribute__((mig_server_routine)) void foo_void(); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+__attribute__((mig_server_routine)) int foo_int(); // expected-warning{{'mig_server_routine' attribute only applies to routines that return a kern_return_t}}
+
+__attribute__((mig_server_routine)) kern_return_t bar_extern(); // no-warning
+__attribute__((mig_server_routine)) kern_return_t bar_forward(); // no-warning
+
+__attribute__((mig_server_routine)) kern_return_t bar_definition() { // no-warning
+  return KERN_SUCCESS;
+}
+
+kern_return_t bar_forward() { // no-warning
+  return KERN_SUCCESS;
+}
+
+__attribute__((mig_server_routine(123))) kern_return_t bar_with_argument(); // expected-error{{'mig_server_routine' attribute takes no arguments}}
Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp
@@ -6458,6 +6458,28 @@
       AL.getAttributeSpellingListIndex()));
 }
 
+static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // Check that the return type is a `typedef int kern_return_t` or a typedef
+  // around it, because otherwise MIG convention checks make no sense.
+  // BlockDecl doesn't store a return type, so it's annoying to check,
+  // so let's skip it for now.
+  if (!isa<BlockDecl>(D)) {
+    QualType T = getFunctionOrMethodResultType(D);
+    bool IsKernReturnT = false;
+    while (const auto *TT = T->getAs<TypedefType>()) {
+      IsKernReturnT = (TT->getDecl()->getName() == "kern_return_t");
+      T = TT->desugar();
+    }
+    if (!IsKernReturnT || T.getCanonicalType() != S.getASTContext().IntTy) {
+      S.Diag(D->getBeginLoc(),
+             diag::warn_mig_server_routine_does_not_return_kern_return_t);
+      return;
+    }
+  }
+
+  handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL);
+}
+
 //===----------------------------------------------------------------------===//
 // Top Level Sema Entry Points
 //===----------------------------------------------------------------------===//
@@ -7191,6 +7213,10 @@
   case ParsedAttr::AT_FortifyStdLib:
     handleFortifyStdLib(S, D, AL);
     break;
+
+  case ParsedAttr::AT_MIGServerRoutine:
+    handleMIGServerRoutineAttr(S, D, AL);
+    break;
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to