================
@@ -7001,6 +7005,85 @@ bool Sema::CheckFormatString(const FormatMatchesAttr 
*Format,
   return false;
 }
 
+static void CheckMissingFormatAttributes(Sema *S, FormatStringType FormatType,
+                                         unsigned FormatIdx, unsigned FirstArg,
+                                         ArrayRef<const Expr *> Args,
+                                         Sema::FormatArgumentPassingKind APK,
+                                         unsigned CallerParamIdx,
+                                         SourceLocation Loc) {
+  const FunctionDecl *Caller = S->getCurFunctionDecl();
+  if (!Caller)
+    return;
+
+  // Find the offset to convert between attribute and parameter indexes.
+  unsigned CallerArgumentIndexOffset =
+      hasImplicitObjectParameter(Caller) ? 2 : 1;
+
+  unsigned FirstArgumentIndex = -1;
+  switch (APK) {
+  case Sema::FormatArgumentPassingKind::FAPK_Fixed:
+  case Sema::FormatArgumentPassingKind::FAPK_Variadic: {
+    // As an extension, clang allows the format attribute on non-variadic
+    // functions.
+    // Caller must have fixed arguments to pass them to a fixed or variadic
+    // function. Try to match caller and callee arguments. If successful, then
+    // emit a diag with the caller idx, otherwise we can't determine the callee
+    // arguments.
+    unsigned NumCalleeArgs = Args.size() - FirstArg;
+    if (NumCalleeArgs == 0 || Caller->getNumParams() < NumCalleeArgs) {
+      // There aren't enough arugments in the caller to pass to callee.
+      return;
+    }
+    for (unsigned CalleeIdx = Args.size() - 1,
+                  CallerIdx = Caller->getNumParams() - 1;
+         CalleeIdx >= FirstArg; --CalleeIdx, --CallerIdx) {
+      const auto *Arg =
+          dyn_cast<DeclRefExpr>(Args[CalleeIdx]->IgnoreParenCasts());
+      if (!Arg)
+        return;
+      const auto *Param = dyn_cast<ParmVarDecl>(Arg->getDecl());
+      if (!Param || Param->getFunctionScopeIndex() != CallerIdx)
+        return;
+    }
+    FirstArgumentIndex =
+        Caller->getNumParams() + CallerArgumentIndexOffset - NumCalleeArgs;
+    break;
+  }
+  case Sema::FormatArgumentPassingKind::FAPK_VAList:
+    // Caller arguments are either variadic or a va_list.
+    FirstArgumentIndex =
+        Caller->isVariadic()
+            ? (Caller->getNumParams() + CallerArgumentIndexOffset)
+            : 0;
+    break;
+  case Sema::FormatArgumentPassingKind::FAPK_Elsewhere:
+    // Args are not passed to the callee.
----------------
vvuksanovic wrote:

Looking further into this, I can suggest `format_matches` in a diagnostic 
message, but there are some problematic cases for creating the actual format 
string parameter to `format_matches` from the call arguments. From the 
attribute docs:

> While checks for the format attribute tolerate sone size mismatches that 
> standard argument promotion renders immaterial (such as formatting an int 
> with %hhd, which specifies a char-sized integer), checks for format_matches 
> require specified argument sizes to match exactly.

In this case the actual format string might be "%d", but pass a char argument. 
That is correct because of arg promotion, but based on the arg type, I would 
deduce this as "%c".

> Format strings expecting a variable modifier (such as %*s) are incompatible 
> with format strings that would itemize the variable modifiers (such as %i 
> %s), even if the two specify ABI-compatible argument lists.

This is a bigger problem as it can't be deduced only based on the arguments.

> All pointer specifiers, modifiers aside, are mutually incompatible. For 
> instance, %s is not compatible with %p, and %p is not compatible with %n, and 
> %hhn is incompatible with %s, even if the pointers are ABI-compatible or 
> identical on the selected platform.

Similarly, some pointer type specifiers can't be determined based on the 
argument type. For example `const char *` could be printed as '%s' or '%p'.

Should I just emit a diagnostic without specific attribute parameters in this 
case?

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

Reply via email to