================
@@ -7064,40 +7078,68 @@ static void CheckMissingFormatAttributes(Sema *S, 
FormatStringType FormatType,
                              : 0;
     break;
   case Sema::FormatArgumentPassingKind::FAPK_Elsewhere:
-    // Args are not passed to the callee.
-    return;
+    // The callee has a format_matches attribute. We will emit that instead.
+    if (!ReferenceFormatString)
+      return;
+    break;
   }
 
   // Emit the diagnostic and fixit.
   unsigned FormatStringIndex = CallerParamIdx + CallerArgumentIndexOffset;
   StringRef FormatTypeName = S->GetFormatStringTypeName(FormatType);
-  {
-    std::string Attr =
-        ("format(" + FormatTypeName + ", " + llvm::Twine(FormatStringIndex) +
-         ", " + llvm::Twine(FirstArgumentIndex) + ")")
-            .str();
+  do {
+    std::string Attr, Fixit;
+    if (APK != Sema::FormatArgumentPassingKind::FAPK_Elsewhere)
+      llvm::raw_string_ostream(Attr)
+          << "format(" << FormatTypeName << ", " << FormatStringIndex << ", "
+          << FirstArgumentIndex << ")";
+    else
+      llvm::raw_string_ostream(Attr)
+          << "format_matches(" << FormatTypeName << ", " << FormatStringIndex
+          << ", \"" << escapeFormatString(ReferenceFormatString->getString())
+          << "\")";
     auto DB = S->Diag(Loc, diag::warn_missing_format_attribute)
               << Attr << Caller;
-    const LangOptions &LO = S->getLangOpts();
-    StringRef AttrPrefix, AttrSuffix;
-    if (LO.C23 || LO.CPlusPlus11) {
-      AttrPrefix = "[[gnu::";
-      AttrSuffix = "]] ";
-    } else if (LO.ObjC || LO.GNUMode) {
-      AttrPrefix = "__attribute__((";
-      AttrSuffix = ")) ";
+
+    SourceLocation SL;
+    llvm::raw_string_ostream IS(Fixit);
+    // The attribute goes at the start of the declaration in C/C++ functions
+    // and methods, but after the declaration for Objective-C methods.
+    if (isa<ObjCMethodDecl>(Caller)) {
+      IS << ' ';
+      SL = Caller->getEndLoc();
     }
-    if (!AttrPrefix.empty()) {
-      DB << FixItHint::CreateInsertion(Caller->getBeginLoc(),
-                                       (AttrPrefix + Attr + AttrSuffix).str());
+    const LangOptions &LO = S->getLangOpts();
+    if (LO.C23 || LO.CPlusPlus11)
+      IS << "[[gnu::" << Attr << "]]";
+    else if (LO.ObjC || LO.GNUMode)
+      IS << "__attribute__((" << Attr << "))";
+    else
+      break;
+    if (!isa<ObjCMethodDecl>(Caller)) {
+      IS << ' ';
+      SL = Caller->getBeginLoc();
     }
-  }
+    IS.flush();
+
+    DB << FixItHint::CreateInsertion(SL, Fixit);
+  } while (false);
   S->Diag(Caller->getLocation(), diag::note_entity_declared_at) << Caller;
+
+  if (APK != Sema::FormatArgumentPassingKind::FAPK_Elsewhere) {
----------------
apple-fcloutier wrote:

We should only do this if `diag::warn_missing_format_attribute` is enabled 
because it can cause new diagnostics to cascade, which users would have no way 
to disable. You can check with 
`!Diag.isIgnored(diag::warn_missing_format_attribute, Loc)`.

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