[clang] [analyzer][NFC] Document and centralize the CallEvent argument/parameter index mapping (PR #221252)

DonĂ¡t Nagy via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 04:10:18 PDT 2026


================
@@ -466,52 +474,71 @@ static SVal castArgToParamTypeIfNeeded(const CallEvent &Call, unsigned ArgIdx,
     return ArgVal;
 
   // Only do this cast if the number arguments at the callsite matches with
-  // the parameters at the runtime definition.
+  // the parameters at the runtime definition. Note that this point is only
+  // reached for C functions without a prototype, so the argument indices
+  // and the declared parameter indices coincide.
   if (Call.getNumArgs() != Definition->getNumParams())
     return UnknownVal();
 
-  const Expr *ArgExpr = Call.getArgExpr(ArgIdx);
-  const ParmVarDecl *Param = Definition->getParamDecl(ArgIdx);
+  const ParmVarDecl *Param = Definition->getParamDecl(DeclParamIdx);
   return SVB.evalCast(ArgVal, Param->getType(), ArgExpr->getType());
 }
 
+/// Binds the value of a single argument to the region of the parameter it
+/// initializes in the callee's stack frame.
+///
+/// \param ParamDecl the declared parameter initialized by this argument.
+/// \param DeclParamIdx index of \p ParamDecl among the callee's declared
+/// parameters. See CallEvent::getDeclaredParameterIndex().
+static void addParameterValueToBindings(const StackFrame *CalleeSF,
+                                        CallEvent::BindingsTy &Bindings,
+                                        SValBuilder &SVB, const CallEvent &Call,
+                                        const ParmVarDecl *ParamDecl,
+                                        unsigned DeclParamIdx, unsigned Idx) {
+  assert(ParamDecl && "Formal parameter has no decl?");
+
+  // TODO: Support allocator calls.
+  if (Call.getKind() != CE_CXXAllocator)
+    if (Call.isArgumentConstructedDirectly(Call.getASTArgumentIndex(Idx)))
+      return;
+
+  SVal ArgVal = Call.getArgSVal(Idx);
+  // TODO: Allocators should receive the correct size and possibly alignment,
+  // determined in compile-time but not represented as arg-expressions,
+  // which makes getArgSVal() fail and return UnknownVal.
+  if (ArgVal.isUnknown())
+    return;
+  const Expr *ArgExpr = Call.getArgExpr(Idx);
+  // Cast the argument value to match the type of the parameter in some
+  // edge-cases.
+  ArgVal = castArgToParamTypeIfNeeded(Call, DeclParamIdx, ArgExpr, ArgVal, SVB);
+
+  Loc ParamLoc = SVB.makeLoc(SVB.getRegionManager().getParamVarRegion(
+      Call.getOriginExpr(), DeclParamIdx, CalleeSF));
+  Bindings.emplace_back(ParamLoc,
+                        processArgument(ArgVal, ArgExpr, ParamDecl, SVB));
+}
+
 static void addParameterValuesToBindings(const StackFrame *CalleeSF,
                                          CallEvent::BindingsTy &Bindings,
                                          SValBuilder &SVB,
                                          const CallEvent &Call,
                                          ArrayRef<ParmVarDecl *> parameters) {
-  MemRegionManager &MRMgr = SVB.getRegionManager();
-
-  // If the function has fewer parameters than the call has arguments, we simply
-  // do not bind any values to them.
-  unsigned NumArgs = Call.getNumArgs();
-  unsigned Idx = 0;
-  ArrayRef<ParmVarDecl*>::iterator I = parameters.begin(), E = parameters.end();
-  for (; I != E && Idx < NumArgs; ++I, ++Idx) {
-    assert(*I && "Formal parameter has no decl?");
-
-    // TODO: Support allocator calls.
-    if (Call.getKind() != CE_CXXAllocator)
-      if (Call.isArgumentConstructedDirectly(Call.getASTArgumentIndex(Idx)))
-        continue;
-
-    // TODO: Allocators should receive the correct size and possibly alignment,
-    // determined in compile-time but not represented as arg-expressions,
-    // which makes getArgSVal() fail and return UnknownVal.
-    SVal ArgVal = Call.getArgSVal(Idx);
-    const Expr *ArgExpr = Call.getArgExpr(Idx);
-
-    if (ArgVal.isUnknown())
+  for (unsigned Idx = 0, NumArgs = Call.getNumArgs(); Idx != NumArgs; ++Idx) {
+    // An argument that doesn't initialize a declared parameter, such as the
+    // object argument of an overloaded operator call.
----------------
NagyDonat wrote:

Good point, you're right that it is mentioned there.

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


More information about the cfe-commits mailing list