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

Aaron Puchert via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 9 10:13:29 PDT 2024


================
@@ -5335,6 +5335,230 @@ static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   D->addAttr(::new (S.Context) PreferredTypeAttr(S.Context, AL, ParmTSI));
 }
 
+// Returns vector of format attributes. There are no two attributes with same
+// arguments in returning vector. There can be attributes that effectively only
+// store information about format type.
+static std::vector<FormatAttr *>
+GetMissingFormatAttributes(Sema &S, Stmt *Body, const FunctionDecl *FDecl) {
+  unsigned int ArgumentIndexOffset =
+      checkIfMethodHasImplicitObjectParameter(FDecl) ? 2 : 1;
+
+  std::vector<FormatAttr *> MissingAttributes;
+
+  // Iterate over body statements.
+  for (auto *Child : Body->children()) {
+    // If child statement is compound statement, recursively get missing
+    // attributes.
+    if (dyn_cast_or_null<CompoundStmt>(Child)) {
+      std::vector<FormatAttr *> CompoundStmtMissingAttributes =
+          GetMissingFormatAttributes(S, Child, FDecl);
+
+      // If there are already missing attributes with same arguments, do not add
+      // duplicates.
+      for (FormatAttr *FA : CompoundStmtMissingAttributes) {
+        if (!llvm::any_of(MissingAttributes, [&](const FormatAttr *Attr) {
+              return FA->getType() == Attr->getType() &&
+                     FA->getFormatIdx() == Attr->getFormatIdx() &&
+                     FA->getFirstArg() == Attr->getFirstArg();
+            }))
+          MissingAttributes.push_back(FA);
+      }
+
+      continue;
+    }
+
+    ValueStmt *VS = dyn_cast<ValueStmt>(Child);
+    if (!VS)
+      continue;
+    CallExpr *TheCall = dyn_cast_or_null<CallExpr>(VS->getExprStmt());
+    if (!TheCall)
+      continue;
+
+    const FunctionDecl *CalleeFunction =
+        dyn_cast_or_null<FunctionDecl>(TheCall->getCalleeDecl());
+    if (!CalleeFunction || !CalleeFunction->hasAttr<FormatAttr>())
+      continue;
+
+    // va_list is not intended to be passed to variadic function.
+    if (CalleeFunction->isVariadic())
+      continue;
----------------
aaronpuchert wrote:

That's true, but my understanding is that checking the format string could still happen. And shouldn't we take the attribute on the callee into account? The variadic arguments could be unrelated to formatting.

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


More information about the cfe-commits mailing list