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

Aaron Puchert via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 24 18:31:19 PDT 2023


================
@@ -435,6 +435,86 @@ bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI,
   return true;
 }
 
+// Warn if parent function does not have builtin function format attribute.
+void Sema::DiagnoseMissingFormatAttributes(NamedDecl *FDecl,
+                                           SourceLocation Loc) {
+  if (!FDecl)
+    return;
+
+  auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl);
+  if (!FD)
+    return;
+
+  unsigned BuiltinID = FD->getBuiltinID(/*ConsiderWrappers=*/true);
+  
+  // Function is not builtin if it's builtin ID is 0.
+  if (!BuiltinID)
+    return;
+
+  // Check if function is one with format attribute.
+  switch (BuiltinID) {
+  case Builtin::BIprintf:
+  case Builtin::BIfprintf:
+  case Builtin::BIsprintf:
+  case Builtin::BIscanf:
+  case Builtin::BIfscanf:
+  case Builtin::BIsscanf:
+  case Builtin::BIvprintf:
+  case Builtin::BIvfprintf:
+  case Builtin::BIvsprintf:
+    break;
+  default: {
+    // In C99 mode check functions below.
+    if (!getLangOpts().C99)
+      return;
+    switch (BuiltinID) {
+    case Builtin::BIsnprintf:
+    case Builtin::BIvsnprintf:
+    case Builtin::BIvscanf:
+    case Builtin::BIvfscanf:
+    case Builtin::BIvsscanf:
+      break;
+    default:
+      return;
+    }
+  }
+  }
+
+  Scope *ParentScope = getCurScope() ? getCurScope()->getFnParent() : nullptr;
+  if (!ParentScope)
+    return;
+
+  DeclContext *ParentScopeEntity = ParentScope->getEntity();
+  if (!ParentScopeEntity)
+    return;
+  if (ParentScopeEntity->getDeclKind() != Decl::Kind::Function)
+    return;
+
+  FunctionDecl *ParentFuncDecl = static_cast<FunctionDecl *>(ParentScopeEntity);
+  if (!ParentFuncDecl)
+    return;
+  if (!ParentFuncDecl->isVariadic())
+    return;
+
+  // Iterate through builtin function format attributes. Then check
+  // if parent function has these attributes. If parent function does
+  // not have builtin function format attribut, emit warning.
+  for (const FormatAttr *Attr : FD->specific_attrs<FormatAttr>()) {
+    bool hasFormatAttr = false;
+    for (const FormatAttr *ParentAttr :
+         ParentFuncDecl->specific_attrs<FormatAttr>()) {
+      if (ParentAttr->getType() == Attr->getType()) {
+        hasFormatAttr = true;
+        break;
+      }
+    }
+    if (!hasFormatAttr) {
+      Diag(Loc, diag::warn_missing_format_attribute)
+          << ParentFuncDecl << Attr->getType();
----------------
aaronpuchert wrote:

Would be cool if we could add a fix-it. There are even ways to find macros that wrap the attribute, see the implementation for `-Wimplicit-fallthrough`.

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


More information about the cfe-commits mailing list