[libc-commits] [libc] [libc] Add explicit format attributes for modular printf (PR #201212)

Daniel Thornburgh via libc-commits libc-commits at lists.llvm.org
Tue Jun 2 14:52:15 PDT 2026


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

>From d47c675f0b8850f57ccc9c7c7631143f393fe8aa Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 2 Jun 2026 14:35:13 -0700
Subject: [PATCH] [libc] Add explicit format attributes for modular printf

We had been relying on compiler-generated format attributes when using
the modular_format attribute for printf-family functions, but this is
not applied in -ffreestanding mode. When modular format is enabled, libc
is explicitly asserting the semantics of these functions, so it should
be explicit about the format attributes as well to keep them from
breaking in -ffreestanding.

Generated by Gemini, reviewed and edited by hand.
---
 .../_LIBC_MODULAR_FORMAT_PRINTF-disable.h        |  2 +-
 .../_LIBC_MODULAR_FORMAT_PRINTF.h                |  6 ++++--
 libc/include/stdio.yaml                          | 16 ++++++++--------
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF-disable.h b/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF-disable.h
index e3238161b3808..57aacadc704b5 100644
--- a/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF-disable.h
+++ b/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF-disable.h
@@ -9,6 +9,6 @@
 #ifndef LLVM_LIBC_MACROS_LIBC_MODULAR_FORMAT_PRINTF_H
 #define LLVM_LIBC_MACROS_LIBC_MODULAR_FORMAT_PRINTF_H
 
-#define _LIBC_MODULAR_FORMAT_PRINTF(MODULAR_IMPL_FN)
+#define _LIBC_MODULAR_FORMAT_PRINTF(MODULAR_IMPL_FN, FORMAT_IDX, FIRST_TO_CHECK)
 
 #endif // LLVM_LIBC_MACROS_LIBC_MODULAR_FORMAT_PRINTF_H
diff --git a/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h b/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h
index 918241ab8f2ec..8e6efe8868625 100644
--- a/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h
+++ b/libc/include/llvm-libc-macros/_LIBC_MODULAR_FORMAT_PRINTF.h
@@ -9,7 +9,9 @@
 #ifndef LLVM_LIBC_MACROS_LIBC_MODULAR_FORMAT_PRINTF_H
 #define LLVM_LIBC_MACROS_LIBC_MODULAR_FORMAT_PRINTF_H
 
-#define _LIBC_MODULAR_FORMAT_PRINTF(MODULAR_IMPL_FN)                           \
-  __attribute__((modular_format(MODULAR_IMPL_FN, "__printf", "float")))
+#define _LIBC_MODULAR_FORMAT_PRINTF(MODULAR_IMPL_FN, FORMAT_IDX,               \
+                                    FIRST_TO_CHECK)                            \
+  __attribute__((format(printf, FORMAT_IDX, FIRST_TO_CHECK),                   \
+                 modular_format(MODULAR_IMPL_FN, "__printf", "float")))
 
 #endif // LLVM_LIBC_MACROS_LIBC_MODULAR_FORMAT_PRINTF_H
diff --git a/libc/include/stdio.yaml b/libc/include/stdio.yaml
index 78d07052198ee..4b12698e2484d 100644
--- a/libc/include/stdio.yaml
+++ b/libc/include/stdio.yaml
@@ -51,7 +51,7 @@ functions:
       - type: const char *__restrict
       - type: '...'
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__asprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__asprintf_modular, 2, 3)
   - name: clearerr
     standards:
       - stdc
@@ -304,7 +304,7 @@ functions:
       - type: const char *__restrict
       - type: '...'
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__printf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__printf_modular, 1, 2)
   - name: putc
     standards:
       - stdc
@@ -377,7 +377,7 @@ functions:
       - type: const char *__restrict
       - type: '...'
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__snprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__snprintf_modular, 3, 4)
   - name: sprintf
     standards:
       - stdc
@@ -387,7 +387,7 @@ functions:
       - type: const char *__restrict
       - type: '...'
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__sprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__sprintf_modular, 2, 3)
   - name: sscanf
     standards:
       - stdc
@@ -412,7 +412,7 @@ functions:
       - type: const char *__restrict
       - type: va_list
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__vasprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__vasprintf_modular, 2, 0)
   - name: vfprintf
     standards:
       - stdc
@@ -429,7 +429,7 @@ functions:
       - type: const char *__restrict
       - type: va_list
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__vprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__vprintf_modular, 1, 0)
   - name: vsnprintf
     standards:
       - stdc
@@ -440,7 +440,7 @@ functions:
       - type: const char *__restrict
       - type: va_list
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__vsnprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__vsnprintf_modular, 3, 0)
   - name: vsprintf
     standards:
       - stdc
@@ -450,7 +450,7 @@ functions:
       - type: const char *__restrict
       - type: va_list
     attributes:
-      - _LIBC_MODULAR_FORMAT_PRINTF(__vsprintf_modular)
+      - _LIBC_MODULAR_FORMAT_PRINTF(__vsprintf_modular, 2, 0)
   - name: vsscanf
     standards:
       - stdc



More information about the libc-commits mailing list