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

Aaron Puchert via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 10 14:06:45 PST 2023


================
@@ -6849,6 +6849,73 @@ static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
 }
 
+// Warn if parent function misses format attribute. Parent function misses
+// format attribute if there is an argument format string forwarded to calling
+// function with format attribute, parent function has a parameter which type
+// is either string or pointer to char and parent function format attribute
+// type does not match with calling function format attribute type.
+void Sema::DiagnoseMissingFormatAttributes(const FunctionDecl *FDecl,
+                                           ArrayRef<const Expr *> Args,
+                                           SourceLocation Loc) {
+  assert(FDecl);
+
+  // Check if function has format attribute with forwarded format string.
+  IdentifierInfo *AttrType;
+  if (!llvm::any_of(
+          FDecl->specific_attrs<FormatAttr>(), [&](const FormatAttr *Attr) {
+            if (!Args[Attr->getFirstArg()]->getReferencedDeclOfCallee())
+              return false;
+
+            AttrType = Attr->getType();
+            return true;
+          }))
+    return;
+
+  const FunctionDecl *ParentFuncDecl = getCurFunctionDecl();
+  if (!ParentFuncDecl)
+    return;
+
+  // Check if parent function has string or pointer to char parameter.
+  unsigned int StringIndex = 0;
+  if (!llvm::any_of(
+          ParentFuncDecl->parameters(), [&](const ParmVarDecl *Param) {
+            StringIndex = Param->getFunctionScopeIndex() + 1;
+            QualType Ty = Param->getType();
+            if (isNSStringType(Ty, Context, true))
+              return true;
+            if (isCFStringType(Ty, Context))
+              return true;
+            if (Ty->isPointerType() &&
+                Ty->castAs<PointerType>()
+                    ->getPointeeType()
+                    ->isSpecificBuiltinType(BuiltinType::Char_S))
+              return true;
+            return false;
+          }))
+    return;
+
+  // Check if there is parent function format attribute which type matches
+  // calling function format attribute type.
+  if (llvm::any_of(
+          ParentFuncDecl->specific_attrs<FormatAttr>(),
+          [&](const FormatAttr *Attr) { return Attr->getType() == AttrType; }))
+    return;
+
+  unsigned int FirstToCheck =
+      ParentFuncDecl->isVariadic() ? (ParentFuncDecl->getNumParams() + 1) : 0;
+
+  // Diagnose missing format attributes
+  std::string InsertionText;
+  llvm::raw_string_ostream OS(InsertionText);
+  OS << "__attribute__((format(" << AttrType->getName() << ", "
+     << std::to_string(StringIndex) << ", " << std::to_string(FirstToCheck)
----------------
aaronpuchert wrote:

I'm surprised that we need `std::to_string` here, can `llvm::raw_string_ostream` not print integers directly?

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


More information about the cfe-commits mailing list