[libc-commits] [libc] [libc][hdrgen] Extend guard attribute support for types (PR #189803)

via libc-commits libc-commits at lists.llvm.org
Tue Mar 31 23:23:55 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: pixl (un-pixelated)

<details>
<summary>Changes</summary>

Closes #<!-- -->187404 
- Add guard field to Type class
- Parse guard from yaml in yaml_to_classes.py
- Emit #ifdef/#endif for guarded types in include_lines()
- Validate that guard macros have macro_header in same yaml file
- Add integration tests for type guarding


---
Full diff: https://github.com/llvm/llvm-project/pull/189803.diff


9 Files Affected:

- (modified) libc/utils/hdrgen/hdrgen/header.py (+34-2) 
- (modified) libc/utils/hdrgen/hdrgen/type.py (+3-2) 
- (modified) libc/utils/hdrgen/hdrgen/yaml_to_classes.py (+15-1) 
- (added) libc/utils/hdrgen/tests/expected_output/type_guarding.h (+22) 
- (added) libc/utils/hdrgen/tests/expected_output/type_guarding_mixed.h (+27) 
- (added) libc/utils/hdrgen/tests/input/type_guarding.yaml (+15) 
- (added) libc/utils/hdrgen/tests/input/type_guarding_invalid_macro.yaml (+17) 
- (added) libc/utils/hdrgen/tests/input/type_guarding_mixed.yaml (+19) 
- (modified) libc/utils/hdrgen/tests/test_integration.py (+21) 


``````````diff
diff --git a/libc/utils/hdrgen/hdrgen/header.py b/libc/utils/hdrgen/hdrgen/header.py
index e2ebbdb6e519a..a5708fd284b0d 100644
--- a/libc/utils/hdrgen/hdrgen/header.py
+++ b/libc/utils/hdrgen/hdrgen/header.py
@@ -10,7 +10,6 @@
 from functools import reduce
 from pathlib import PurePosixPath
 
-
 STDINT_SIZES = [
     "16",
     "32",
@@ -175,6 +174,7 @@ def includes(self):
                     PurePosixPath("llvm-libc-types") / f"{typ.name}.h",
                 )
                 for typ in self.all_types()
+                if typ.guard is None
             }
             | {
                 PurePosixPath("llvm-libc-macros") / f"{attr.split('(')[0]}.h"
@@ -239,7 +239,7 @@ def relpath(file):
         # It's implicitly emitted here when using the default template so
         # it can get the right relative path.  Custom template files should
         # all have it explicitly with their right particular relative path.
-        return [
+        content = [
             f"#include {file}"
             for file in ([f'"{relpath(COMMON_HEADER)!s}"'] if with_common else [])
             + sorted(
@@ -248,6 +248,38 @@ def relpath(file):
             )
         ]
 
+        # Add guarded types
+        append_blank_line_if_guarded_types_exist = True
+        current_guard = None
+        for typ in sorted(self.types):
+            path = COMPILER_HEADER_TYPES.get(
+                typ.name,
+                PurePosixPath("llvm-libc-types") / f"{typ.name}.h",
+            )
+            if append_blank_line_if_guarded_types_exist and typ.guard is not None:
+                append_blank_line_if_guarded_types_exist = False
+                content.append("")
+            if typ.guard is None:
+                continue
+            if current_guard is None:
+                current_guard = typ.guard
+                content.append(f"#ifdef {current_guard}")
+                content.append(f'#include "{relpath(path)!s}"')
+            elif current_guard == typ.guard:
+                content.append(f'#include "{relpath(path)!s}"')
+            else:
+                content.append(f"#endif // {current_guard}")
+                content.append("")
+                current_guard = typ.guard
+                if current_guard is not None:
+                    content.append(f"#ifdef {current_guard}")
+                content.append(f'#include "{relpath(path)!s}"')
+        if current_guard is not None:
+            content.append(f"#endif // {current_guard}")
+            content.append("")
+
+        return content
+
     def macro_lines(self):
         content = []
         for macro in sorted(self.macros):
diff --git a/libc/utils/hdrgen/hdrgen/type.py b/libc/utils/hdrgen/hdrgen/type.py
index 20c1881a9379a..4ea5c31c8f1f3 100644
--- a/libc/utils/hdrgen/hdrgen/type.py
+++ b/libc/utils/hdrgen/hdrgen/type.py
@@ -10,6 +10,7 @@
 
 
 class Type(Symbol):
-    # A type so far carries no specific information beyond its name.
-    def __init__(self, name):
+    # A type carries its name and guard.
+    def __init__(self, name, guard=None):
         super().__init__(name)
+        self.guard = guard
diff --git a/libc/utils/hdrgen/hdrgen/yaml_to_classes.py b/libc/utils/hdrgen/hdrgen/yaml_to_classes.py
index 85aa3267b5274..d174a1b4c4307 100644
--- a/libc/utils/hdrgen/hdrgen/yaml_to_classes.py
+++ b/libc/utils/hdrgen/hdrgen/yaml_to_classes.py
@@ -52,7 +52,21 @@ def yaml_to_classes(yaml_data, header_class, entry_points=None):
     types = yaml_data.get("types", [])
     sorted_types = sorted(types, key=lambda x: x["type_name"])
     for type_data in sorted_types:
-        header.add_type(Type(type_data["type_name"]))
+        type_name = type_data["type_name"]
+        type_guard = type_data.get("guard")
+        # If a type has a guard, the macro it references must exist in
+        # the same yaml file with a macro_header attribute.
+        if type_guard is not None and not any(
+            macro_data["macro_name"] == type_guard
+            and macro_data.get("macro_header") is not None
+            for macro_data in yaml_data.get("macros", [])
+        ):
+            raise ValueError(
+                f"Type '{type_name}' has guard '{type_guard}' but no macro with "
+                f"macro_header '{type_guard}' was found in this file."
+            )
+
+        header.add_type(Type(type_name, type_guard))
 
     for enum_data in yaml_data.get("enums", []):
         header.add_enumeration(
diff --git a/libc/utils/hdrgen/tests/expected_output/type_guarding.h b/libc/utils/hdrgen/tests/expected_output/type_guarding.h
new file mode 100644
index 0000000000000..b01dbea891231
--- /dev/null
+++ b/libc/utils/hdrgen/tests/expected_output/type_guarding.h
@@ -0,0 +1,22 @@
+//===-- Standard C header <type_guarding.h> --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef _LLVM_LIBC_TYPE_GUARDING_H
+#define _LLVM_LIBC_TYPE_GUARDING_H
+
+#include "__llvm-libc-common.h"
+#include "llvm-libc-macros/size_t-macro.h"
+#include "llvm-libc-types/myType.h"
+#include <stdint.h>
+
+#ifdef LIBC_TYPES_HAS_SIZE_T
+#include "llvm-libc-types/size_t.h"
+#include "llvm-libc-types/ssize_t.h"
+#endif // LIBC_TYPES_HAS_SIZE_T
+
+#endif // _LLVM_LIBC_TYPE_GUARDING_H
diff --git a/libc/utils/hdrgen/tests/expected_output/type_guarding_mixed.h b/libc/utils/hdrgen/tests/expected_output/type_guarding_mixed.h
new file mode 100644
index 0000000000000..33a6fbd22d8d0
--- /dev/null
+++ b/libc/utils/hdrgen/tests/expected_output/type_guarding_mixed.h
@@ -0,0 +1,27 @@
+//===-- Standard C header <type_guarding_mixed.h> --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef _LLVM_LIBC_TYPE_GUARDING_MIXED_H
+#define _LLVM_LIBC_TYPE_GUARDING_MIXED_H
+
+#include "__llvm-libc-common.h"
+#include "llvm-libc-macros/float16-macro.h"
+#include "llvm-libc-macros/size_t-macro.h"
+#include "llvm-libc-types/myType.h"
+#include <stdint.h>
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+#include "llvm-libc-types/float16.h"
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#ifdef LIBC_TYPES_HAS_SIZE_T
+#include "llvm-libc-types/size_t.h"
+#include "llvm-libc-types/ssize_t.h"
+#endif // LIBC_TYPES_HAS_SIZE_T
+
+#endif // _LLVM_LIBC_TYPE_GUARDING_MIXED_H
diff --git a/libc/utils/hdrgen/tests/input/type_guarding.yaml b/libc/utils/hdrgen/tests/input/type_guarding.yaml
new file mode 100644
index 0000000000000..79ddfe4bad151
--- /dev/null
+++ b/libc/utils/hdrgen/tests/input/type_guarding.yaml
@@ -0,0 +1,15 @@
+header: type_guarding.h
+standards:
+  - stdc
+
+macros:
+  - macro_name: LIBC_TYPES_HAS_SIZE_T
+    macro_header: size_t-macro.h
+
+types:
+  - type_name: size_t
+    guard: LIBC_TYPES_HAS_SIZE_T
+  - type_name: ssize_t
+    guard: LIBC_TYPES_HAS_SIZE_T
+  - type_name: uint8_t
+  - type_name: myType
diff --git a/libc/utils/hdrgen/tests/input/type_guarding_invalid_macro.yaml b/libc/utils/hdrgen/tests/input/type_guarding_invalid_macro.yaml
new file mode 100644
index 0000000000000..daf43a90b29bf
--- /dev/null
+++ b/libc/utils/hdrgen/tests/input/type_guarding_invalid_macro.yaml
@@ -0,0 +1,17 @@
+header: type_guarding_invalid_macro.h
+standards:
+  - stdc
+
+macros:
+  - macro_name: LIBC_TYPES_HAS_SIZE_T
+    macro_header: size_t-macro.h
+  - macro_name: MY_TYPES_GUARD
+
+types:
+  - type_name: size_t
+    guard: LIBC_TYPES_HAS_SIZE_T
+  - type_name: ssize_t
+    guard: LIBC_TYPES_HAS_SIZE_T
+  - type_name: uint8_t
+  - type_name: myType
+    guard: MY_TYPES_GUARD
diff --git a/libc/utils/hdrgen/tests/input/type_guarding_mixed.yaml b/libc/utils/hdrgen/tests/input/type_guarding_mixed.yaml
new file mode 100644
index 0000000000000..b1e7fb14e5d3b
--- /dev/null
+++ b/libc/utils/hdrgen/tests/input/type_guarding_mixed.yaml
@@ -0,0 +1,19 @@
+header: type_guarding_mixed.h
+standards:
+  - stdc
+
+macros:
+  - macro_name: LIBC_TYPES_HAS_SIZE_T
+    macro_header: size_t-macro.h
+  - macro_name: LIBC_TYPES_HAS_FLOAT16
+    macro_header: float16-macro.h
+
+types:
+  - type_name: size_t
+    guard: LIBC_TYPES_HAS_SIZE_T
+  - type_name: ssize_t
+    guard: LIBC_TYPES_HAS_SIZE_T
+  - type_name: float16
+    guard: LIBC_TYPES_HAS_FLOAT16
+  - type_name: uint8_t
+  - type_name: myType
diff --git a/libc/utils/hdrgen/tests/test_integration.py b/libc/utils/hdrgen/tests/test_integration.py
index 8848afe29d50f..9a87a5831f900 100644
--- a/libc/utils/hdrgen/tests/test_integration.py
+++ b/libc/utils/hdrgen/tests/test_integration.py
@@ -96,6 +96,27 @@ def test_generate_macro_only_header(self):
         self.run_script(yaml_file, output_file)
         self.compare_files(output_file, expected_output_file)
 
+    def test_type_guarding(self):
+        yaml_file = self.source_dir / "input/type_guarding.yaml"
+        expected_output_file = self.source_dir / "expected_output/type_guarding.h"
+        output_file = self.output_dir / "type_guarding.h"
+        self.run_script(yaml_file, output_file)
+        self.compare_files(output_file, expected_output_file)
+
+    def test_type_guarding_mixed(self):
+        yaml_file = self.source_dir / "input/type_guarding_mixed.yaml"
+        expected_output_file = self.source_dir / "expected_output/type_guarding_mixed.h"
+        output_file = self.output_dir / "type_guarding_mixed.h"
+        self.run_script(yaml_file, output_file)
+        self.compare_files(output_file, expected_output_file)
+
+    def test_type_guarding_invalid_macro(self):
+        yaml_file = self.source_dir / "input/type_guarding_invalid_macro.yaml"
+        output_file = self.output_dir / "type_guarding_invalid_macro.h"
+        with self.assertRaises(subprocess.CalledProcessError):
+            self.run_script(yaml_file, output_file)
+
+
 def main():
     parser = argparse.ArgumentParser(description="TestHeaderGenIntegration arguments")
     parser.add_argument(

``````````

</details>


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


More information about the libc-commits mailing list