[clang] [clang] Catch missing format attributes (PR #70024)

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 29 08:42:20 PDT 2024


================
@@ -7096,6 +7096,111 @@ static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
 }
 
+// This function is called only if function call is not inside template body.
+// TODO: Add call for function calls inside template body.
+// Check if parent function misses format attribute. If misses, emit warning.
+void Sema::DiagnoseMissingFormatAttributes(const FunctionDecl *FDecl,
+                                           ArrayRef<const Expr *> Args,
+                                           SourceLocation Loc) {
+  assert(FDecl);
+
+  const FunctionDecl *ParentFuncDecl = getCurFunctionDecl();
+  if (!ParentFuncDecl)
+    return;
+
+  // If function is a member of struct/union/class, format attribute argument
+  // indexing starts from 2. Otherwise, it starts from 1.
+  const unsigned int FormatArgumentIndexOffset =
+      isInstanceMethod(FDecl) ? 2 : 1;
+  const unsigned int ParentFunctionFormatArgumentIndexOffset =
+      isInstanceMethod(ParentFuncDecl) ? 2 : 1;
+
+  // Check if function has format attribute with forwarded format string.
+  IdentifierInfo *AttrType;
+  const ParmVarDecl *FormatArg;
+  if (!llvm::any_of(
+          FDecl->specific_attrs<FormatAttr>(), [&](const FormatAttr *Attr) {
+            const int FormatIndexOffseted =
+                Attr->getFormatIdx() - FormatArgumentIndexOffset;
+            if (FormatIndexOffseted < 0 ||
+                (unsigned)FormatIndexOffseted >= Args.size())
+              return false;
+
+            const DeclRefExpr *FormatArgExpr = dyn_cast_or_null<DeclRefExpr>(
+                Args[FormatIndexOffseted]->IgnoreParenCasts());
+            if (!FormatArgExpr)
+              return false;
+
+            FormatArg = dyn_cast_or_null<ParmVarDecl>(
+                FormatArgExpr->getReferencedDeclOfCallee());
+            if (!FormatArg)
+              return false;
+
+            AttrType = Attr->getType();
+            return true;
+          }))
+    return;
+
+  // Check if format string argument is parent function parameter.
+  unsigned int StringIndex = 0;
+  if (!llvm::any_of(ParentFuncDecl->parameters(),
+                    [&](const ParmVarDecl *Param) {
+                      StringIndex = Param->getFunctionScopeIndex() +
+                                    ParentFunctionFormatArgumentIndexOffset;
+
+                      return Param == FormatArg;
+                    }))
+    return;
+
+  unsigned NumOfParentFunctionParams = ParentFuncDecl->getNumParams();
+
+  // Compare parent and calling function format attribute arguments (archetype
+  // and format string).
+  if (llvm::any_of(
+          ParentFuncDecl->specific_attrs<FormatAttr>(),
+          [&](const FormatAttr *Attr) {
+            if (Attr->getType() != AttrType)
+              return false;
+            const int FormatIndexOffseted =
----------------
AaronBallman wrote:

```suggestion
            int FormatIndexOffseted =
```

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


More information about the cfe-commits mailing list