@@ -53,6 +53,8 @@ class UnsafeUse {
5353 ReferenceToUnsafeThroughTypealias,
5454 // / A call to an unsafe declaration.
5555 CallToUnsafe,
56+ // / An unsafe argument in a call.
57+ CallArgument,
5658 // / A @preconcurrency import.
5759 PreconcurrencyImport,
5860 // / A use of withoutActuallyEscaping that lacks enforcement that the
@@ -91,6 +93,15 @@ class UnsafeUse {
9193
9294 MakeTemporarilyEscapableExpr *temporarilyEscaping;
9395
96+ struct {
97+ Expr *call;
98+ const Decl *calleeDecl;
99+ TypeBase *paramType;
100+ const void *argumentName;
101+ unsigned argumentIndex;
102+ Expr *argument;
103+ } callArgument;
104+
94105 const ImportDecl *importDecl;
95106 } storage;
96107
@@ -201,6 +212,19 @@ class UnsafeUse {
201212 decl, type, location);
202213 }
203214
215+ static UnsafeUse forCallArgument (
216+ Expr *call, const Decl *calleeDecl, Type paramType,
217+ Identifier argumentName, unsigned argumentIndex, Expr *argument) {
218+ UnsafeUse result (CallArgument);
219+ result.storage .callArgument .call = call;
220+ result.storage .callArgument .calleeDecl = calleeDecl;
221+ result.storage .callArgument .paramType = paramType.getPointer ();
222+ result.storage .callArgument .argumentName = argumentName.getAsOpaquePointer ();
223+ result.storage .callArgument .argumentIndex = argumentIndex;
224+ result.storage .callArgument .argument = argument;
225+ return result;
226+ }
227+
204228 static UnsafeUse forTemporarilyEscaping (MakeTemporarilyEscapableExpr *expr) {
205229 UnsafeUse result (TemporarilyEscaping);
206230 result.storage .temporarilyEscaping = expr;
@@ -242,6 +266,9 @@ class UnsafeUse {
242266 return SourceLoc (
243267 llvm::SMLoc::getFromPointer ((const char *)storage.entity .location ));
244268
269+ case CallArgument:
270+ return storage.callArgument .call ->getLoc ();
271+
245272 case TemporarilyEscaping:
246273 return storage.temporarilyEscaping ->getLoc ();
247274
@@ -257,6 +284,7 @@ class UnsafeUse {
257284 case Witness:
258285 case TemporarilyEscaping:
259286 case PreconcurrencyImport:
287+ case CallArgument:
260288 // Cannot replace location.
261289 return ;
262290
@@ -298,6 +326,9 @@ class UnsafeUse {
298326 case CallToUnsafe:
299327 return storage.entity .decl ;
300328
329+ case CallArgument:
330+ return storage.callArgument .calleeDecl ;
331+
301332 case UnsafeConformance:
302333 case TemporarilyEscaping:
303334 return nullptr ;
@@ -330,6 +361,7 @@ class UnsafeUse {
330361 case ReferenceToUnsafeThroughTypealias:
331362 case ReferenceToUnsafeStorage:
332363 case CallToUnsafe:
364+ case CallArgument:
333365 case UnsafeConformance:
334366 case PreconcurrencyImport:
335367 case TemporarilyEscaping:
@@ -360,6 +392,9 @@ class UnsafeUse {
360392 case CallToUnsafe:
361393 return storage.entity .type ;
362394
395+ case CallArgument:
396+ return storage.callArgument .paramType ;
397+
363398 case TemporarilyEscaping:
364399 return storage.temporarilyEscaping ->getOpaqueValue ()->getType ();
365400 }
@@ -386,11 +421,24 @@ class UnsafeUse {
386421 case ReferenceToUnsafeStorage:
387422 case ReferenceToUnsafeThroughTypealias:
388423 case CallToUnsafe:
424+ case CallArgument:
389425 case TemporarilyEscaping:
390426 case PreconcurrencyImport:
391427 return ProtocolConformanceRef::forInvalid ();
392428 }
393429 }
430+
431+ // / Get information about the call argument.
432+ // /
433+ // / Produces the argument name, argument index, and argument expression for
434+ // / a unsafe use describing a call argument.
435+ std::tuple<Identifier, unsigned , Expr *> getCallArgument () const {
436+ assert (getKind () == CallArgument);
437+ return std::make_tuple (
438+ Identifier::getFromOpaquePointer (storage.callArgument .argumentName ),
439+ storage.callArgument .argumentIndex ,
440+ storage.callArgument .argument );
441+ }
394442};
395443
396444} // end namespace swift
0 commit comments