[clang] [flang] [clang][flang][docs] Re-land Markdown CLI ref generator (PR #222147)
Reid Kleckner via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 8 15:50:17 PDT 2026
https://github.com/rnk updated https://github.com/llvm/llvm-project/pull/222147
>From 9337c420844d1637cca37e724e1b3c3378a5cbee Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 8 Sep 2026 20:25:39 +0000
Subject: [PATCH 1/3] [clang][docs] Reapply Markdown command line reference
generation
---
clang/docs/CMakeLists.txt | 14 ++--
.../include/clang/Options/ClangOptionDocs.td | 19 +++---
clang/include/clang/Options/Options.td | 65 ++++++++++---------
.../utils/TableGen/ClangOptionDocEmitter.cpp | 65 +++++++++++--------
4 files changed, 87 insertions(+), 76 deletions(-)
diff --git a/clang/docs/CMakeLists.txt b/clang/docs/CMakeLists.txt
index f6f70cd7ce01b..79c2d30a3ae7c 100644
--- a/clang/docs/CMakeLists.txt
+++ b/clang/docs/CMakeLists.txt
@@ -80,7 +80,7 @@ if (LLVM_ENABLE_DOXYGEN)
endif()
endif()
-function (gen_rst_file_from_td output_file td_option source docs_targets)
+function (gen_sphinx_file_from_td output_file td_option source docs_targets)
if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
message(FATAL_ERROR "Cannot find source file: ${source} in ${CMAKE_CURRENT_SOURCE_DIR}")
endif()
@@ -104,9 +104,9 @@ if (LLVM_ENABLE_SPHINX)
# directory before we run sphinx.
set(clang_generated_docs
AttributeReference.md
- DiagnosticsReference.md
+ DiagnosticsReference.md
AMDGPUBuiltinReference.rst
- ClangCommandLineReference.rst
+ ClangCommandLineReference.md
analyzer/user-docs/Options.rst)
add_sphinx_source_sync_target(copy-clang-rst-docs
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}"
@@ -145,10 +145,10 @@ if (LLVM_ENABLE_SPHINX)
endif()
# Generated files
- gen_rst_file_from_td(AttributeReference.md -gen-attr-docs ../include/clang/Basic/Attr.td "${docs_targets}")
- gen_rst_file_from_td(DiagnosticsReference.md -gen-diag-docs ../include/clang/Basic/Diagnostic.td "${docs_targets}")
- gen_rst_file_from_td(AMDGPUBuiltinReference.rst -gen-builtin-docs ../include/clang/Basic/BuiltinsAMDGPU.td "${docs_targets}")
- gen_rst_file_from_td(ClangCommandLineReference.rst -gen-opt-docs ../include/clang/Options/ClangOptionDocs.td "${docs_targets}")
+ gen_sphinx_file_from_td(AttributeReference.md -gen-attr-docs ../include/clang/Basic/Attr.td "${docs_targets}")
+ gen_sphinx_file_from_td(DiagnosticsReference.md -gen-diag-docs ../include/clang/Basic/Diagnostic.td "${docs_targets}")
+ gen_sphinx_file_from_td(AMDGPUBuiltinReference.rst -gen-builtin-docs ../include/clang/Basic/BuiltinsAMDGPU.td "${docs_targets}")
+ gen_sphinx_file_from_td(ClangCommandLineReference.md -gen-opt-docs ../include/clang/Options/ClangOptionDocs.td "${docs_targets}")
# Another generated file from a different source
set(docs_tools_dir ${CMAKE_CURRENT_SOURCE_DIR}/tools)
diff --git a/clang/include/clang/Options/ClangOptionDocs.td b/clang/include/clang/Options/ClangOptionDocs.td
index 917d9773bdb2d..57ed3af73fbb6 100644
--- a/clang/include/clang/Options/ClangOptionDocs.td
+++ b/clang/include/clang/Options/ClangOptionDocs.td
@@ -7,21 +7,18 @@
//===----------------------------------------------------------------------===//
def GlobalDocumentation {
- code Intro =[{..
- -------------------------------------------------------------------
- NOTE: This file is automatically generated by running clang-tblgen
- -gen-opt-docs. Do not edit this file by hand!!
- -------------------------------------------------------------------
+ code Intro =[{%
+% -------------------------------------------------------------------
+% NOTE: This file is automatically generated by running clang-tblgen
+% -gen-opt-docs. Do not edit this file by hand!!
+% -------------------------------------------------------------------
-=====================================
-Clang command line argument reference
-=====================================
+# Clang command line argument reference
-Introduction
-============
+## Introduction
This page lists the command line arguments currently supported by the
-GCC-compatible ``clang`` and ``clang++`` drivers.
+GCC-compatible `clang` and `clang++` drivers.
}];
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index b4023d278dfe8..f7e22ee84a9f4 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -100,10 +100,11 @@ def DXCOption : OptionVisibility;
/////////
// Docs
-// A short name to show in documentation. The name will be interpreted as rST.
+// A short name to show in documentation. The name will be interpreted as
+// Markdown.
class DocName<string name> { string DocName = name; }
-// A brief description to show in documentation, interpreted as rST.
+// A brief description to show in documentation, interpreted as Markdown.
class DocBrief<code descr> { code DocBrief = descr; }
// Indicates that this group should be flattened into its parent when generating
@@ -133,7 +134,7 @@ Flags controlling the behavior of the %Program preprocessor.}]>.str>;
def IncludePath_Group : OptionGroup<"<I/i group>">, Group<Preprocessor_Group>,
DocName<"Include path management">,
DocBrief<[{
-Flags controlling how ``#include``\s are resolved to files.}]>;
+Flags controlling how `#include`s are resolved to files.}]>;
def I_Group : OptionGroup<"<I group>">, Group<IncludePath_Group>, DocFlatten;
def i_Group : OptionGroup<"<i group>">, Group<IncludePath_Group>, DocFlatten;
@@ -141,7 +142,7 @@ def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>, DocFlatten;
def M_Group : OptionGroup<"<M group>">, Group<Preprocessor_Group>,
DocName<"Dependency file generation">, DocBrief<[{
-Flags controlling generation of a dependency file for ``make``-like build
+Flags controlling generation of a dependency file for `make`-like build
systems.}]>;
def d_Group : OptionGroup<"<d group>">, Group<Preprocessor_Group>,
@@ -154,7 +155,7 @@ def Diag_Group : OptionGroup<"<W/R group>">, Group<CompileOnly_Group>,
"Flags controlling which warnings, errors, and remarks %Program will generate. ">.str,
// When in clang link directly to the page.
!cond(!eq(GlobalDocumentation.Program, "Clang"):
-"See the :doc:`full list of warning and remark flags <DiagnosticsReference>`.",
+"See the {doc}`full list of warning and remark flags <DiagnosticsReference>`.",
// When elsewhere the link will not work.
true:
"See Clang's Diagnostic Reference for a full list of warning and remark flags."))>;
@@ -282,7 +283,7 @@ Flags controlling the behavior of the Scalable Static Analysis Framework (SSAF).
// invoking GCC to compile Fortran code.
def gfortran_Group : OptionGroup<"<gfortran group>">,
DocName<"Fortran compilation options">, DocBrief<[{
-Flags that will be passed onto the ``gfortran`` compiler when Clang is given
+Flags that will be passed onto the `gfortran` compiler when Clang is given
a Fortran input.}]>;
def Link_Group : OptionGroup<"<T/e/s/t/u group>">, DocName<"Linker options">,
@@ -783,8 +784,8 @@ def H : Flag<["-"], "H">, Visibility<[ClangOption, CC1Option]>,
def fshow_skipped_includes : Flag<["-"], "fshow-skipped-includes">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Show skipped includes in -H output.">,
- DocBrief<[{#include files may be "skipped" due to include guard optimization
- or #pragma once. This flag makes -H show also such includes.}]>,
+ DocBrief<[{`#include` files may be "skipped" due to include guard optimization
+or `#pragma once`. This flag makes `-H` show also such includes.}]>,
MarshallingInfoFlag<DependencyOutputOpts<"ShowSkippedHeaderIncludes">>;
def I_ : Flag<["-"], "I-">, Group<I_Group>, IgnoredGCCCompat,
@@ -1055,13 +1056,13 @@ def Xarch__
HelpText<"Pass <arg> to the compilation if the target matches <arch>">,
DocBrief<
[{Specifies that the argument should only be used if the compilation
- target matches the specified architecture. This can be used with the target
- CPU, triple architecture, or offloading host and device. It is most useful
- for separating behavior undesirable on one of the targets when combining many
- compilation jobs, as is common with offloading. For example, -Xarch_x86_64,
- -Xarch_gfx90a, and -Xarch_device are all valid selectors. -Xarch_device will
- forward the argument to the offloading device while -Xarch_host will target
- the host system, which can be used to suppress incompatible GPU arguments.}]>,
+target matches the specified architecture. This can be used with the target
+CPU, triple architecture, or offloading host and device. It is most useful
+for separating behavior undesirable on one of the targets when combining many
+compilation jobs, as is common with offloading. For example, `-Xarch_x86_64`,
+`-Xarch_gfx90a`, and `-Xarch_device` are all valid selectors. `-Xarch_device` will
+forward the argument to the offloading device while `-Xarch_host` will target
+the host system, which can be used to suppress incompatible GPU arguments.}]>,
MetaVarName<"<arch> <arg>">;
def Xarch_host : Separate<["-"], "Xarch_host">, Flags<[NoXarchOption]>,
HelpText<"Pass <arg> to host compilation in the offloading toolchain">, MetaVarName<"<arg>">;
@@ -1735,10 +1736,10 @@ def fstrict_flex_arrays_EQ : Joined<["-"], "fstrict-flex-arrays=">, Group<f_Grou
NormalizedValuesScope<"LangOptions::StrictFlexArraysLevelKind">,
NormalizedValues<["Default", "OneZeroOrIncomplete", "ZeroOrIncomplete", "IncompleteOnly"]>,
HelpText<"Enable optimizations based on the strict definition of flexible arrays.">,
- DocBrief<[{If ``<n>`` is equal to 0, any trailing array member is considered a flexible array.
- If ``<n>`` is equal to 1, trailing array members of size 0, 1 or undefined are considered flexible arrays.
- If ``<n>`` is equal to 2, trailing array members of size 0 or undefined are considered flexible arrays.
- If ``<n>`` is equal to 3, only trailing array members of undefined size are considered flexible arrays.}]>,
+ DocBrief<[{If `<n>` is equal to 0, any trailing array member is considered a flexible array.
+If `<n>` is equal to 1, trailing array members of size 0, 1 or undefined are considered flexible arrays.
+If `<n>` is equal to 2, trailing array members of size 0 or undefined are considered flexible arrays.
+If `<n>` is equal to 3, only trailing array members of undefined size are considered flexible arrays.}]>,
MarshallingInfoEnum<LangOpts<"StrictFlexArraysLevel">, "Default">;
defm apple_pragma_pack : BoolFOption<"apple-pragma-pack",
LangOpts<"ApplePragmaPack">, DefaultFalse,
@@ -1887,18 +1888,18 @@ def fprofile_sample_accurate : Flag<["-"], "fprofile-sample-accurate">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Specifies that the sample profile is accurate">,
DocBrief<[{Specifies that the sample profile is accurate. If the sample
- profile is accurate, callsites without profile samples are marked
- as cold. Otherwise, treat callsites without profile samples as if
- we have no profile}]>,
+profile is accurate, callsites without profile samples are marked
+as cold. Otherwise, treat callsites without profile samples as if
+we have no profile}]>,
MarshallingInfoFlag<CodeGenOpts<"ProfileSampleAccurate">>;
def fsample_profile_use_profi : Flag<["-"], "fsample-profile-use-profi">,
Visibility<[ClangOption, CC1Option]>,
Group<f_Group>,
HelpText<"Use profi to infer block and edge counts">,
DocBrief<[{Infer block and edge counts. If the profiles have errors or missing
- blocks caused by sampling, profile inference (profi) can convert
- basic block counts to branch probabilities to fix them by extended
- and re-engineered classic MCMF (min-cost max-flow) approach.}]>;
+blocks caused by sampling, profile inference (profi) can convert
+basic block counts to branch probabilities to fix them by extended
+and re-engineered classic MCMF (min-cost max-flow) approach.}]>;
def fno_profile_sample_accurate : Flag<["-"], "fno-profile-sample-accurate">, Group<f_Group>;
def fno_sample_profile_use_profi : Flag<["-"], "fno-sample-profile-use-profi">,
Group<f_Group>;
@@ -2793,14 +2794,14 @@ defm sanitize_address_poison_custom_array_cookie : BoolOption<"f", "sanitize-add
NegFlag<SetFalse, [], [ClangOption], "Disable">,
BothFlags<[], [ClangOption], " poisoning array cookies when using custom operator new[] in AddressSanitizer">>,
DocBrief<[{Enable "poisoning" array cookies when allocating arrays with a
-custom operator new\[\] in Address Sanitizer, preventing accesses to the
+custom operator new[] in Address Sanitizer, preventing accesses to the
cookies from user code. An array cookie is a small implementation-defined
header added to certain array allocations to record metadata such as the
length of the array. Accesses to array cookies from user code are technically
allowed by the standard but are more likely to be the result of an
out-of-bounds array access.
-An operator new\[\] is "custom" if it is not one of the allocation functions
+An operator new[] is "custom" if it is not one of the allocation functions
provided by the C++ standard library. Array cookies from non-custom allocation
functions are always poisoned.}]>,
Group<f_clang_Group>;
@@ -4788,8 +4789,8 @@ def ftime_trace : Flag<["-"], "ftime-trace">, Group<f_Group>,
HelpText<"Turn on time profiler. Generates JSON file based on output filename.">,
DocBrief<[{
Turn on time profiler. Generates JSON file based on output filename. Results
-can be analyzed with chrome://tracing or `Speedscope App
-<https://www.speedscope.app>`_ for flamegraph visualization.}]>,
+can be analyzed with chrome://tracing or [Speedscope App](https://www.speedscope.app)
+for flamegraph visualization.}]>,
Visibility<[ClangOption, CLOption, DXCOption]>;
def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Group<f_Group>,
HelpText<"Minimum time granularity (in microseconds) traced by time profiler">,
@@ -5006,7 +5007,7 @@ def fdefined_pointer_subtraction :
"When subtracting two pointers, do not assume that the byte difference is an "
"exact multiple of the pointee type size, thereby preventing such subtraction "
"from resulting in undefined behavior. Users should prefer casting pointers "
- "to ``char *`` before subtracting them rather than relying on this flag."
+ "to `char *` before subtracting them rather than relying on this flag."
>,
MarshallingInfoFlag<LangOpts<"StablePointerSubtraction">>;
def fno_wrapv_pointer : Flag<["-"], "fno-wrapv-pointer">, Group<f_Group>,
@@ -5388,9 +5389,9 @@ defm structor_decl_linkage_names
"declarations in DWARF.">,
BothFlags<[], [ClangOption, CLOption, CC1Option]>>,
Group<g_flags_Group>,
- DocBrief<[{On some ABIs (e.g., Itanium), constructors and destructors may have multiple variants. Historically, when generating DWARF, Clang did not attach ``DW_AT_linkage_name`` to structor DIEs because there were multiple possible manglings (depending on the structor variant) that could be used. With ``-gstructor-decl-linkage-names``, for ABIs with structor variants, we attach a "unified" mangled name to structor declarations DIEs which debuggers can use to look up all the definitions for a structor declaration. E.g., a "unified" mangled name ``_ZN3FooC4Ev`` may have multiple definitions associated with it such as ``_ZN3FooC1Ev`` and ``_ZN3FooC2Ev``.
+ DocBrief<[{On some ABIs (e.g., Itanium), constructors and destructors may have multiple variants. Historically, when generating DWARF, Clang did not attach `DW_AT_linkage_name` to structor DIEs because there were multiple possible manglings (depending on the structor variant) that could be used. With `-gstructor-decl-linkage-names`, for ABIs with structor variants, we attach a "unified" mangled name to structor declarations DIEs which debuggers can use to look up all the definitions for a structor declaration. E.g., a "unified" mangled name `_ZN3FooC4Ev` may have multiple definitions associated with it such as `_ZN3FooC1Ev` and `_ZN3FooC2Ev`.
-Enabling this flag results in a better interactive debugging experience (both GDB and LLDB have support for understanding these "unified" linkage names). However, it comes with a significant increase in debug-info size (particularly the `.debug_str` section). As an escape hatch, users can disable this feature using ``-gno-structor-decl-linkage-names``.}]>;
+Enabling this flag results in a better interactive debugging experience (both GDB and LLDB have support for understanding these "unified" linkage names). However, it comes with a significant increase in debug-info size (particularly the `.debug_str` section). As an escape hatch, users can disable this feature using `-gno-structor-decl-linkage-names`.}]>;
defm key_instructions : BoolGOption<"key-instructions",
CodeGenOpts<"DebugKeyInstructions">, DefaultFalse,
NegFlag<SetFalse>, PosFlag<SetTrue, [], [],
diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index f790a496ead6a..74ddb6b276671 100644
--- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -195,12 +195,12 @@ unsigned getNumArgsForKind(const Record *OptionKind, const Record *Option) {
.Default(0);
}
-std::string escapeRST(StringRef Str) {
+std::string escapePlainTextForMarkdown(StringRef Str) {
std::string Out;
- for (auto K : Str) {
- if (StringRef("`*|[]\\").count(K))
+ for (char C : Str) {
+ if (StringRef("*[]\\<>").count(C))
Out.push_back('\\');
- Out.push_back(K);
+ Out.push_back(C);
}
return Out;
}
@@ -219,37 +219,42 @@ bool canSphinxCopeWithOption(const Record *Option) {
}
void emitHeading(int Depth, const std::string &Heading, raw_ostream &OS) {
- assert(Depth < 8 && "groups nested too deeply");
- OS << Heading << '\n'
- << std::string(Heading.size(), "=~-_'+<>"[Depth]) << "\n";
+ assert(Depth < 5 && "groups nested too deeply");
+ OS << std::string(Depth + 2, '#') << ' ' << Heading << "\n\n";
}
/// Get the value of field \p Primary, if possible. If \p Primary does not
-/// exist, get the value of \p Fallback and escape it for rST emission.
-std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary,
- StringRef Fallback) {
+/// exist, get the value of \p Fallback and escape it for Markdown emission.
+std::string getMarkdownStringWithTextFallback(const Record *R,
+ StringRef Primary,
+ StringRef Fallback) {
for (auto Field : {Primary, Fallback}) {
if (auto *V = R->getValue(Field)) {
StringRef Value;
if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue()))
Value = SV->getValue();
if (!Value.empty())
- return Field == Primary ? Value.str() : escapeRST(Value);
+ return Field == Primary ? Value.str()
+ : escapePlainTextForMarkdown(Value);
}
}
return std::string(StringRef());
}
+// The Sphinx option directive contents do not need to be escaped. They use
+// standard usage conventions, where angle brackets are values, and square
+// brackets are optional arguments. See
+// https://www.sphinx-doc.org/en/master/usage/domains/standard.html#directive-option
void emitOptionWithArgs(StringRef Prefix, const Record *Option,
ArrayRef<StringRef> Args, raw_ostream &OS) {
- OS << Prefix << escapeRST(Option->getValueAsString("Name"));
+ OS << Prefix << Option->getValueAsString("Name");
std::pair<StringRef, StringRef> Separators =
getSeparatorsForKind(Option->getValueAsDef("Kind"));
StringRef Separator = Separators.first;
for (auto Arg : Args) {
- OS << Separator << escapeRST(Arg);
+ OS << Separator << Arg;
Separator = Separators.second;
}
}
@@ -346,17 +351,15 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
std::string Program = DocInfo->getValueAsString("Program").lower();
if (SphinxWorkaroundSuffix)
- OS << ".. program:: " << Program << SphinxWorkaroundSuffix << "\n";
+ OS << "```{program} " << Program << SphinxWorkaroundSuffix << "\n```\n\n";
// Emit the names of the option.
- OS << ".. option:: ";
+ OS << ":::{option} ";
bool EmittedAny = false;
forEachOptionName(Option, DocInfo, [&](const Record *Option) {
EmittedAny = emitOptionNames(Option, OS, EmittedAny);
});
- if (SphinxWorkaroundSuffix)
- OS << "\n.. program:: " << Program;
- OS << "\n\n";
+ OS << "\n:::\n\n";
// Emit the description, if we have one.
const Record *R = Option.Option;
@@ -376,7 +379,8 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
for (const Init *Visibility : Visibilities) {
if (Visibility->getAsUnquotedString() == DocInfoMask) {
// Use the first one we find.
- Description = escapeRST(VisibilityHelp->getValueAsString("Text"));
+ Description = escapePlainTextForMarkdown(
+ VisibilityHelp->getValueAsString("Text"));
break;
}
}
@@ -390,7 +394,7 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
// If there's not a program specific string, use the default one.
if (Description.empty())
- Description = getRSTStringWithTextFallback(R, "DocBrief", "HelpText");
+ Description = getMarkdownStringWithTextFallback(R, "DocBrief", "HelpText");
if (!isa<UnsetInit>(R->getValueInit("Values"))) {
if (!Description.empty() && Description.back() != '.')
@@ -404,16 +408,23 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
SmallVector<StringRef> Values;
SplitString(R->getValueAsString("Values"), Values, ",");
- Description += (" " + MetaVarName + " must be '").str();
+ Description += " " + escapePlainTextForMarkdown(MetaVarName) + " must be '";
if (Values.size() > 1) {
- Description += join(Values.begin(), Values.end() - 1, "', '");
+ for (auto [I, Value] : enumerate(drop_end(Values))) {
+ if (I)
+ Description += "', '";
+ Description += escapePlainTextForMarkdown(Value);
+ }
Description += "' or '";
}
- Description += (Values.back() + "'.").str();
+ Description += escapePlainTextForMarkdown(Values.back()) + "'.";
}
if (!Description.empty())
OS << Description << "\n\n";
+
+ if (SphinxWorkaroundSuffix)
+ OS << "```{program} " << Program << "\n```\n\n";
}
void emitDocumentation(int Depth, const Documentation &Doc,
@@ -422,11 +433,12 @@ void emitDocumentation(int Depth, const Documentation &Doc,
void emitGroup(int Depth, const DocumentedGroup &Group, const Record *DocInfo,
raw_ostream &OS) {
emitHeading(Depth,
- getRSTStringWithTextFallback(Group.Group, "DocName", "Name"), OS);
+ getMarkdownStringWithTextFallback(Group.Group, "DocName", "Name"),
+ OS);
// Emit the description, if we have one.
std::string Description =
- getRSTStringWithTextFallback(Group.Group, "DocBrief", "HelpText");
+ getMarkdownStringWithTextFallback(Group.Group, "DocBrief", "HelpText");
if (!Description.empty())
OS << Description << "\n\n";
@@ -452,7 +464,8 @@ void clang::EmitClangOptDocs(const RecordKeeper &Records, raw_ostream &OS) {
return;
}
OS << DocInfo->getValueAsString("Intro") << "\n";
- OS << ".. program:: " << DocInfo->getValueAsString("Program").lower() << "\n";
+ OS << "```{program} " << DocInfo->getValueAsString("Program").lower()
+ << "\n```\n\n";
emitDocumentation(0, extractDocumentation(Records, DocInfo), DocInfo, OS);
}
>From bf7eb9f0de33dfbd88b532d11792eac22c9c2480 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 8 Sep 2026 20:28:05 +0000
Subject: [PATCH 2/3] [flang][docs] Support Markdown option documentation
---
clang/include/clang/Options/FlangOptions.td | 93 ++++++++++-----------
flang/docs/CMakeLists.txt | 30 +++----
flang/docs/FlangOptionsDocs.td | 23 +++--
flang/docs/FlangOptionsMan.td | 12 +--
4 files changed, 75 insertions(+), 83 deletions(-)
diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index dad57464799c3..8fd0d78a2659c 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -236,11 +236,11 @@ programs:
* OpenACC/OpenMP offload programs may behave incorrectly with regards
to the device data environment, due to the fact that the original
array and the temporary may have different presence status on the device.
-* ``IS_CONTIGUOUS`` intrinsic may return ``TRUE`` with the array repacking
- enabled, whereas if would return ``FALSE`` with the repacking disabled.
-* The result of ``LOC`` intrinsic applied to an actual argument associated
+* `IS_CONTIGUOUS` intrinsic may return `TRUE` with the array repacking
+ enabled, whereas if would return `FALSE` with the repacking disabled.
+* The result of `LOC` intrinsic applied to an actual argument associated
with a non-contiguous assumed shape dummy array, may be different
- from the result of ``LOC`` applied to the dummy array.}]>;
+ from the result of `LOC` applied to the dummy array.}]>;
def frepack_arrays_contiguity_EQ
: Joined<["-"], "frepack-arrays-contiguity=">,
@@ -295,10 +295,10 @@ def relaxed_c_loc : Flag<["-"], "frelaxed-c-loc-checks">, Group<f_Group>,
Visibility<[FlangOption, FC1Option]>,
HelpText<"Allow a data object or function pointer as the C_LOC() argument">,
DocBrief<[{
- Allow a data object or function pointer as the C_LOC() argument
- (not just pointers/targets). The compiler will not reason about aliases
- created through non-target non-pointer arguments and code generated
- using such aliases may exhibit unexpected behavior.}]>;
+Allow a data object or function pointer as the C_LOC() argument
+(not just pointers/targets). The compiler will not reason about aliases
+created through non-target non-pointer arguments and code generated
+using such aliases may exhibit unexpected behavior.}]>;
def fhermetic_module_files : Flag<["-"], "fhermetic-module-files">, Group<f_Group>,
HelpText<"Emit hermetic module files (no nested USE association)">;
@@ -326,12 +326,12 @@ defm fp_sum_reassociation
"Disable reassociation within individual REAL and COMPLEX "
"sum expressions">>,
DocBrief<[{
- Enable Fortran-standard compliant reassociation within individual
- ``REAL`` and ``COMPLEX`` sum expressions. This can improve optimization
- opportunities and may change exact floating-point results while
- preserving standard-conforming Fortran semantics. It is enabled by
- default at all optimization levels.
- }]>;
+Enable Fortran-standard compliant reassociation within individual
+`REAL` and `COMPLEX` sum expressions. This can improve optimization
+opportunities and may change exact floating-point results while
+preserving standard-conforming Fortran semantics. It is enabled by
+default at all optimization levels.
+}]>;
def freal_sum_reassociation : Flag<["-"], "freal-sum-reassociation">,
Flags<[HelpHidden]>, Alias<ffp_sum_reassociation>;
@@ -340,61 +340,52 @@ def fno_real_sum_reassociation : Flag<["-"], "fno-real-sum-reassociation">,
def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<f_Group>,
HelpText<"Set the initial floating-point exception halting mode for the main program">,
- DocBrief<[{The ``-ffpe-trap=[list]`` option sets the initial floating-point
+ DocBrief<[{The `-ffpe-trap=[list]` option sets the initial floating-point
exception halting mode for the main program unit. This is the halting mode in
effect when the main program begins execution; the program may subsequently
-change it (for example, with ``IEEE_SET_HALTING_MODE``). ``[list]`` is a
-(possibly empty) comma-separated list of ``none`` or the following exceptions:
-``invalid``, ``zero``, ``overflow``, ``underflow``, ``inexact``, and
-``denormal``. The first five exceptions correspond to the Fortran 2023 (17.6)
-``IEEE_FLAG_TYPE`` values ``IEEE_INVALID``, ``IEEE_DIVIDE_BY_ZERO``,
-``IEEE_OVERFLOW``, ``IEEE_UNDERFLOW``, and ``IEEE_INEXACT``, whereas
-``denormal`` is a non-standard GFortran-compatible extension that halts on the
-hardware denormal (subnormal) operand exception. The value ``none`` may appear
+change it (for example, with `IEEE_SET_HALTING_MODE`). `[list]` is a
+(possibly empty) comma-separated list of `none` or the following exceptions:
+`invalid`, `zero`, `overflow`, `underflow`, `inexact`, and
+`denormal`. The first five exceptions correspond to the Fortran 2023 (17.6)
+`IEEE_FLAG_TYPE` values `IEEE_INVALID`, `IEEE_DIVIDE_BY_ZERO`,
+`IEEE_OVERFLOW`, `IEEE_UNDERFLOW`, and `IEEE_INEXACT`, whereas
+`denormal` is a non-standard GFortran-compatible extension that halts on the
+hardware denormal (subnormal) operand exception. The value `none` may appear
anywhere in the list; it disables halting and clears any preceding exceptions in
the list, while exceptions following it are still effective (e.g.,
-``invalid,none,zero`` enables halting on ``zero`` only). In the absence of this
+`invalid,none,zero` enables halting on `zero` only). In the absence of this
option, or when an empty list is passed to it, the program runs with traps
-disabled (equivalent to passing ``none``). Multiple occurrences of this option
+disabled (equivalent to passing `none`). Multiple occurrences of this option
are allowed, in which case only the last one takes effect.
-Run-time halting relies on glibc's ``feenableexcept`` (exposed as
-``IEEE_SUPPORT_HALTING``). The compile-time warning is a conservative
+Run-time halting relies on glibc's `feenableexcept` (exposed as
+`IEEE_SUPPORT_HALTING`). The compile-time warning is a conservative
approximation from the target triple; the runtime is the definitive authority on
which exceptions can be trapped.
The table below summarizes the halting behavior for different system
-configurations. The C standard library is ``glibc`` (in practice Linux) or
-``non-glibc``; "Standard Exception" covers ``invalid``, ``zero``, ``overflow``,
-``underflow``, and ``inexact``. In the Standard Exception and Denormal columns,
+configurations. The C standard library is `glibc` (in practice Linux) or
+`non-glibc`; "Standard Exception" covers `invalid`, `zero`, `overflow`,
+`underflow`, and `inexact`. In the Standard Exception and Denormal columns,
each cell names the compiler action followed by the run-time action:
-``compiler accepts`` = the compiler forwards the request without a warning,
-``compiler warns`` = the compiler emits a warning, ``runtime halts`` = the
-exception is trapped at run time, and ``runtime ignores`` = the request is
+`compiler accepts` = the compiler forwards the request without a warning,
+`compiler warns` = the compiler emits a warning, `runtime halts` = the
+exception is trapped at run time, and `runtime ignores` = the request is
silently ignored at run time.
-+--------------+--------------------+--------------------+-------------------+
-| Architecture | C Standard Library | Standard Exception | Denormal |
-+==============+====================+====================+===================+
-| x86 | glibc | compiler accepts, | compiler accepts, |
-| | | runtime halts | runtime halts |
-+--------------+--------------------+--------------------+-------------------+
-| non-x86 | glibc | compiler accepts, | compiler warns, |
-| | | runtime halts | runtime ignores |
-+--------------+--------------------+--------------------+-------------------+
-| x86 | non-glibc | compiler accepts, | compiler accepts, |
-| | | runtime ignores | runtime ignores |
-+--------------+--------------------+--------------------+-------------------+
-| non-x86 | non-glibc | compiler warns, | compiler warns, |
-| | | runtime ignores | runtime ignores |
-+--------------+--------------------+--------------------+-------------------+
+| Architecture | C Standard Library | Standard Exception | Denormal |
+|--------------|--------------------|------------------------------------------|---------------------------------------|
+| x86 | glibc | `compiler accepts`, `runtime halts` | `compiler accepts`, `runtime halts` |
+| non-x86 | glibc | `compiler accepts`, `runtime halts` | `compiler warns`, `runtime ignores` |
+| x86 | non-glibc | `compiler accepts`, `runtime ignores` | `compiler accepts`, `runtime ignores` |
+| non-x86 | non-glibc | `compiler warns`, `runtime ignores` | `compiler warns`, `runtime ignores` |
Notes:
* On non-x86 targets the standard exceptions halt only where the target's glibc
- ``feenableexcept`` supports them; the runtime probes each at start-up (via
- ``IEEE_SUPPORT_HALTING``) and enables only those it can.
-* ``denormal`` is honored only on x86_64; on 32-bit x86 it is silently ignored
+ `feenableexcept` supports them; the runtime probes each at start-up (via
+ `IEEE_SUPPORT_HALTING`) and enables only those it can.
+* `denormal` is honored only on x86_64; on 32-bit x86 it is silently ignored
(no warning).}]>;
defm init_global_zero : BoolOptionWithoutMarshalling<"f", "init-global-zero",
diff --git a/flang/docs/CMakeLists.txt b/flang/docs/CMakeLists.txt
index 89fd219ef88cf..dbb289c194dff 100644
--- a/flang/docs/CMakeLists.txt
+++ b/flang/docs/CMakeLists.txt
@@ -79,7 +79,7 @@ if (LLVM_ENABLE_DOXYGEN)
endif()
endif()
-function (gen_rst_file_from_td output_file td_option source target)
+function (gen_sphinx_file_from_td output_file td_option source target)
if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
message(FATAL_ERROR "Cannot find source file: ${source} in ${CMAKE_CURRENT_SOURCE_DIR}")
endif()
@@ -98,16 +98,16 @@ if (LLVM_ENABLE_SPHINX)
# CLANG_TABLEGEN_EXE variable needs to be set for clang_tablegen to run without error
find_program(CLANG_TABLEGEN_EXE "clang-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH)
- # Generate the RST file from TableGen (for both HTML and MAN builds)
- gen_rst_file_from_td(FlangCommandLineReference.rst -gen-opt-docs FlangOptionsDocs.td "gen-FlangCommandLineReference.rst")
- gen_rst_file_from_td(FlangCommandLineOptions.rst -gen-opt-docs FlangOptionsMan.td "gen-FlangCommandLineOptions.rst")
- # clang_tablegen() (called from gen_rst_file_from_td()) does not create the
+ # Generate the Sphinx file from TableGen (for both HTML and MAN builds)
+ gen_sphinx_file_from_td(FlangCommandLineReference.md -gen-opt-docs FlangOptionsDocs.td "gen-FlangCommandLineReference.md")
+ gen_sphinx_file_from_td(FlangCommandLineOptions.md -gen-opt-docs FlangOptionsMan.td "gen-FlangCommandLineOptions.md")
+ # clang_tablegen() (called from gen_sphinx_file_from_td()) does not create the
# output directory automatically, so we have to create it explicitly.
add_custom_target(create-flang-rst-output-dir
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/Source
)
- add_dependencies("gen-FlangCommandLineReference.rst" create-flang-rst-output-dir)
- add_dependencies("gen-FlangCommandLineOptions.rst" create-flang-rst-output-dir)
+ add_dependencies("gen-FlangCommandLineReference.md" create-flang-rst-output-dir)
+ add_dependencies("gen-FlangCommandLineOptions.md" create-flang-rst-output-dir)
if (${SPHINX_OUTPUT_HTML})
message(STATUS "Using index.md for html build")
@@ -119,7 +119,7 @@ if (LLVM_ENABLE_SPHINX)
"${CMAKE_CURRENT_SOURCE_DIR}"
"${FLANG_DOCS_HTML_DIR}"
PRESERVE_DOCS
- FlangCommandLineReference.rst
+ FlangCommandLineReference.md
FIRLangRef.md
IGNORE_MISSING_FILES
CommandGuide/index.md)
@@ -127,10 +127,10 @@ if (LLVM_ENABLE_SPHINX)
COMMAND "${CMAKE_COMMAND}" -E remove
"${FLANG_DOCS_HTML_DIR}/CommandGuide/index.md"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
- "${CMAKE_CURRENT_BINARY_DIR}/Source/FlangCommandLineReference.rst"
- "${FLANG_DOCS_HTML_DIR}/FlangCommandLineReference.rst")
+ "${CMAKE_CURRENT_BINARY_DIR}/Source/FlangCommandLineReference.md"
+ "${FLANG_DOCS_HTML_DIR}/FlangCommandLineReference.md")
add_dependencies(copy-flang-src-docs-html
- flang-doc gen-FlangCommandLineReference.rst)
+ flang-doc gen-FlangCommandLineReference.md)
# ${CMAKE_CURRENT_BINARY_DIR}/Dialect/FIRLangRef.md is generated by
# mlir-tblgen. The script executed in the command below adds some text to
@@ -156,7 +156,7 @@ if (LLVM_ENABLE_SPHINX)
# Create minimal Source dir with ONLY the files needed for man build:
# - conf.py (Sphinx config)
# - index.md (top-level man page)
- # - FlangCommandLineOptions.rst (generated reference)
+ # - FlangCommandLineOptions.md (generated reference)
add_custom_target(copy-flang-src-docs-man
COMMAND "${CMAKE_COMMAND}" -E make_directory
"${FLANG_DOCS_MAN_DIR}"
@@ -164,12 +164,12 @@ if (LLVM_ENABLE_SPHINX)
"${CMAKE_CURRENT_SOURCE_DIR}/conf.py"
"${FLANG_DOCS_MAN_DIR}/conf.py"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
- "${CMAKE_CURRENT_BINARY_DIR}/Source/FlangCommandLineOptions.rst"
- "${FLANG_DOCS_MAN_DIR}/FlangCommandLineOptions.rst"
+ "${CMAKE_CURRENT_BINARY_DIR}/Source/FlangCommandLineOptions.md"
+ "${FLANG_DOCS_MAN_DIR}/FlangCommandLineOptions.md"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/CommandGuide/index.md"
"${FLANG_DOCS_MAN_DIR}/index.md"
- DEPENDS flang-doc gen-FlangCommandLineOptions.rst)
+ DEPENDS flang-doc gen-FlangCommandLineOptions.md)
add_sphinx_target(man flang SOURCE_DIR "${FLANG_DOCS_MAN_DIR}")
add_dependencies(docs-flang-man copy-flang-src-docs-man)
diff --git a/flang/docs/FlangOptionsDocs.td b/flang/docs/FlangOptionsDocs.td
index f2847f07afdf3..2d8d849e6159a 100644
--- a/flang/docs/FlangOptionsDocs.td
+++ b/flang/docs/FlangOptionsDocs.td
@@ -7,20 +7,19 @@
//===----------------------------------------------------------------------===//
def GlobalDocumentation {
- code Intro =[{..
- -------------------------------------------------------------------
- NOTE: This file is automatically generated by running clang-tblgen
- -gen-opt-docs. Do not edit this file by hand!!
- -------------------------------------------------------------------
+ code Intro =[{%
+% -------------------------------------------------------------------
+% NOTE: This file is automatically generated by running clang-tblgen
+% -gen-opt-docs. Do not edit this file by hand!!
+% -------------------------------------------------------------------
-=====================================
-Flang command line argument reference
-=====================================
-.. contents::
- :local:
+# Flang command line argument reference
-Introduction
-============
+```{contents}
+:local:
+```
+
+## Introduction
}];
diff --git a/flang/docs/FlangOptionsMan.td b/flang/docs/FlangOptionsMan.td
index 86cde115eb6f5..954cfd3d90701 100644
--- a/flang/docs/FlangOptionsMan.td
+++ b/flang/docs/FlangOptionsMan.td
@@ -7,11 +7,13 @@
//===----------------------------------------------------------------------===//
def GlobalDocumentation {
- code Intro =[{..
- -------------------------------------------------------------------
- NOTE: This file is automatically generated by running clang-tblgen
- -gen-opt-docs. Do not edit this file by hand!!
- -------------------------------------------------------------------
+ code Intro =[{%
+% -------------------------------------------------------------------
+% NOTE: This file is automatically generated by running clang-tblgen
+% -gen-opt-docs. Do not edit this file by hand!!
+% -------------------------------------------------------------------
+
+# Flang command line options
}];
string Program = "Flang";
>From a5ff86b73054911eed2c3933b36923131e0d052b Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 8 Sep 2026 21:30:00 +0000
Subject: [PATCH 3/3] colon fence {program}
---
clang/utils/TableGen/ClangOptionDocEmitter.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index 74ddb6b276671..7924d5e5ca1c8 100644
--- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -351,7 +351,7 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
std::string Program = DocInfo->getValueAsString("Program").lower();
if (SphinxWorkaroundSuffix)
- OS << "```{program} " << Program << SphinxWorkaroundSuffix << "\n```\n\n";
+ OS << ":::{program} " << Program << SphinxWorkaroundSuffix << "\n:::\n\n";
// Emit the names of the option.
OS << ":::{option} ";
@@ -424,7 +424,7 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
OS << Description << "\n\n";
if (SphinxWorkaroundSuffix)
- OS << "```{program} " << Program << "\n```\n\n";
+ OS << ":::{program} " << Program << "\n:::\n\n";
}
void emitDocumentation(int Depth, const Documentation &Doc,
@@ -464,8 +464,8 @@ void clang::EmitClangOptDocs(const RecordKeeper &Records, raw_ostream &OS) {
return;
}
OS << DocInfo->getValueAsString("Intro") << "\n";
- OS << "```{program} " << DocInfo->getValueAsString("Program").lower()
- << "\n```\n\n";
+ OS << ":::{program} " << DocInfo->getValueAsString("Program").lower()
+ << "\n:::\n\n";
emitDocumentation(0, extractDocumentation(Records, DocInfo), DocInfo, OS);
}
More information about the cfe-commits
mailing list