================
@@ -275,22 +416,41 @@ void FactsGenerator::handleFunctionCall(const Expr *Call,
         // For explicit arguments, find the corresponding parameter
         // declaration.
         PVD = Method->getParamDecl(I - 1);
-    } else if (I < FD->getNumParams())
+    } else if (I < FD->getNumParams()) {
       // For free functions or static methods.
       PVD = FD->getParamDecl(I);
+    }
     return PVD ? PVD->hasAttr<clang::LifetimeBoundAttr>() : false;
   };
   if (Args.empty())
     return;
-  bool killedSrc = false;
-  for (unsigned I = 0; I < Args.size(); ++I)
-    if (IsGslConstruction || IsArgLifetimeBound(I)) {
-      if (!killedSrc) {
-        killedSrc = true;
-        killAndFlowOrigin(*Call, *Args[I]);
-      } else
-        flowOrigin(*Call, *Args[I]);
+  bool KillSrc = true;
+  for (unsigned I = 0; I < Args.size(); ++I) {
+    OriginList *ArgList = getOriginsList(*Args[I]);
+    if (!ArgList)
+      continue;
+    if (IsGslConstruction) {
+      // TODO: document with code example.
+      // std::string_view(const std::string_view& from)
+      if (isGslPointerType(Args[I]->getType())) {
+        assert(!Args[I]->isGLValue() || ArgList->getLength() >= 2);
+        ArgList = getRValueOrigins(Args[I], ArgList);
+      }
+      if (isGslOwnerType(Args[I]->getType())) {
+        // GSL construction creates a view that borrows from arguments.
+        // This implies flowing origins through the list structure.
+        flow(CallList, ArgList, KillSrc);
+        KillSrc = false;
+      }
+    } else if (IsArgLifetimeBound(I)) {
+      // Lifetimebound on a non-GSL-ctor function means the returned
----------------
usx95 wrote:

Interesting idea. Started a thread to discuss this further. Postponing for a 
future PR to try this out.

https://github.com/llvm/llvm-project/pull/168344
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to