guitard0g created this revision.
guitard0g added reviewers: aaron.ballman, NoQ, vsavchenko.
guitard0g requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The 'escape' attribute indicates that the annotated pointer parameter
may escape the scope of the function. This attribute is meant to be
used for compiler diagnostics/static analysis checks. The attribute
will first be used by the Swift compiler in a new implicit bridging
diagnostic, but may have other non-Swift use-cases for diagnostics.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D107026

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/AST/ast-dump-attr.cpp
  clang/test/AST/ast-dump-attr.m

Index: clang/test/AST/ast-dump-attr.m
===================================================================
--- clang/test/AST/ast-dump-attr.m
+++ clang/test/AST/ast-dump-attr.m
@@ -65,4 +65,8 @@
 // CHECK-NEXT: | `-NoEscapeAttr
 // CHECK-NEXT: |-ParmVarDecl{{.*}} Test14 'int'
 // CHECK-NEXT: `-NSConsumesSelfAttr
+-(void)Test15: (int *) [[clang::escape]] Test16;
+// CHECK: ObjCMethodDecl{{.*}} Test15: 'void'
+// CHECK-NEXT: -ParmVarDecl{{.*}} Test16 'int *'
+// CHECK-NEXT: `-EscapeAttr
 @end
Index: clang/test/AST/ast-dump-attr.cpp
===================================================================
--- clang/test/AST/ast-dump-attr.cpp
+++ clang/test/AST/ast-dump-attr.cpp
@@ -200,6 +200,15 @@
   // CHECK-NEXT: NoEscapeAttr
 }
 
+namespace TestEscape {
+  void escapeFunc(int *p0, __attribute__((escape)) int *p1) {}
+  // CHECK: NamespaceDecl{{.*}} TestEscape
+  // CHECK-NEXT: `-FunctionDecl{{.*}} escapeFunc 'void (int *, int *)'
+  // CHECK-NEXT: ParmVarDecl
+  // CHECK-NEXT: ParmVarDecl
+  // CHECK-NEXT: EscapeAttr
+}
+
 namespace TestSuppress {
   [[gsl::suppress("at-namespace")]];
   // CHECK: NamespaceDecl{{.*}} TestSuppress
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -1553,11 +1553,11 @@
   D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL));
 }
 
-static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+static void handleXEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   if (D->isInvalidDecl())
     return;
 
-  // noescape only applies to pointer types.
+  // escape/noescape only applies to pointer types.
   QualType T = cast<ParmVarDecl>(D)->getType();
   if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
     S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
@@ -1565,7 +1565,16 @@
     return;
   }
 
-  D->addAttr(::new (S.Context) NoEscapeAttr(S.Context, AL));
+  switch (AL.getKind()) {
+  default:
+    llvm_unreachable("invalid escape attribute");
+  case ParsedAttr::AT_NoEscape:
+    handleSimpleAttribute<NoEscapeAttr>(S, D, AL);
+    return;
+  case ParsedAttr::AT_Escape:
+    handleSimpleAttribute<EscapeAttr>(S, D, AL);
+    return;
+  }
 }
 
 static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -8007,8 +8016,9 @@
   case ParsedAttr::AT_ReturnsNonNull:
     handleReturnsNonNullAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_Escape:
   case ParsedAttr::AT_NoEscape:
-    handleNoEscapeAttr(S, D, AL);
+    handleXEscapeAttr(S, D, AL);
     break;
   case ParsedAttr::AT_AssumeAligned:
     handleAssumeAlignedAttr(S, D, AL);
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -253,6 +253,27 @@
   }];
 }
 
+def EscapeDocs : Documentation {
+  let Category = DocCatVariable;
+  let Content = [{
+``escape`` placed on a function parameter of a pointer type is used to indicate
+that the pointer can escape the function. This means that a reference to the object
+the pointer points to that is derived from the parameter value may survive
+after the function returns.
+
+For example:
+
+.. code-block:: c
+
+  int *gp;
+
+  void escapingFunc(__attribute__((escape)) int *p) {
+    gp = p;
+  }
+
+  }];
+}
+
 def CarriesDependencyDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1949,6 +1949,12 @@
   let Documentation = [NoEscapeDocs];
 }
 
+def Escape : Attr {
+  let Spellings = [Clang<"escape">];
+  let Subjects = SubjectList<[ParmVar]>;
+  let Documentation = [EscapeDocs];
+}
+
 def AssumeAligned : InheritableAttr {
   let Spellings = [GCC<"assume_aligned">];
   let Subjects = SubjectList<[ObjCMethod, Function]>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to