[llvm-branch-commits] [clang] f1a5264 - Revert "[clang] Catch missing format attributes (#70024)"

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jul 12 03:57:51 PDT 2024


Author: Aaron Ballman
Date: 2024-07-12T06:57:49-04:00
New Revision: f1a52644e84021dded1fa5e58401cf23b8c519e6

URL: https://github.com/llvm/llvm-project/commit/f1a52644e84021dded1fa5e58401cf23b8c519e6
DIFF: https://github.com/llvm/llvm-project/commit/f1a52644e84021dded1fa5e58401cf23b8c519e6.diff

LOG: Revert "[clang] Catch missing format attributes (#70024)"

This reverts commit 70f57d25743ca7230bcad3cae7e3072f0aded6f7.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Attr.h
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaDeclAttr.cpp

Removed: 
    clang/test/Sema/attr-format-missing.c
    clang/test/Sema/attr-format-missing.cpp


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index afcd3c655f0f6..781fc8ab1de1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -716,9 +716,6 @@ Improvements to Clang's diagnostics
 
 - Clang now diagnoses integer constant expressions that are folded to a constant value as an extension in more circumstances. Fixes #GH59863
 
-- Clang now diagnoses missing format attributes for non-template functions and
-  class/struct/union members. Fixes #GH60718
-
 Improvements to Clang's time-trace
 ----------------------------------
 

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index da6a3b2fe3571..2241f8481484e 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -525,6 +525,7 @@ def MainReturnType : DiagGroup<"main-return-type">;
 def MaxUnsignedZero : DiagGroup<"max-unsigned-zero">;
 def MissingBraces : DiagGroup<"missing-braces">;
 def MissingDeclarations: DiagGroup<"missing-declarations">;
+def : DiagGroup<"missing-format-attribute">;
 def MissingIncludeDirs : DiagGroup<"missing-include-dirs">;
 def MissingNoreturn : DiagGroup<"missing-noreturn">;
 def MultiChar : DiagGroup<"multichar">;

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f5c18edb65217..0ea3677355169 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1031,9 +1031,6 @@ def err_opencl_invalid_param : Error<
 def err_opencl_invalid_return : Error<
   "declaring function return value of type %0 is not allowed %select{; did you forget * ?|}1">;
 def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
-def warn_missing_format_attribute : Warning<
-  "diagnostic behavior may be improved by adding the %0 format attribute to the declaration of %1">,
-  InGroup<DiagGroup<"missing-format-attribute">>, DefaultIgnore;
 def warn_pragma_options_align_reset_failed : Warning<
   "#pragma options align=reset failed: %0">,
   InGroup<IgnoredPragmas>;

diff  --git a/clang/include/clang/Sema/Attr.h b/clang/include/clang/Sema/Attr.h
index 37c124ca7b454..3f0b10212789a 100644
--- a/clang/include/clang/Sema/Attr.h
+++ b/clang/include/clang/Sema/Attr.h
@@ -123,13 +123,6 @@ inline bool isInstanceMethod(const Decl *D) {
   return false;
 }
 
-inline bool checkIfMethodHasImplicitObjectParameter(const Decl *D) {
-  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
-    return MethodDecl->isInstance() &&
-           !MethodDecl->hasCXXExplicitFunctionObjectParameter();
-  return false;
-}
-
 /// Diagnose mutually exclusive attributes when present on a given
 /// declaration. Returns true if diagnosed.
 template <typename AttrTy>

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e30252749d2c3..6be6f6725e5b7 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4594,10 +4594,6 @@ class Sema final : public SemaBase {
 
   enum class RetainOwnershipKind { NS, CF, OS };
 
-  void DiagnoseMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl);
-  std::vector<FormatAttr *>
-  GetMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl);
-
   UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
                           StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0039df2a21bc6..80b5a8cd4bae6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15934,8 +15934,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
         }
       }
 
-      DiagnoseMissingFormatAttributes(Body, FD);
-
       // We might not have found a prototype because we didn't wish to warn on
       // the lack of a missing prototype. Try again without the checks for
       // whether we want to warn on the missing prototype.

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 5166e61bb41d4..f2cd46d1e7c93 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3508,7 +3508,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
 
   // In C++ the implicit 'this' function parameter also counts, and they are
   // counted from one.
-  bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter(D);
+  bool HasImplicitThisParam = isInstanceMethod(D);
   unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
 
   IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
@@ -3621,7 +3621,7 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     return;
   }
 
-  bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter(D);
+  bool HasImplicitThisParam = isInstanceMethod(D);
   int32_t NumArgs = getFunctionOrMethodNumParams(D);
 
   FunctionDecl *FD = D->getAsFunction();
@@ -5320,221 +5320,6 @@ static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   D->addAttr(::new (S.Context) PreferredTypeAttr(S.Context, AL, ParmTSI));
 }
 
-// This function is called only if function call is not inside template body.
-// TODO: Add call for function calls inside template body.
-// Emit warnings if parent function misses format attributes.
-void Sema::DiagnoseMissingFormatAttributes(Stmt *Body,
-                                           const FunctionDecl *FDecl) {
-  assert(FDecl);
-
-  // If there are no function body, exit.
-  if (!Body)
-    return;
-
-  // Get missing format attributes
-  std::vector<FormatAttr *> MissingFormatAttributes =
-      GetMissingFormatAttributes(Body, FDecl);
-  if (MissingFormatAttributes.empty())
-    return;
-
-  // Check if there are more than one format type found. In that case do not
-  // emit diagnostic.
-  const FormatAttr *FirstAttr = MissingFormatAttributes[0];
-  if (llvm::any_of(MissingFormatAttributes, [&](const FormatAttr *Attr) {
-        return FirstAttr->getType() != Attr->getType();
-      }))
-    return;
-
-  for (const FormatAttr *FA : MissingFormatAttributes) {
-    // If format index and first-to-check argument index are negative, it means
-    // that this attribute is only saved for multiple format types checking.
-    if (FA->getFormatIdx() < 0 || FA->getFirstArg() < 0)
-      continue;
-
-    // Emit diagnostic
-    SourceLocation Loc = FDecl->getLocation();
-    Diag(Loc, diag::warn_missing_format_attribute)
-        << FA->getType() << FDecl
-        << FixItHint::CreateInsertion(Loc,
-                                      (llvm::Twine("__attribute__((format(") +
-                                       FA->getType()->getName() + ", " +
-                                       llvm::Twine(FA->getFormatIdx()) + ", " +
-                                       llvm::Twine(FA->getFirstArg()) + ")))")
-                                          .str());
-  }
-}
-
-// Returns vector of format attributes. There are no two attributes with same
-// arguments in returning vector. There can be attributes that effectivelly only
-// store information about format type.
-std::vector<FormatAttr *>
-Sema::GetMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl) {
-  unsigned int FunctionFormatArgumentIndexOffset =
-      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(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_or_null<ValueStmt>(Child);
-    if (!VS)
-      continue;
-    Expr *TheExpr = VS->getExprStmt();
-    if (!TheExpr)
-      continue;
-    CallExpr *TheCall = dyn_cast_or_null<CallExpr>(TheExpr);
-    if (!TheCall)
-      continue;
-    const FunctionDecl *ChildFunction =
-        dyn_cast_or_null<FunctionDecl>(TheCall->getCalleeDecl());
-    if (!ChildFunction)
-      continue;
-
-    Expr **Args = TheCall->getArgs();
-    unsigned int NumArgs = TheCall->getNumArgs();
-
-    // If child expression is function, check if it is format function.
-    // If it is, check if parent function misses format attributes.
-
-    // If child function is format function and format arguments are not
-    // relevant to emit diagnostic, save only information about format type
-    // (format index and first-to-check argument index are set to -1).
-    // Information about format type is later used to determine if there are
-    // more than one format type found.
-
-    unsigned int ChildFunctionFormatArgumentIndexOffset =
-        checkIfMethodHasImplicitObjectParameter(ChildFunction) ? 2 : 1;
-
-    // Check if function has format attribute with forwarded format string.
-    IdentifierInfo *AttrType;
-    const ParmVarDecl *FormatArg;
-    if (!llvm::any_of(ChildFunction->specific_attrs<FormatAttr>(),
-                      [&](const FormatAttr *Attr) {
-                        AttrType = Attr->getType();
-
-                        int OffsetFormatIndex =
-                            Attr->getFormatIdx() -
-                            ChildFunctionFormatArgumentIndexOffset;
-                        if (OffsetFormatIndex < 0 ||
-                            (unsigned)OffsetFormatIndex >= NumArgs)
-                          return false;
-
-                        const auto *FormatArgExpr = dyn_cast<DeclRefExpr>(
-                            Args[OffsetFormatIndex]->IgnoreParenCasts());
-                        if (!FormatArgExpr)
-                          return false;
-
-                        FormatArg = dyn_cast_or_null<ParmVarDecl>(
-                            FormatArgExpr->getReferencedDeclOfCallee());
-                        if (!FormatArg)
-                          return false;
-
-                        return true;
-                      })) {
-      MissingAttributes.push_back(
-          FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
-      continue;
-    }
-
-    // Do not add in a vector format attributes whose type is 
diff erent than
-    // parent function attribute type.
-    if (llvm::any_of(FDecl->specific_attrs<FormatAttr>(),
-                     [&](const FormatAttr *FunctionAttr) {
-                       return AttrType != FunctionAttr->getType();
-                     }))
-      continue;
-
-    // Check if format string argument is parent function parameter.
-    unsigned int StringIndex = 0;
-    if (!llvm::any_of(FDecl->parameters(), [&](const ParmVarDecl *Param) {
-          if (Param != FormatArg)
-            return false;
-
-          StringIndex = Param->getFunctionScopeIndex() +
-                        FunctionFormatArgumentIndexOffset;
-
-          return true;
-        })) {
-      MissingAttributes.push_back(
-          FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
-      continue;
-    }
-
-    unsigned NumOfParentFunctionParams = FDecl->getNumParams();
-
-    // Compare parent and calling function format attribute arguments (archetype
-    // and format string).
-    if (llvm::any_of(
-            FDecl->specific_attrs<FormatAttr>(), [&](const FormatAttr *Attr) {
-              if (Attr->getType() != AttrType)
-                return false;
-              int OffsetFormatIndex =
-                  Attr->getFormatIdx() - FunctionFormatArgumentIndexOffset;
-
-              if (OffsetFormatIndex < 0 ||
-                  (unsigned)OffsetFormatIndex >= NumOfParentFunctionParams)
-                return false;
-
-              if (FDecl->parameters()[OffsetFormatIndex] != FormatArg)
-                return false;
-
-              return true;
-            })) {
-      MissingAttributes.push_back(
-          FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
-      continue;
-    }
-
-    // Get first argument index
-    unsigned FirstToCheck = [&]() -> unsigned {
-      if (!FDecl->isVariadic())
-        return 0;
-      const auto *FirstToCheckArg =
-          dyn_cast<DeclRefExpr>(Args[NumArgs - 1]->IgnoreParenCasts());
-      if (!FirstToCheckArg)
-        return 0;
-
-      if (FirstToCheckArg->getType().getCanonicalType() !=
-          Context.getBuiltinVaListType().getCanonicalType())
-        return 0;
-      return NumOfParentFunctionParams + FunctionFormatArgumentIndexOffset;
-    }();
-
-    // If there are already attributes which arguments matches arguments
-    // detected in this iteration, do not add new attribute as it would be
-    // duplicate.
-    if (!llvm::any_of(MissingAttributes, [&](const FormatAttr *Attr) {
-          return Attr->getType() == AttrType &&
-                 Attr->getFormatIdx() == StringIndex &&
-                 Attr->getFirstArg() == FirstToCheck;
-        }))
-      MissingAttributes.push_back(FormatAttr::CreateImplicit(
-          getASTContext(), AttrType, StringIndex, FirstToCheck));
-  }
-
-  return MissingAttributes;
-}
-
 //===----------------------------------------------------------------------===//
 // Microsoft specific attribute handlers.
 //===----------------------------------------------------------------------===//

diff  --git a/clang/test/Sema/attr-format-missing.c b/clang/test/Sema/attr-format-missing.c
deleted file mode 100644
index 4f9e91eb1becb..0000000000000
--- a/clang/test/Sema/attr-format-missing.c
+++ /dev/null
@@ -1,403 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,c_diagnostics -Wmissing-format-attribute %s
-// RUN: %clang_cc1 -fsyntax-only -Wmissing-format-attribute -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s --check-prefixes=CHECK,C-CHECK
-// RUN: %clang_cc1 -fsyntax-only -x c++ -verify=expected,cpp_diagnostics -Wmissing-format-attribute %s
-// RUN: %clang_cc1 -fsyntax-only -x c++ -verify=expected,cpp_diagnostics -std=c++2b -Wmissing-format-attribute %s
-// RUN: %clang_cc1 -fsyntax-only -x c++ -verify=expected,cpp_diagnostics -std=c++23 -Wmissing-format-attribute %s
-// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple x86_64-linux %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-LIN64
-// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple x86_64-windows %s 2>&1 | FileCheck %s --check-prefixes=CHECK
-// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple i386-windows %s 2>&1 | FileCheck %s --check-prefixes=CHECK
-// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple i386-windows %s 2>&1 | FileCheck %s --check-prefixes=CHECK
-
-#ifndef __cplusplus
-typedef unsigned short char16_t;
-typedef unsigned int char32_t;
-typedef __WCHAR_TYPE__ wchar_t;
-#endif
-
-typedef __SIZE_TYPE__ size_t;
-typedef __builtin_va_list va_list;
-
-__attribute__((__format__(__printf__, 1, 2)))
-int printf(const char *, ...); // #printf
-
-__attribute__((__format__(__scanf__, 1, 2)))
-int scanf(const char *, ...); // #scanf
-
-__attribute__((__format__(__printf__, 1, 0)))
-int vprintf(const char *, va_list); // #vprintf
-
-__attribute__((__format__(__scanf__, 1, 0)))
-int vscanf(const char *, va_list); // #vscanf
-
-__attribute__((__format__(__printf__, 2, 0)))
-int vsprintf(char *, const char *, va_list); // #vsprintf
-
-__attribute__((__format__(__printf__, 3, 0)))
-int vsnprintf(char *ch, size_t, const char *, va_list); // #vsnprintf
-
-__attribute__((__format__(__scanf__, 1, 4)))
-void f1(char *out, const size_t len, const char *format, ... /* args */) // #f1
-{
-    va_list args;
-    vsnprintf(out, len, format, args); // expected-no-warning@#f1
-}
-
-__attribute__((__format__(__printf__, 1, 4)))
-void f2(char *out, const size_t len, const char *format, ... /* args */) // #f2
-{
-    va_list args;
-    vsnprintf(out, len, format, args); // expected-warning@#f2 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f2'}}
-                                       // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 3, 4)))"
-}
-
-void f3(char *out, va_list args) // #f3
-{
-    vprintf(out, args); // expected-warning@#f3 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f3'}}
-                        // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:6-[[@LINE-3]]:6}:"__attribute__((format(printf, 1, 0)))"
-}
-
-void f4(char* out, ... /* args */) // #f4
-{
-    va_list args;
-    vprintf("test", args); // expected-no-warning@#f4
-
-    const char *ch;
-    vprintf(ch, args); // expected-no-warning@#f4
-}
-
-void f5(va_list args) // #f5
-{
-    char *ch;
-    vscanf(ch, args); // expected-no-warning@#f5
-}
-
-void f6(char *out, va_list args) // #f6
-{
-    char *ch;
-    vprintf(ch, args); // expected-no-warning@#f6
-    vprintf("test", args); // expected-no-warning@#f6
-    vprintf(out, args); // expected-warning@#f6 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f6'}}
-                        // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(printf, 1, 0)))"
-}
-
-void f7(const char *out, ... /* args */) // #f7
-{
-    va_list args;
-
-    vscanf(out, &args[0]); // expected-warning@#f7 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f7'}}
-                           // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:6-[[@LINE-5]]:6}:"__attribute__((format(scanf, 1, 0)))"
-}
-
-void f8(const char *out, ... /* args */) // #f8
-{
-    va_list args;
-
-    vscanf(out, &args[0]); // expected-no-warning@#f8
-    vprintf(out, &args[0]); // expected-no-warning@#f8
-}
-
-void f9(const char out[], ... /* args */) // #f9
-{
-    va_list args;
-    char *ch;
-    vprintf(ch, args); // expected-no-warning
-    vsprintf(ch, out, args); // expected-warning@#f9 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f9'}}
-                             // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(printf, 1, 2)))"
-}
-
-void f10(const wchar_t *out, ... /* args */) // #f10
-{
-    va_list args;
-    vscanf(out, args);
-#if __SIZEOF_WCHAR_T__ == 4
-                        // c_diagnostics-warning at -2 {{incompatible pointer types passing 'const wchar_t *' (aka 'const int *') to parameter of type 'const char *'}}
-#else
-                        // c_diagnostics-warning at -4 {{incompatible pointer types passing 'const wchar_t *' (aka 'const unsigned short *') to parameter of type 'const char *'}}
-#endif
-                        // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                        // c_diagnostics-warning@#f10 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f10'}}
-                        // cpp_diagnostics-error at -8 {{no matching function for call to 'vscanf'}}
-                        // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const wchar_t *' to 'const char *' for 1st argument}}
-                        // C-CHECK: fix-it:"{{.*}}":{[[@LINE-13]]:6-[[@LINE-13]]:6}:"__attribute__((format(scanf, 1, 2)))"
-}
-
-void f11(const wchar_t *out, ... /* args */) // #f11
-{
-    va_list args;
-    vscanf((const char *) out, args); // expected-warning@#f11 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f11'}}
-                                      // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
-}
-
-void f12(const wchar_t *out, ... /* args */) // #f12
-{
-    va_list args;
-    vscanf((char *) out, args); // expected-warning@#f12 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f12'}}
-                                // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
-}
-
-void f13(const wchar_t *out, ... /* args */) // #f13
-{
-    va_list args;
-    vscanf(out, args);
-#if __SIZEOF_WCHAR_T__ == 4
-                        // c_diagnostics-warning at -2 {{incompatible pointer types passing 'const wchar_t *' (aka 'const int *') to parameter of type 'const char *'}}
-#else
-                        // c_diagnostics-warning at -4 {{incompatible pointer types passing 'const wchar_t *' (aka 'const unsigned short *') to parameter of type 'const char *'}}
-#endif
-                        // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                        // cpp_diagnostics-error at -7 {{no matching function for call to 'vscanf'}}
-                        // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const wchar_t *' to 'const char *' for 1st argument}}
-                        // expected-warning@#f13 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f13'}}
-                        // CHECK: fix-it:"{{.*}}":{[[@LINE-13]]:6-[[@LINE-13]]:6}:"__attribute__((format(scanf, 1, 2)))"
-    vscanf((const char *) out, args);
-    vscanf((char *) out, args);
-}
-
-void f14(const char *out) // #f14
-{
-    va_list args;
-    vscanf(out, args); // expected-warning@#f14 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f14'}}
-                       // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 0)))"
-}
-
-void f15(const char16_t *out, ... /* args */) // #f15
-{
-    va_list args;
-    vscanf(out, args); // c_diagnostics-warning {{incompatible pointer types passing 'const char16_t *' (aka 'const unsigned short *') to parameter of type 'const char *'}}
-                       // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                       // c_diagnostics-warning@#f15 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f15'}}
-                       // C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
-                       // cpp_diagnostics-error at -4 {{no matching function for call to 'vscanf'}}
-                       // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const char16_t *' to 'const char *' for 1st argument}}
-}
-
-void f16(const char32_t *out, ... /* args */) // #f16
-{
-    va_list args;
-    vscanf(out, args); // c_diagnostics-warning {{incompatible pointer types passing 'const char32_t *' (aka 'const unsigned int *') to parameter of type 'const char *'}}
-                       // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                       // c_diagnostics-warning@#f16 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f16'}}
-                       // C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
-                       // cpp_diagnostics-error at -4 {{no matching function for call to 'vscanf'}}
-                       // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const char32_t *' to 'const char *' for 1st argument}}
-}
-
-void f17(const unsigned char *out, ... /* args */) // #f17
-{
-    va_list args;
-    vscanf(out, args); // c_diagnostics-warning {{passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
-                       // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                       // c_diagnostics-warning@#f17 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f17'}}
-                       // C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
-                       // cpp_diagnostics-error at -4 {{no matching function for call to 'vscanf'}}
-                       // cpp_diagnostics-note@#vprintf {{candidate function not viable: no known conversion from 'const unsigned char *' to 'const char *' for 1st argument}}
-}
-
-void f18(const unsigned char *out, ... /* args */) // #f18
-{
-    va_list args;
-    vscanf((const char *) out, args); // expected-warning@#f18 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f18'}}
-                                      // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
-}
-
-void f19(const unsigned char *out, ... /* args */) // #f19
-{
-    va_list args;
-    vscanf((char *) out, args); // expected-warning@#f19 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f19'}}
-                                // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
-}
-
-__attribute__((format(printf, 1, 2)))
-void f20(const unsigned char *out, ... /* args */) // #f20
-{
-    va_list args;
-    vprintf(out, args); // c_diagnostics-warning {{passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
-                        // c_diagnostics-note@#vprintf {{passing argument to parameter here}}
-                        // cpp_diagnostics-error at -2 {{no matching function for call to 'vprintf'}}
-                        // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const unsigned char *' to 'const char *' for 1st argument}}
-    vscanf((const char *) out, args); // expected-no-warning
-    vprintf((const char *) out, args); // expected-no-warning
-    vscanf((char *) out, args); // expected-no-warning
-    vprintf((char *) out, args); // expected-no-warning
-}
-
-void f21(signed char *out, ... /* args */) // #f21
-{
-    va_list args;
-    vscanf(out, args); // c_diagnostics-warning {{passing 'signed char *' to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}} \
-                       // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                       // c_diagnostics-warning@#f21 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f21'}}
-                       // C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
-                       // cpp_diagnostics-error at -4 {{no matching function for call to 'vscanf'}}
-                       // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'signed char *' to 'const char *' for 1st argument}}
-}
-
-void f22(signed char *out, ... /* args */) // #f22
-{
-    va_list args;
-    vscanf((const char *) out, args); // expected-warning@#f22 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f22'}}
-                                      // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
-}
-
-void f23(signed char *out, ... /* args */) // #f23
-{
-    va_list args;
-    vprintf((char *) out, args); // expected-warning@#f23 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f23'}}
-                                 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 2)))"
-}
-
-__attribute__((format(scanf, 1, 2)))
-void f24(signed char *out, ... /* args */) // #f24
-{
-    va_list args;
-    vprintf((const char *) out, args); // expected-no-warning@#f24
-    vprintf((char *) out, args); // expected-no-warning@#f24
-}
-
-__attribute__((format(printf, 1, 2)))
-void f25(unsigned char out[], ... /* args */) // #f25
-{
-    va_list args;
-    vscanf((const char *) out, args); // expected-no-warning@#f25
-    vscanf((char *) out, args); // expected-no-warning@#f25
-}
-
-void f26(char* out) // #f26
-{
-    va_list args;
-    const char* ch;
-    vsprintf(out, ch, args); // expected-no-warning@#f26
-    vprintf(out, args); // expected-warning@#f26 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f26'}}
-                        // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(printf, 1, 0)))"
-}
-
-void f27(const char *out, ... /* args */) // #f27
-{
-    int a;
-    printf(out, a); // expected-warning@#f27 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f27'}}
-                    // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 0)))"
-}
-
-void f28(const char *out, ... /* args */) // #f28
-{
-    printf(out, 1); // expected-warning@#f28 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f28'}}
-                    // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:6-[[@LINE-3]]:6}:"__attribute__((format(printf, 1, 0)))"
-}
-
-__attribute__((format(printf, 1, 2)))
-void f29(const char *out, ... /* args */) // #f29
-{
-    int a;
-    printf(out, a); // expected-no-warning@#f29
-}
-
-__attribute__((format(printf, 1, 2)))
-void f30(const char *out, ... /* args */) // #f30
-{
-    printf(out, 1); // expected-no-warning@#f30
-}
-
-__attribute__((format(printf, 1, 2)))
-void f31(const char *out, ... /* args */) // #f31
-{
-    int a;
-    printf(out, a); // expected-no-warning@#f31
-    printf(out, 1); // expected-no-warning@#f31
-}
-
-void f32(char *out, ... /* args */) // #f32
-{
-    va_list args;
-    scanf(out, args); // expected-no-warning@#f32
-    {
-        printf(out, args); // expected-no-warning@#f32
-    }
-}
-
-void f33(char *out, va_list args) // #f33
-{
-    {
-        scanf(out, args); // expected-no-warning@#f33
-        printf(out, args); // expected-no-warning@#f33
-    }
-}
-
-// expected-warning@#f34 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f34'}}
-// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:6-[[@LINE+1]]:6}:"__attribute__((format(scanf, 1, 2)))"
-void f34(char *out, ... /* args */) // #f34
-{
-    va_list args;
-    scanf(out, args); // expected-no-warning@#f34
-    {
-        scanf(out, args); // expected-no-warning@#f34
-    }
-}
-
-void f35(char* ch, const char *out, ... /* args */) // #f35
-{
-    va_list args;
-    printf(ch, args); // expected-warning@#f35 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f35}}
-                      // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 3)))"
-    int a;
-    printf(out, a); // expected-warning@#f35 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f35'}}
-                    // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:6-[[@LINE-7]]:6}:"__attribute__((format(printf, 2, 0)))"
-    printf(out, 1); // no warning because first command above emitted same warning with same fix-it text
-    printf(out, args); // expected-warning@#f35 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f35'}}
-                       // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:6-[[@LINE-10]]:6}:"__attribute__((format(printf, 2, 3)))"
-}
-
-typedef va_list tdVaList;
-typedef int tdInt;
-
-void f36(const char *out, ... /* args */) // #f36
-{
-    tdVaList args;
-    printf(out, args); // expected-warning@#f36 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f36'}}
-                       // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 2)))"
-}
-
-void f37(const char *out, ... /* args */) // #f37
-{
-    tdInt a;
-    scanf(out, a); // expected-warning@#f37 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f37'}}
-                   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 0)))"
-}
-
-void f38(const char *out, tdVaList args) // #f38
-{
-    scanf(out, args); // expected-warning@#f38 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f38'}}
-                      // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:6-[[@LINE-3]]:6}:"__attribute__((format(scanf, 1, 0)))"
-}
-
-void f39(const char *out, tdVaList args) // #f39
-{
-    tdInt a;
-    printf(out, a); // expected-warning@#f39 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f39'}}
-                    // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 0)))"
-}
-
-void f40(char *out, ... /* args */) // #f40
-{
-    va_list args;
-    char *ch;
-    vscanf(ch, args); // expected-no-warning@#f40
-    vprintf(out, args); // expected-no-warning@#f40
-}
-
-void f41(char *out, ... /* args */) // #f41
-{
-    va_list args;
-    char *ch;
-    vscanf("%s", ch);
-#if defined(__x86_64__) && defined(__linux__)
-                        // c_diagnostics-warning at -2 {{incompatible pointer types passing 'char *' to parameter of type 'struct __va_list_tag *'}}
-                        // c_diagnostics-note@#vscanf {{passing argument to parameter here}}
-                        // cpp_diagnostics-error at -4 {{no matching function for call to 'vscanf'}}
-                        // cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'char *' to '__va_list_tag *' for 2nd argument}}
-#endif
-    vprintf(out, args);
-#if defined(__x86_64__) && defined(__linux__)
-                        // cpp_diagnostics-warning@#f41 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f41'}}
-                        // CHECK-LIN64: fix-it:"{{.*}}":{[[@LINE-14]]:6-[[@LINE-14]]:6}:"__attribute__((format(printf, 1, 2)))"
-#endif
-}

diff  --git a/clang/test/Sema/attr-format-missing.cpp b/clang/test/Sema/attr-format-missing.cpp
deleted file mode 100644
index 4c5758d6c9d84..0000000000000
--- a/clang/test/Sema/attr-format-missing.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,beforeCxx2b -Wmissing-format-attribute %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2b -Wmissing-format-attribute %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wmissing-format-attribute %s
-// RUN: not %clang_cc1 -fsyntax-only -Wmissing-format-attribute -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
-
-typedef __SIZE_TYPE__ size_t;
-typedef __builtin_va_list va_list;
-
-namespace std
-{
-    template<class Elem> struct basic_string_view {};
-    template<class Elem> struct basic_string {
-        const Elem *c_str() const noexcept;
-        basic_string(const basic_string_view<Elem> SW);
-    };
-
-    using string = basic_string<char>;
-    using wstring = basic_string<wchar_t>;
-    using string_view = basic_string_view<char>;
-    using wstring_view = basic_string_view<wchar_t>;
-}
-
-__attribute__((__format__(__printf__, 1, 2)))
-int printf(const char *, ...); // #printf
-
-__attribute__((__format__(__scanf__, 1, 2)))
-int scanf(const char *, ...); // #scanf
-
-__attribute__((__format__(__printf__, 1, 0)))
-int vprintf(const char *, va_list); // #vprintf
-
-__attribute__((__format__(__scanf__, 1, 0)))
-int vscanf(const char *, va_list); // #vscanf
-
-__attribute__((__format__(__printf__, 2, 0)))
-int vsprintf(char *, const char *, va_list); // #vsprintf
-
-__attribute__((__format__(__printf__, 3, 0)))
-int vsnprintf(char *ch, size_t, const char *, va_list); // #vsnprintf
-
-void f1(const std::string &str, ... /* args */) // #f1
-{
-    va_list args;
-    vscanf(str.c_str(), args); // expected-no-warning@#f1
-}
-
-__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
-void f2(const std::string &str, ... /* args */); // #f2
-
-void f3(std::string_view str, ... /* args */) // #f3
-{
-    va_list args;
-    vscanf(std::string(str).c_str(), args); // expected-no-warning@#f3
-}
-
-__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
-void f4(std::string_view str, ... /* args */); // #f4
-
-void f5(const std::wstring &str, ... /* args */) // #f5
-{
-    va_list args;
-    vprintf((const char *)str.c_str(), args); // expected-no-warning@#f5
-}
-
-__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
-void f6(const std::wstring &str, ... /* args */); // #f6
-
-void f7(std::wstring_view str, ... /* args */) // #f7
-{
-    va_list args;
-    vprintf((const char *) std::wstring(str).c_str(), args); // expected-no-warning@#f7
-}
-
-__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
-void f8(std::wstring_view str, ... /* args */); // #f8
-
-struct S1
-{
-    void fn1(const char *out, ... /* args */) // #S1_fn1
-    {
-        va_list args;
-        vscanf(out, args); // expected-warning@#S1_fn1 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'fn1'}}
-                           // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:10-[[@LINE-4]]:10}:"__attribute__((format(scanf, 2, 3)))"
-    }
-
-    __attribute__((format(scanf, 2, 0)))
-    void fn2(const char *out, va_list args); // #S1_fn2
-
-    void fn3(const char *out, ... /* args */);
-
-    void fn4(this S1& expliciteThis, const char *out, va_list args) // #S1_fn4
-    {
-        expliciteThis.fn2(out, args); // beforeCxx2b-error@#S1_fn4 {{explicit object parameters are incompatible with C++ standards before C++2b}}
-                                      // expected-warning@#S1_fn4 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'fn4'}}
-                                      // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:10-[[@LINE-4]]:10}:"__attribute__((format(scanf, 2, 0)))"
-    }
-};
-
-void S1::fn3(const char *out, ... /* args */) // #S1_fn3
-{
-    va_list args;
-    fn2(out, args); // expected-warning@#S1_fn3 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'fn3'}}
-                    // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:10-[[@LINE-4]]:10}:"__attribute__((format(scanf, 2, 3)))"
-}
-
-union U1
-{
-    __attribute__((format(printf, 2, 0)))
-    void fn1(const char *out, va_list args); // #U1_fn1
-
-    void fn2(const char *out, ... /* args */) // #U1_fn2
-    {
-        va_list args;
-        fn1(out, args); // expected-warning@#U1_fn2 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'fn2'}}
-                        // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:10-[[@LINE-4]]:10}:"__attribute__((format(printf, 2, 3)))"
-    }
-
-    void fn3(this U1&, const char *out) // #U1_fn3
-    {
-        va_list args;
-        printf(out, args); // beforeCxx2b-error@#U1_fn3 {{explicit object parameters are incompatible with C++ standards before C++2b}}
-                           // expected-warning@#U1_fn3 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'fn3'}}
-                           // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:10-[[@LINE-5]]:10}:"__attribute__((format(printf, 2, 0)))"
-    }
-};
-
-class C1
-{
-    __attribute__((format(printf, 3, 0)))
-    void fn1(const int n, const char *out, va_list args); // #C1_fn1
-
-    void fn2(const char *out, const int n, ... /* args */) // #C1_fn2
-    {
-        va_list args;
-        fn1(n, out, args); // expected-warning@#C1_fn2 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'fn2'}}
-                           // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:10-[[@LINE-4]]:10}:"__attribute__((format(printf, 2, 4)))"
-    }
-
-    void fn3(this const C1&, const char *out, va_list args) // #C1_fn3
-    {
-        scanf(out, args); // beforeCxx2b-error@#C1_fn3 {{explicit object parameters are incompatible with C++ standards before C++2b}}
-                          // expected-warning@#C1_fn3 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'fn3'}}
-                          // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:10-[[@LINE-4]]:10}:"__attribute__((format(scanf, 2, 0)))"
-    }
-
-    C1(const int n, const char *out) //#C1_C1a
-    {
-        va_list args;
-        fn1(n, out, args); // expected-warning@#C1_C1a {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'C1'}}
-                           // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:5-[[@LINE-4]]:5}:"__attribute__((format(printf, 3, 0)))"
-    }
-
-    C1(const char *out, ... /* args */) // #C1_C1b
-    {
-        va_list args;
-        printf(out, args); // expected-warning@#C1_C1b {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'C1'}}
-                           // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:5-[[@LINE-4]]:5}:"__attribute__((format(printf, 2, 3)))"
-    }
-
-    ~C1() // #d_C1
-    {
-        const char *out;
-        va_list args;
-        vprintf(out, args); // expected-no-warning@#d_C1
-    }
-};
-
-// TODO: implement for templates
-template <int N>
-void func(char (&str)[N], ... /* args */) // #func
-{
-    va_list args;
-    vprintf(str, args); // expected-no-warning@#func
-}


        


More information about the llvm-branch-commits mailing list