[clang] [llvm] [CaptureTracking][FunctionAttrs] Add support for CaptureInfo (PR #125880)

Nikita Popov via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 6 11:32:58 PST 2025


================
@@ -1303,27 +1341,42 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
       ArgumentSCCNodes.insert(I->Definition);
     }
 
-    bool SCCCaptured = false;
+    // At the SCC level, only track merged CaptureComponents. We're not
+    // currently prepared to handle propagation of return-only captures across
+    // the SCC.
+    CaptureComponents CC = CaptureComponents::None;
     for (ArgumentGraphNode *N : ArgumentSCC) {
       for (ArgumentGraphNode *Use : N->Uses) {
         Argument *A = Use->Definition;
-        if (A->hasNoCaptureAttr() || ArgumentSCCNodes.count(A))
-          continue;
-        SCCCaptured = true;
+        if (ArgumentSCCNodes.count(A))
+          CC |= Use->CC;
+        else
+          CC |= CaptureComponents(A->getAttributes().getCaptureInfo());
         break;
       }
-      if (SCCCaptured)
+      if (capturesAll(CC))
         break;
     }
-    if (SCCCaptured)
-      continue;
 
-    for (ArgumentGraphNode *N : ArgumentSCC) {
-      Argument *A = N->Definition;
-      A->addAttr(
-          Attribute::getWithCaptureInfo(A->getContext(), CaptureInfo::none()));
-      ++NumNoCapture;
-      Changed.insert(A->getParent());
+    if (!capturesAll(CC)) {
+      for (ArgumentGraphNode *N : ArgumentSCC) {
+        Argument *A = N->Definition;
+        CaptureInfo CI = N->CC | CC;
+        A->addAttr(Attribute::getWithCaptureInfo(A->getContext(), CI));
+        addCapturesStat(CI);
+        Changed.insert(A->getParent());
+      }
+    }
+
+    // TODO(captures): Ignore address-only captures.
+    if (!capturesNothing(CC)) {
+      // As the pointer may be captured, determine the pointer attributes
+      // looking at each argument invidivually.
+      for (ArgumentGraphNode *N : ArgumentSCC) {
+        if (DetermineAccessAttrsForSingleton(N->Definition))
+          Changed.insert(N->Definition->getParent());
+      }
----------------
nikic wrote:

For the SCC case, we skip inferring the access attributes initially, so we have to do it after we're done handling the SCC. If we infer captures(none) we can do the access attribute inference over the whole SCC, which is what the code below this does. If we don't, we can fall back on inferring for each argument individually, which is what the new code here does.

This is more useful to do now than previously because we can have states between captures(none) and captures(all).

https://github.com/llvm/llvm-project/pull/125880


More information about the cfe-commits mailing list