https://github.com/mysterymath updated 
https://github.com/llvm/llvm-project/pull/147431

>From 3ac748150a5c7caf8fed4d7c488770722d505068 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 10 Jun 2025 14:06:53 -0700
Subject: [PATCH 01/12] [clang] "modular_format" attribute for functions using
 format strings

This provides a C language version of the new IR modular-format
attribute. This, in concert with the format attribute, allows a library
function to declare that a modular version of its implementation is
available.

See issue #146159 for context.
---
 clang/include/clang/Basic/Attr.td     | 11 +++++++++++
 clang/include/clang/Basic/AttrDocs.td | 25 +++++++++++++++++++++++++
 clang/lib/CodeGen/CGCall.cpp          | 12 ++++++++++++
 clang/lib/Sema/SemaDeclAttr.cpp       | 27 +++++++++++++++++++++++++++
 4 files changed, 75 insertions(+)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 749f531ec9ab1..8605032df2eee 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -5309,3 +5309,14 @@ def NonString : InheritableAttr {
   let Subjects = SubjectList<[Var, Field]>;
   let Documentation = [NonStringDocs];
 }
+
+def ModularFormat : InheritableAttr {
+  let Spellings = [Clang<"modular_format">];
+  let Args = [
+    IdentifierArgument<"ModularImplFn">,
+    StringArgument<"ImplName">,
+    VariadicStringArgument<"Aspects">
+  ];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [ModularFormatDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 2fdd041c1b46e..7baee073b5cfd 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9674,3 +9674,28 @@ silence diagnostics with code like:
   __attribute__((nonstring)) char NotAStr[3] = "foo"; // Not diagnosed
   }];
 }
+
+def ModularFormatDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``modular_format`` attribute can be applied to a function that bears the
+``format`` attribute to indicate that the implementation is modular on the
+format string argument. When the format argument for a given call is constant,
+the compiler may redirect the call to the symbol given as the first argument to
+the attribute (the modular implementation function).
+
+The second argument is a implementation name, and the remaining arguments are
+aspects of the format string for the compiler to report. If the compiler does
+not understand a aspect, it must summarily report that the format string has
+that aspect.
+
+The compiler reports an aspect by issing a relocation for the symbol
+`<impl_name>_<aspect>``. This arranges for code and data needed to support the
+aspect of the implementation to be brought into the link to satisfy weak
+references in the modular implemenation function.
+
+The following aspects are currently supported:
+
+- ``float``: The call has a floating point argument
+  }];
+}
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 465f3f4e670c2..cfff662757c78 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2557,6 +2557,18 @@ void CodeGenModule::ConstructAttributeList(StringRef 
Name,
 
     if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
       FuncAttrs.addAttribute("aarch64_pstate_sm_body");
+
+    if (auto *ModularFormat = TargetDecl->getAttr<ModularFormatAttr>()) {
+      // TODO: Error checking
+      FormatAttr *Format = TargetDecl->getAttr<FormatAttr>();
+      std::string FormatIdx = std::to_string(Format->getFormatIdx());
+      std::string FirstArg = std::to_string(Format->getFirstArg());
+      SmallVector<StringRef> Args = {
+          FormatIdx, FirstArg, ModularFormat->getModularImplFn()->getName(),
+          ModularFormat->getImplName()};
+      llvm::append_range(Args, ModularFormat->aspects());
+      FuncAttrs.addAttribute("modular-format", llvm::join(Args, ","));
+    }
   }
 
   // Attach "no-builtins" attributes to:
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index a9e7b44ac9d73..484e4ad921835 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6911,6 +6911,29 @@ static void handleVTablePointerAuthentication(Sema &S, 
Decl *D,
       CustomDiscriminationValue));
 }
 
+static void handleModularFormat(Sema &S, Decl *D, const ParsedAttr &AL) {
+  StringRef ImplName;
+  if (!S.checkStringLiteralArgumentAttr(AL, 1, ImplName))
+    return;
+  SmallVector<StringRef> Aspects;
+  for (unsigned I = 2, E = AL.getNumArgs(); I != E; ++I) {
+    StringRef Aspect;
+    if (!S.checkStringLiteralArgumentAttr(AL, I, Aspect))
+      return;
+    Aspects.push_back(Aspect);
+  }
+
+  // Store aspects sorted and without duplicates.
+  llvm::sort(Aspects);
+  Aspects.erase(llvm::unique(Aspects), Aspects.end());
+
+  // TODO: Type checking on identifier
+  // TODO: Merge attributes
+  D->addAttr(::new (S.Context) ModularFormatAttr(
+      S.Context, AL, AL.getArgAsIdent(0)->getIdentifierInfo(), ImplName,
+      Aspects.data(), Aspects.size()));
+}
+
 
//===----------------------------------------------------------------------===//
 // Top Level Sema Entry Points
 
//===----------------------------------------------------------------------===//
@@ -7845,6 +7868,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 
const ParsedAttr &AL,
   case ParsedAttr::AT_VTablePointerAuthentication:
     handleVTablePointerAuthentication(S, D, AL);
     break;
+
+  case ParsedAttr::AT_ModularFormat:
+    handleModularFormat(S, D, AL);
+    break;
   }
 }
 

>From 009666f0d4a055f41c0923b86c24efc69d3ab201 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 15 Jul 2025 11:28:20 -0700
Subject: [PATCH 02/12] Update docs to account for clang inferring format
 attribute

---
 clang/include/clang/Basic/AttrDocs.td | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 7baee073b5cfd..9c182c37eedee 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9679,10 +9679,11 @@ def ModularFormatDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
 The ``modular_format`` attribute can be applied to a function that bears the
-``format`` attribute to indicate that the implementation is modular on the
-format string argument. When the format argument for a given call is constant,
-the compiler may redirect the call to the symbol given as the first argument to
-the attribute (the modular implementation function).
+``format`` attribute (or standard library functions) to indicate that the
+implementation is modular on the format string argument. When the format string
+for a given call is constant, the compiler may redirect the call to the symbol
+given as the first argument to the attribute (the modular implementation
+function).
 
 The second argument is a implementation name, and the remaining arguments are
 aspects of the format string for the compiler to report. If the compiler does

>From 15c4fc0ff495a07bf79457096edd606826868cc0 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Wed, 16 Jul 2025 15:19:37 -0700
Subject: [PATCH 03/12] Add an example to clang attr doc

---
 clang/include/clang/Basic/AttrDocs.td | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 9c182c37eedee..219e21d37351c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9691,10 +9691,18 @@ not understand a aspect, it must summarily report that 
the format string has
 that aspect.
 
 The compiler reports an aspect by issing a relocation for the symbol
-`<impl_name>_<aspect>``. This arranges for code and data needed to support the
+``<impl_name>_<aspect>``. This arranges for code and data needed to support the
 aspect of the implementation to be brought into the link to satisfy weak
 references in the modular implemenation function.
 
+For example, say ``printf`` is annotated with
+``modular_format(__modular_printf, __printf, float)``. Then, a call to
+``printf(var, 42)`` would be untouched. A call to ``printf("%d", 42)`` would
+become a call to ``__modular_printf`` with the same arguments, as would
+``printf("%f", 42.0)``. The latter would be accompanied with a strong
+relocation against the symbol ``__printf_float``, which would bring floating
+point support for ``printf`` into the link.
+
 The following aspects are currently supported:
 
 - ``float``: The call has a floating point argument

>From e2af60f352e0469c4f7ffd00d047032b92a837d7 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 22 Jul 2025 13:35:46 -0700
Subject: [PATCH 04/12] Emit the new type arg from format attr

---
 clang/lib/CodeGen/CGCall.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index cfff662757c78..f922f45e2dd0a 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2561,10 +2561,12 @@ void CodeGenModule::ConstructAttributeList(StringRef 
Name,
     if (auto *ModularFormat = TargetDecl->getAttr<ModularFormatAttr>()) {
       // TODO: Error checking
       FormatAttr *Format = TargetDecl->getAttr<FormatAttr>();
+      StringRef Type = Format->getType()->getName();
       std::string FormatIdx = std::to_string(Format->getFormatIdx());
       std::string FirstArg = std::to_string(Format->getFirstArg());
       SmallVector<StringRef> Args = {
-          FormatIdx, FirstArg, ModularFormat->getModularImplFn()->getName(),
+          Type, FormatIdx, FirstArg,
+          ModularFormat->getModularImplFn()->getName(),
           ModularFormat->getImplName()};
       llvm::append_range(Args, ModularFormat->aspects());
       FuncAttrs.addAttribute("modular-format", llvm::join(Args, ","));

>From 4083c9868511e135af3a31eaa21999771368641e Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 22 Jul 2025 15:01:56 -0700
Subject: [PATCH 05/12] Correct typos

---
 clang/include/clang/Basic/AttrDocs.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 219e21d37351c..0e4899e1d8cb0 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9687,10 +9687,10 @@ function).
 
 The second argument is a implementation name, and the remaining arguments are
 aspects of the format string for the compiler to report. If the compiler does
-not understand a aspect, it must summarily report that the format string has
+not understand an aspect, it must summarily report that the format string has
 that aspect.
 
-The compiler reports an aspect by issing a relocation for the symbol
+The compiler reports an aspect by issuing a relocation for the symbol
 ``<impl_name>_<aspect>``. This arranges for code and data needed to support the
 aspect of the implementation to be brought into the link to satisfy weak
 references in the modular implemenation function.

>From a0bf190989fd926c1175fba38f660747d9f208b1 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Thu, 17 Jul 2025 15:56:10 -0700
Subject: [PATCH 06/12] Tests for successful format string passthrough

---
 clang/test/CodeGen/attr-modular-format.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 clang/test/CodeGen/attr-modular-format.c

diff --git a/clang/test/CodeGen/attr-modular-format.c 
b/clang/test/CodeGen/attr-modular-format.c
new file mode 100644
index 0000000000000..7d0580def41e9
--- /dev/null
+++ b/clang/test/CodeGen/attr-modular-format.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | 
FileCheck %s
+
+int printf(const char *fmt, ...)  
__attribute__((modular_format(__modular_printf, "__printf", "float")));
+int myprintf(const char *fmt, ...)  
__attribute__((modular_format(__modular_printf, "__printf", "float"), 
format(printf, 1, 2)));
+
+// CHECK-LABEL: define dso_local void @test_inferred_format(
+// CHECK:    {{.*}} = call i32 (ptr, ...) @printf(ptr noundef @.str) 
#[[ATTR:[0-9]+]]
+void test_inferred_format(void) {
+  printf("hello");
+}
+
+// CHECK-LABEL: define dso_local void @test_explicit_format(
+// CHECK:    {{.*}} = call i32 (ptr, ...) @myprintf(ptr noundef @.str) 
#[[ATTR:[0-9]+]]
+void test_explicit_format(void) {
+  myprintf("hello");
+}
+
+// CHECK: attributes #[[ATTR]] = { 
"modular-format"="printf,1,2,__modular_printf,__printf,float" }

>From 51b2ad3f9415cd3dae825c97dfe6043878db00a5 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Fri, 5 Sep 2025 17:10:37 -0700
Subject: [PATCH 07/12] Add redeclaration test

---
 clang/lib/Sema/SemaDeclAttr.cpp          |  1 -
 clang/test/CodeGen/attr-modular-format.c | 10 ++++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 484e4ad921835..2d33c4308a600 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6928,7 +6928,6 @@ static void handleModularFormat(Sema &S, Decl *D, const 
ParsedAttr &AL) {
   Aspects.erase(llvm::unique(Aspects), Aspects.end());
 
   // TODO: Type checking on identifier
-  // TODO: Merge attributes
   D->addAttr(::new (S.Context) ModularFormatAttr(
       S.Context, AL, AL.getArgAsIdent(0)->getIdentifierInfo(), ImplName,
       Aspects.data(), Aspects.size()));
diff --git a/clang/test/CodeGen/attr-modular-format.c 
b/clang/test/CodeGen/attr-modular-format.c
index 7d0580def41e9..2c647214b3bca 100644
--- a/clang/test/CodeGen/attr-modular-format.c
+++ b/clang/test/CodeGen/attr-modular-format.c
@@ -15,4 +15,14 @@ void test_explicit_format(void) {
   myprintf("hello");
 }
 
+int redecl(const char *fmt, ...) __attribute__((modular_format(__first_impl, 
"__first", "one"), format(printf, 1, 2)));
+int redecl(const char *fmt, ...) __attribute__((modular_format(__second_impl, 
"__second", "two", "three")));
+
+// CHECK-LABEL: define dso_local void @test_redecl(
+// CHECK:    {{.*}} = call i32 (ptr, ...) @redecl(ptr noundef @.str) 
#[[ATTR_REDECL:[0-9]+]]
+void test_redecl(void) {
+  redecl("hello");
+}
+
 // CHECK: attributes #[[ATTR]] = { 
"modular-format"="printf,1,2,__modular_printf,__printf,float" }
+// CHECK: attributes #[[ATTR_REDECL]] = { 
"modular-format"="printf,1,2,__second_impl,__second,three,two" }

>From 1b9cdfdf0fd122b2f838c7f929c0a5dec1deadcb Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Mon, 3 Nov 2025 16:48:55 -0800
Subject: [PATCH 08/12] Clarify and correct docs

---
 clang/include/clang/Basic/AttrDocs.td | 23 ++++++++++++-----------
 clang/lib/Sema/SemaDeclAttr.cpp       |  1 -
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0e4899e1d8cb0..f22c45cbf012c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9680,23 +9680,24 @@ def ModularFormatDocs : Documentation {
   let Content = [{
 The ``modular_format`` attribute can be applied to a function that bears the
 ``format`` attribute (or standard library functions) to indicate that the
-implementation is modular on the format string argument. When the format string
-for a given call is constant, the compiler may redirect the call to the symbol
-given as the first argument to the attribute (the modular implementation
-function).
+implementation is "modular", that is, that the implemenation is logically
+divided into a number of named aspects. When the compiler can determine that
+not all aspects of the implementation are needed for a given call, the compiler
+may redirect the call to the identifier given as the first argument to the
+attribute (the modular implementation function).
 
 The second argument is a implementation name, and the remaining arguments are
 aspects of the format string for the compiler to report. If the compiler does
-not understand an aspect, it must summarily report that the format string has
-that aspect.
+not understand an aspect, it must summarily consider any call to require that
+aspect. 
 
-The compiler reports an aspect by issuing a relocation for the symbol
-``<impl_name>_<aspect>``. This arranges for code and data needed to support the
-aspect of the implementation to be brought into the link to satisfy weak
-references in the modular implemenation function.
+The compiler reports that a call requires an aspect by issuing a relocation for
+the symbol ``<impl_name>_<aspect>`` at the point of the call. This arranges for
+code and data needed to support the aspect of the implementation to be brought
+into the link to satisfy weak references in the modular implemenation function.
 
 For example, say ``printf`` is annotated with
-``modular_format(__modular_printf, __printf, float)``. Then, a call to
+``modular_format(__modular_printf, "__printf", "float")``. Then, a call to
 ``printf(var, 42)`` would be untouched. A call to ``printf("%d", 42)`` would
 become a call to ``__modular_printf`` with the same arguments, as would
 ``printf("%f", 42.0)``. The latter would be accompanied with a strong
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 2d33c4308a600..aece42d38d9fb 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6927,7 +6927,6 @@ static void handleModularFormat(Sema &S, Decl *D, const 
ParsedAttr &AL) {
   llvm::sort(Aspects);
   Aspects.erase(llvm::unique(Aspects), Aspects.end());
 
-  // TODO: Type checking on identifier
   D->addAttr(::new (S.Context) ModularFormatAttr(
       S.Context, AL, AL.getArgAsIdent(0)->getIdentifierInfo(), ImplName,
       Aspects.data(), Aspects.size()));

>From cfe70653e1c84b31c335b01f59551892f0b9d2a7 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 4 Nov 2025 13:17:47 -0800
Subject: [PATCH 09/12] Emit error for missing format attribute

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +++
 clang/lib/Sema/SemaDecl.cpp                      | 6 ++++++
 clang/test/Sema/attr-modular-format.c            | 7 +++++++
 3 files changed, 16 insertions(+)
 create mode 100644 clang/test/Sema/attr-modular-format.c

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fa509536bf021..07ae0540d324b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13017,6 +13017,9 @@ def err_get_vtable_pointer_requires_complete_type
     : Error<"__builtin_get_vtable_pointer requires an argument with a complete 
"
             "type, but %0 is incomplete">;
 
+def err_modular_format_attribute_no_format : Error<
+    "'modular_format' attribute requires 'format' attribute">;
+
 // SYCL-specific diagnostics
 def warn_sycl_kernel_num_of_template_params : Warning<
   "'sycl_kernel' attribute only applies to a function template with at least"
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fc3aabf5741ca..83bae024417f8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7210,6 +7210,11 @@ static void checkLifetimeBoundAttr(Sema &S, NamedDecl 
&ND) {
   }
 }
 
+static void checkModularFormatAttr(Sema &S, NamedDecl &ND) {
+  if (ND.hasAttr<ModularFormatAttr>() && !ND.hasAttr<FormatAttr>())
+    S.Diag(ND.getLocation(), diag::err_modular_format_attribute_no_format);
+}
+
 static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
   // Ensure that an auto decl is deduced otherwise the checks below might cache
   // the wrong linkage.
@@ -7222,6 +7227,7 @@ static void checkAttributesAfterMerging(Sema &S, 
NamedDecl &ND) {
   checkHybridPatchableAttr(S, ND);
   checkInheritableAttr(S, ND);
   checkLifetimeBoundAttr(S, ND);
+  checkModularFormatAttr(S, ND);
 }
 
 static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
diff --git a/clang/test/Sema/attr-modular-format.c 
b/clang/test/Sema/attr-modular-format.c
new file mode 100644
index 0000000000000..46811b980f854
--- /dev/null
+++ b/clang/test/Sema/attr-modular-format.c
@@ -0,0 +1,7 @@
+//RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include <stdarg.h>
+
+int printf(const char *fmt, ...)  
__attribute__((modular_format(__modular_printf, "__printf", "float")));  // 
no-error
+int myprintf(const char *fmt, ...)  
__attribute__((modular_format(__modular_printf, "__printf", "float")));  // 
expected-error {{'modular_format' attribute requires 'format' attribute}}
+

>From cfa9c2b2dda18a0c2b5740cfd43a67f7410f150b Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 4 Nov 2025 16:38:55 -0800
Subject: [PATCH 10/12] Clarify semantics

---
 clang/include/clang/Basic/AttrDocs.td | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index f22c45cbf012c..a38aedbcbbbcf 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -9687,14 +9687,15 @@ may redirect the call to the identifier given as the 
first argument to the
 attribute (the modular implementation function).
 
 The second argument is a implementation name, and the remaining arguments are
-aspects of the format string for the compiler to report. If the compiler does
-not understand an aspect, it must summarily consider any call to require that
-aspect. 
+aspects of the format string for the compiler to report. The implementation
+name is an unevaluted identifier be in the C namespace.
 
 The compiler reports that a call requires an aspect by issuing a relocation for
 the symbol ``<impl_name>_<aspect>`` at the point of the call. This arranges for
 code and data needed to support the aspect of the implementation to be brought
 into the link to satisfy weak references in the modular implemenation function.
+If the compiler does not understand an aspect, it must summarily consider any
+call to require that aspect. 
 
 For example, say ``printf`` is annotated with
 ``modular_format(__modular_printf, "__printf", "float")``. Then, a call to

>From b148035c29f844ea2ff3950dfef35a57c67c99f1 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 4 Nov 2025 16:40:11 -0800
Subject: [PATCH 11/12] clang-format

---
 clang/include/clang/Basic/Attr.td                | 7 ++-----
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++--
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 8605032df2eee..053be3453eaea 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -5312,11 +5312,8 @@ def NonString : InheritableAttr {
 
 def ModularFormat : InheritableAttr {
   let Spellings = [Clang<"modular_format">];
-  let Args = [
-    IdentifierArgument<"ModularImplFn">,
-    StringArgument<"ImplName">,
-    VariadicStringArgument<"Aspects">
-  ];
+  let Args = [IdentifierArgument<"ModularImplFn">, StringArgument<"ImplName">,
+              VariadicStringArgument<"Aspects">];
   let Subjects = SubjectList<[Function]>;
   let Documentation = [ModularFormatDocs];
 }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 07ae0540d324b..a0c44e83e7e42 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13017,8 +13017,8 @@ def err_get_vtable_pointer_requires_complete_type
     : Error<"__builtin_get_vtable_pointer requires an argument with a complete 
"
             "type, but %0 is incomplete">;
 
-def err_modular_format_attribute_no_format : Error<
-    "'modular_format' attribute requires 'format' attribute">;
+def err_modular_format_attribute_no_format
+    : Error<"'modular_format' attribute requires 'format' attribute">;
 
 // SYCL-specific diagnostics
 def warn_sycl_kernel_num_of_template_params : Warning<

>From ef6282937037a69cfcd6f95716e9bbbc9acfd3cc Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <[email protected]>
Date: Tue, 4 Nov 2025 16:44:44 -0800
Subject: [PATCH 12/12] Add a blurb to the release notes

---
 clang/docs/ReleaseNotes.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3f57ddc92d5e8..507be73a7fc4b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -325,6 +325,11 @@ Attribute Changes in Clang
 - New format attributes ``gnu_printf``, ``gnu_scanf``, ``gnu_strftime`` and 
``gnu_strfmon`` are added
   as aliases for ``printf``, ``scanf``, ``strftime`` and ``strfmon``. 
(#GH16219)
 
+- New attribute ``modular_format`` to allow dynamically selecting at link time
+  which aspects of a statically linked libc's printf (et al) implementation are
+  required. This can reduce code size without requiring e.g. multilibs for
+  printf features. Requires cooperation with the libc implementation.
+
 Improvements to Clang's diagnostics
 -----------------------------------
 - Diagnostics messages now refer to ``structured binding`` instead of 
``decomposition``,

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to