[llvm-branch-commits] [clang] [llvm] [docs] Enable absolute self-documentation link checks (PR #222508)

Reid Kleckner via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Sep 14 21:52:36 PDT 2026


https://github.com/rnk updated https://github.com/llvm/llvm-project/pull/222508

>From aca8ce1aa1cf1952ae6dbeebeba4541d4085bd99 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Fri, 11 Sep 2026 22:10:33 +0000
Subject: [PATCH 1/4] [docs] Check absolute cross-project documentation links

Extend the absolute documentation link check to recognize documents from
configured intersphinx inventories. Diagnose absolute links to those documents
so authors use validated, project-qualified intersphinx roles instead.

Part of #214861
---
 utils/docs/llvm_sphinx/__init__.py            |  21 ++-
 utils/docs/llvm_sphinx/ext/absolute_links.py  | 148 ++++++++++++++++--
 .../ext/absolute_links_test/conf.py           |   1 +
 .../ext/absolute_links_test/external/conf.py  |   4 +
 .../ext/absolute_links_test/external/index.md |   5 +
 .../absolute_links_test/external/target.md    |   5 +
 .../ext/absolute_links_test/markdown.md       |   7 +-
 .../ext/absolute_links_test/rest.rst          |   2 +-
 8 files changed, 173 insertions(+), 20 deletions(-)
 create mode 100644 utils/docs/llvm_sphinx/ext/absolute_links_test/external/conf.py
 create mode 100644 utils/docs/llvm_sphinx/ext/absolute_links_test/external/index.md
 create mode 100644 utils/docs/llvm_sphinx/ext/absolute_links_test/external/target.md

diff --git a/utils/docs/llvm_sphinx/__init__.py b/utils/docs/llvm_sphinx/__init__.py
index 2693218931b43..7684cf31e1709 100644
--- a/utils/docs/llvm_sphinx/__init__.py
+++ b/utils/docs/llvm_sphinx/__init__.py
@@ -19,13 +19,27 @@
 
 import sys
 from pathlib import Path
-from typing import Any, Dict, Iterable, Optional
+from typing import Any, Dict, Iterable, Optional, Tuple
 from enum import Enum, auto
 from sphinx.util.tags import Tags
 from llvm_sphinx.help import venv_help
 
 _SHARED_STATIC_DIR = Path(__file__).parent / "_static"
 
+_LLVM_PROJECT_DOCS = {
+    "llvm": "https://llvm.org/docs/",
+    "clang": "https://clang.llvm.org/docs/",
+    "clang-tools-extra": "https://clang.llvm.org/extra/",
+    "mlir": "https://mlir.llvm.org/docs/",
+    "libc": "https://libc.llvm.org/",
+    "libcxx": "https://libcxx.llvm.org/",
+    "lld": "https://lld.llvm.org/",
+    "lldb": "https://lldb.llvm.org/",
+    "openmp": "https://openmp.llvm.org/",
+    "flang": "https://flang.llvm.org/docs/",
+    "polly": "https://polly.llvm.org/docs/",
+}
+
 
 class Markdown(Enum):
     ALWAYS = auto()
@@ -68,6 +82,11 @@ def common_conf(tags: Tags, markdown=Markdown.ALWAYS) -> Dict[str, Any]:
     return locals()
 
 
+def get_llvm_intersphinx_mapping(*projects: str) -> Dict[str, Tuple[str, None]]:
+    """Return intersphinx mappings for published LLVM project documentation."""
+    return {project: (_LLVM_PROJECT_DOCS[project], None) for project in projects}
+
+
 def _append_unique(target, entries):
     for entry in entries:
         if entry not in target:
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links.py b/utils/docs/llvm_sphinx/ext/absolute_links.py
index 1d7cf92d13bea..1745d53161ab8 100644
--- a/utils/docs/llvm_sphinx/ext/absolute_links.py
+++ b/utils/docs/llvm_sphinx/ext/absolute_links.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-"""Check for absolute links to documents in the current Sphinx project."""
+"""Check for absolute links to Sphinx documentation."""
 
 from __future__ import annotations
 
@@ -8,14 +8,15 @@
 import sys
 import tempfile
 from pathlib import Path
-from typing import Collection, Dict, Sequence
-from urllib.parse import unquote, urlsplit
+from typing import Collection, Dict, Mapping, Sequence
+from urllib.parse import unquote, urljoin, urlsplit
 
 from llvm_sphinx.help import venv_help
 
 try:
     from docutils import nodes
     from sphinx.application import Sphinx
+    from sphinx.ext.intersphinx import InventoryAdapter
     from sphinx.util import logging
 except ImportError as err:
     print(venv_help(err), file=sys.stderr)
@@ -27,6 +28,7 @@
 
 
 def setup(app: Sphinx) -> Dict[str, object]:
+    app.setup_extension("sphinx.ext.intersphinx")
     app.add_config_value("llvm_sphinx_doc_url_prefixes", (), "env", [list, tuple])
     app.connect("doctree-read", check_absolute_doc_links)
     return {
@@ -74,10 +76,14 @@ def _docname_from_url(
         if prefix_parts is None:
             continue
         prefix_hostname, prefix_path = prefix_parts
-        if hostname != prefix_hostname or not path.startswith(prefix_path):
+        if hostname != prefix_hostname:
+            continue
+        if path.rstrip("/") == prefix_path.rstrip("/"):
+            relative_path = ""
+        elif path.startswith(prefix_path):
+            relative_path = path[len(prefix_path) :]
+        else:
             continue
-
-        relative_path = path[len(prefix_path) :]
         if not relative_path:
             docname = "index"
         elif relative_path.endswith(".html"):
@@ -92,28 +98,111 @@ def _docname_from_url(
     return None
 
 
+def _intersphinx_base_url(project: str, mapping: object) -> str | None:
+    """Return the target URL from a validated intersphinx mapping entry."""
+    if not isinstance(mapping, tuple) or len(mapping) != 2:
+        return None
+    name_or_url, target_or_inventory = mapping
+    if name_or_url == project and isinstance(target_or_inventory, tuple):
+        base_url = target_or_inventory[0]
+    else:
+        base_url = name_or_url
+    return base_url if isinstance(base_url, str) else None
+
+
+def _inventory_item_uri(item: object) -> str | None:
+    uri = getattr(item, "uri", None)
+    if uri is None and isinstance(item, tuple) and len(item) > 2:
+        uri = item[2]
+    return uri if isinstance(uri, str) else None
+
+
+def _external_target_from_url(
+    uri: str, base_url: str, inventory: Mapping[str, Mapping[str, object]]
+) -> tuple[str, str, str] | None:
+    docs = inventory.get("std:doc", {})
+    docname = _docname_from_url(uri, (base_url,), docs.keys())
+    if docname is None:
+        return None
+
+    fragment = unquote(urlsplit(uri).fragment)
+    if not fragment:
+        return docname, "doc", docname
+
+    expected_uri = urljoin(base_url, f"{docname}.html#{fragment}")
+    preferred_roles = {"std:label": "ref", "std:cmdoption": "option"}
+    for object_type, objects in inventory.items():
+        for target, item in objects.items():
+            item_uri = _inventory_item_uri(item)
+            if item_uri is None:
+                continue
+            item_url = urlsplit(urljoin(base_url, item_uri))
+            expected_url = urlsplit(expected_uri)
+            if (
+                item_url.hostname,
+                item_url.path,
+                item_url.fragment,
+            ) != (
+                expected_url.hostname,
+                expected_url.path,
+                expected_url.fragment,
+            ):
+                continue
+            role = preferred_roles.get(object_type, "any")
+            return docname, role, target
+    return None
+
+
 def check_absolute_doc_links(app: Sphinx, doctree: nodes.document) -> None:
-    """Diagnose absolute URLs that name documents in this Sphinx project."""
+    """Diagnose absolute URLs that name documents known to Sphinx."""
     prefixes = app.config.llvm_sphinx_doc_url_prefixes
     if not prefixes:
         return
 
     for node in doctree.findall(nodes.reference):
+        if node.get("inv_match"):
+            continue
         uri = node.get("refuri")
         if not uri:
             continue
         docname = _docname_from_url(uri, prefixes, app.env.found_docs)
-        if docname is None:
+        if docname is not None:
+            logger.warning(
+                "absolute URL points to document %r in this Sphinx project; "
+                "use an internal 'doc' or 'ref' role instead: %s",
+                docname,
+                uri,
+                location=node,
+                type="llvm_sphinx",
+                subtype="absolute-doc-link",
+            )
             continue
-        logger.warning(
-            "absolute URL points to document %r in this Sphinx project; "
-            "use an internal 'doc' or 'ref' role instead: %s",
-            docname,
-            uri,
-            location=node,
-            type="llvm_sphinx",
-            subtype="absolute-doc-link",
-        )
+
+        inventories = InventoryAdapter(app.env).named_inventory
+        for project, mapping in app.config.intersphinx_mapping.items():
+            base_url = _intersphinx_base_url(project, mapping)
+            if base_url is None:
+                continue
+            inventory = inventories.get(project, {})
+            external_target = _external_target_from_url(uri, base_url, inventory)
+            if external_target is None:
+                continue
+            docname, role, target = external_target
+            logger.warning(
+                "absolute URL points to document %r in the %r Sphinx project; "
+                "use the 'external+%s:%s' intersphinx role with target %r "
+                "instead: %s",
+                docname,
+                project,
+                project,
+                role,
+                target,
+                uri,
+                location=node,
+                type="llvm_sphinx",
+                subtype="absolute-doc-link",
+            )
+            break
 
 
 # -----------------------------------------------------------------------------
@@ -124,6 +213,21 @@ def _build_test_docs() -> str:
     srcdir = Path(__file__).resolve().parent / "absolute_links_test"
     with tempfile.TemporaryDirectory() as tmp:
         tmp_path = Path(tmp)
+        external_srcdir = srcdir / "external"
+        external_outdir = tmp_path / "external"
+        external_app = Sphinx(
+            srcdir=external_srcdir,
+            confdir=external_srcdir,
+            outdir=external_outdir,
+            doctreedir=tmp_path / "external-doctrees",
+            buildername="html",
+            freshenv=True,
+            warningiserror=False,
+            status=None,
+            warning=None,
+        )
+        external_app.build()
+
         warnings = io.StringIO()
         app = Sphinx(
             srcdir=srcdir,
@@ -133,6 +237,14 @@ def _build_test_docs() -> str:
             buildername="html",
             freshenv=True,
             warningiserror=False,
+            confoverrides={
+                "intersphinx_mapping": {
+                    "other": (
+                        "https://other.example.test/docs/",
+                        str(external_outdir / "objects.inv"),
+                    )
+                }
+            },
             status=None,
             warning=warnings,
         )
@@ -146,6 +258,8 @@ def run_tests() -> None:
         "https://example.test/docs/target.html#target-section",
         "https://example.test/docs/",
         "http://www.example.test/docs/target.html?view=1#target-section",
+        "https://other.example.test/docs/target.html#external-section",
+        "https://other.example.test/docs",
     )
     for url in expected_urls:
         if url not in warnings:
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links_test/conf.py b/utils/docs/llvm_sphinx/ext/absolute_links_test/conf.py
index 060ace6765816..64b2416d400dd 100644
--- a/utils/docs/llvm_sphinx/ext/absolute_links_test/conf.py
+++ b/utils/docs/llvm_sphinx/ext/absolute_links_test/conf.py
@@ -1,6 +1,7 @@
 extensions = ["llvm_sphinx.ext.absolute_links", "myst_parser"]
 master_doc = "index"
 project = "absolute links test"
+exclude_patterns = ["external"]
 source_suffix = {
     ".rst": "restructuredtext",
     ".md": "markdown",
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links_test/external/conf.py b/utils/docs/llvm_sphinx/ext/absolute_links_test/external/conf.py
new file mode 100644
index 0000000000000..b735eb1b5daf1
--- /dev/null
+++ b/utils/docs/llvm_sphinx/ext/absolute_links_test/external/conf.py
@@ -0,0 +1,4 @@
+master_doc = "index"
+project = "external absolute links test"
+source_suffix = {".md": "markdown"}
+extensions = ["myst_parser"]
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links_test/external/index.md b/utils/docs/llvm_sphinx/ext/absolute_links_test/external/index.md
new file mode 100644
index 0000000000000..9485ced74e54f
--- /dev/null
+++ b/utils/docs/llvm_sphinx/ext/absolute_links_test/external/index.md
@@ -0,0 +1,5 @@
+# External Test Project
+
+```{toctree}
+target
+```
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links_test/external/target.md b/utils/docs/llvm_sphinx/ext/absolute_links_test/external/target.md
new file mode 100644
index 0000000000000..346cb7f2756c0
--- /dev/null
+++ b/utils/docs/llvm_sphinx/ext/absolute_links_test/external/target.md
@@ -0,0 +1,5 @@
+# External Target Document
+
+(external-section)=
+
+## External Section
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links_test/markdown.md b/utils/docs/llvm_sphinx/ext/absolute_links_test/markdown.md
index 2e281ec149c9a..c64960576b460 100644
--- a/utils/docs/llvm_sphinx/ext/absolute_links_test/markdown.md
+++ b/utils/docs/llvm_sphinx/ext/absolute_links_test/markdown.md
@@ -3,8 +3,13 @@
 This [absolute link](http://www.example.test/docs/target.html?view=1#target-section)
 points into this Sphinx project.
 
+This [cross-project link](https://other.example.test/docs/target.html#external-section)
+points into a configured intersphinx project.
+Its [project root](https://other.example.test/docs) does too.
+
 These links should not warn:
 
-- [another project](https://other.example.test/docs/target.html)
+- [an intersphinx inventory link](inv:other:std:doc#target)
+- [an unconfigured project](https://unconfigured.example.test/docs/target.html)
 - [a nonexistent document](https://example.test/docs/missing.html)
 - [a non-document page](https://example.test/docs/downloads/package.tar.xz)
diff --git a/utils/docs/llvm_sphinx/ext/absolute_links_test/rest.rst b/utils/docs/llvm_sphinx/ext/absolute_links_test/rest.rst
index 89240c3a52682..7e4b2dddb2136 100644
--- a/utils/docs/llvm_sphinx/ext/absolute_links_test/rest.rst
+++ b/utils/docs/llvm_sphinx/ext/absolute_links_test/rest.rst
@@ -7,6 +7,6 @@ The `project root <https://example.test/docs/>`_ does too.
 
 These links should not warn:
 
-* `another project <https://other.example.test/docs/target.html>`_
+* `an unconfigured project <https://unconfigured.example.test/docs/target.html>`_
 * `a nonexistent document <https://example.test/docs/missing.html>`_
 * `a non-document page <https://example.test/docs/downloads/package.tar.xz>`_

>From 498ad94378ace269c00390a78adbc57c654ed9d5 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Fri, 11 Sep 2026 22:13:52 +0000
Subject: [PATCH 2/4] [docs] Use intersphinx for LLVM cross-project links

Configure the LLVM documentation with the external project inventories it
references and replace absolute cross-project documentation URLs with
validated intersphinx document and reference roles.

Part of #214861
---
 llvm/docs/AMDGPUUsage.rst           | 14 ++++++------
 llvm/docs/CMake.md                  | 11 +++++----
 llvm/docs/CodingStandards.md        |  7 +++---
 llvm/docs/CoverageMappingFormat.md  |  4 ++--
 llvm/docs/DTLTO.md                  |  2 +-
 llvm/docs/DeveloperPolicy.md        |  2 +-
 llvm/docs/ExceptionHandling.md      |  3 +--
 llvm/docs/FuzzingLLVM.rst           |  4 ++--
 llvm/docs/GettingInvolved.md        |  2 +-
 llvm/docs/GettingStarted.md         |  7 +++---
 llvm/docs/GwpAsan.rst               |  2 +-
 llvm/docs/HowToCrossCompileLLVM.md  |  2 +-
 llvm/docs/InstrProfileFormat.md     |  2 +-
 llvm/docs/LangRef.md                | 35 +++++++++++++++--------------
 llvm/docs/Lexicon.md                |  2 +-
 llvm/docs/LibFuzzer.md              | 13 +++++------
 llvm/docs/MemTagSanitizer.rst       |  9 ++++----
 llvm/docs/PointerAuth.md            |  2 +-
 llvm/docs/Remarks.md                |  2 +-
 llvm/docs/SymbolizerMarkupFormat.md |  2 +-
 llvm/docs/TestSuiteGuide.md         |  2 +-
 llvm/docs/TypeMetadata.rst          | 10 ++++-----
 llvm/docs/conf.py                   |  4 +++-
 23 files changed, 70 insertions(+), 73 deletions(-)

diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst
index efd26f04daa2e..76f237134e512 100644
--- a/llvm/docs/AMDGPUUsage.rst
+++ b/llvm/docs/AMDGPUUsage.rst
@@ -1051,8 +1051,8 @@ consumed by the AMDGPU backend during code generation.
 Target ID
 ---------
 
-AMDGPU supports target IDs. See `Clang Offload Bundler
-<https://clang.llvm.org/docs/ClangOffloadBundler.html>`_ for a general
+AMDGPU supports target IDs. See :external+clang:doc:`Clang Offload Bundler
+<ClangOffloadBundler>` for a general
 description. The AMDGPU target specific information is:
 
 **processor**
@@ -1076,8 +1076,8 @@ description. The AMDGPU target specific information is:
 Code Object V2 to V3 Target ID
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The target ID syntax for code object V2 to V3 is the same as defined in `Clang
-Offload Bundler <https://clang.llvm.org/docs/ClangOffloadBundler.html>`_ except
+The target ID syntax for code object V2 to V3 is the same as defined in
+:external+clang:doc:`Clang Offload Bundler <ClangOffloadBundler>` except
 when used in the :ref:`amdgpu-assembler-directive-amdgcn-target` assembler
 directive and the bundle entry ID. In those cases it has the following BNF
 syntax:
@@ -1099,8 +1099,8 @@ Embedding Bundled Code Objects
 ------------------------------
 
 AMDGPU supports the HIP and OpenMP languages that perform code object embedding
-as described in `Clang Offload Bundler
-<https://clang.llvm.org/docs/ClangOffloadBundler.html>`_.
+as described in :external+clang:doc:`Clang Offload Bundler
+<ClangOffloadBundler>`.
 
 .. note::
 
@@ -22147,7 +22147,7 @@ Additional Documentation
 .. [AMD-ROCm] `AMD ROCm™ Platform <https://rocmdocs.amd.com/>`__
 .. [AMD-ROCm-github] `AMD ROCm™ github <http://github.com/ROCm>`__
 .. [AMD-ROCm-Release-Notes] `AMD ROCm Release Notes <https://github.com/ROCm/ROCm>`__
-.. [CLANG-ATTR] `Attributes in Clang <https://clang.llvm.org/docs/AttributeReference.html>`__
+.. [CLANG-ATTR] :external+clang:doc:`Attributes in Clang <AttributeReference>`
 .. [DWARF] `DWARF Debugging Information Format <http://dwarfstd.org/>`__
 .. [ELF] `Executable and Linkable Format (ELF) <http://www.sco.com/developers/gabi/>`__
 .. [HRF] `Heterogeneous-race-free Memory Models <https://research.cs.wisc.edu/multifacet/papers/asplos14_hrf.pdf>`__
diff --git a/llvm/docs/CMake.md b/llvm/docs/CMake.md
index d324b2ca4932e..84a43b453259d 100644
--- a/llvm/docs/CMake.md
+++ b/llvm/docs/CMake.md
@@ -380,8 +380,8 @@ sub-projects. Nearly all of these variable names begin with `LLVM_`.
 
 **LLVM_BUILD_INSTRUMENTED_COVERAGE**:BOOL
 
-:   If enabled, [source-based code
-    coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html)
+:   If enabled, {external+clang:doc}`source-based code
+    coverage <SourceBasedCodeCoverage>`
     instrumentation is enabled while building llvm. If CMake can locate the
     code coverage scripts and the llvm-cov and llvm-profdata tools that pair
     with your compiler, the build will also generate the
@@ -609,8 +609,7 @@ sub-projects. Nearly all of these variable names begin with `LLVM_`.
 
 **LLVM_ENABLE_MODULES**:BOOL
 
-:   Compile with [Clang Header
-    Modules](https://clang.llvm.org/docs/Modules.html).
+:   Compile with {external+clang:doc}`Clang Header Modules <Modules>`.
 
 (llvm_enable_pdb)=
 
@@ -672,8 +671,8 @@ sub-projects. Nearly all of these variable names begin with `LLVM_`.
     compiler. This is the correct way to build runtimes when putting together a
     toolchain. It will build the builtins separately from the other runtimes to
     preserve correct dependency ordering. If you want to build the runtimes
-    using a system compiler, see the [libc++
-    documentation](https://libcxx.llvm.org/VendorDocumentation.html).
+    using a system compiler, see the {external+libcxx:doc}`libc++
+    documentation <VendorDocumentation>`.
 
     :::{note}
     The list should not have duplicates with `LLVM_ENABLE_PROJECTS`.
diff --git a/llvm/docs/CodingStandards.md b/llvm/docs/CodingStandards.md
index b5afe4b579443..89381d0a5e956 100644
--- a/llvm/docs/CodingStandards.md
+++ b/llvm/docs/CodingStandards.md
@@ -60,7 +60,7 @@ Each toolchain provides a good reference for what it accepts:
 
 * Clang: https://clang.llvm.org/cxx_status.html
 
-  * libc++: https://libcxx.llvm.org/Status/Cxx17.html
+  * libc++: {external+libcxx:doc}`C++17 status <Status/Cxx17>`
 
 * GCC: https://gcc.gnu.org/projects/cxx-status.html#cxx17
 
@@ -537,9 +537,8 @@ llvm::Constant *Mask[] = {
 ```
 
 This formatting scheme also makes it particularly easy to get predictable,
-consistent, and automatic formatting with tools like [Clang Format].
-
-[Clang Format]: https://clang.llvm.org/docs/ClangFormat.html
+consistent, and automatic formatting with tools like
+{external+clang:doc}`Clang Format <ClangFormat>`.
 
 ### Language and Compiler Issues
 
diff --git a/llvm/docs/CoverageMappingFormat.md b/llvm/docs/CoverageMappingFormat.md
index 02fab85fa1c81..071103597f0e2 100644
--- a/llvm/docs/CoverageMappingFormat.md
+++ b/llvm/docs/CoverageMappingFormat.md
@@ -10,8 +10,8 @@ analysis using LLVM's and Clang's instrumentation based profiling
 This document is aimed at those who would like to know how LLVM's code coverage
 mapping works under the hood. A prior knowledge of how Clang's profile guided
 optimization works is useful, but not required. For those interested in using
-LLVM to provide code coverage analysis for their own programs, see the [Clang
-documentation](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html).
+LLVM to provide code coverage analysis for their own programs, see the
+{external+clang:doc}`Clang documentation <SourceBasedCodeCoverage>`.
 
 We start by briefly describing LLVM's code coverage mapping format and the
 way that Clang and LLVM's code coverage tool work with this format. After
diff --git a/llvm/docs/DTLTO.md b/llvm/docs/DTLTO.md
index c498cae3b8ebf..2f61535c10e48 100644
--- a/llvm/docs/DTLTO.md
+++ b/llvm/docs/DTLTO.md
@@ -88,7 +88,7 @@ also be specified. Such options are transparently forwarded.
 The backend compilations are currently performed by invoking Clang. For further
 details, refer to:
 
-- Clang documentation: <https://clang.llvm.org/docs/ThinLTO.html>
+- Clang documentation: {external+clang:doc}`ThinLTO`
 - LLD documentation: <https://lld.llvm.org/DTLTO.html>
 
 When invoked with a distributor, LLD generates a JSON file describing the
diff --git a/llvm/docs/DeveloperPolicy.md b/llvm/docs/DeveloperPolicy.md
index d0e922cd22cd6..f6996492ce07c 100644
--- a/llvm/docs/DeveloperPolicy.md
+++ b/llvm/docs/DeveloperPolicy.md
@@ -211,7 +211,7 @@ features added. Some tips for getting your testcase approved:
   [llvm/utils/update_llc_test_checks.py](https://github.com/llvm/llvm-project/blob/main/llvm/utils/update_llc_test_checks.py)
 - Some subprojects such as `clang` and `clangd` have project specific testing
   tools, like the `clang -verify` flag
-  ([docs](https://clang.llvm.org/docs/InternalsManual.html#verifying-diagnostics))
+  ({external+clang:ref}`docs <verifying-diagnostics>`)
   and the `clangd -lit-test` flag, which are preferred over `FileCheck`.
 - Changes to libraries, such as Support, which are not directly observable
   through tool invocations, are often best tested with unit tests. Unit tests
diff --git a/llvm/docs/ExceptionHandling.md b/llvm/docs/ExceptionHandling.md
index 4b6cf835bac7f..c7af4f4f61659 100644
--- a/llvm/docs/ExceptionHandling.md
+++ b/llvm/docs/ExceptionHandling.md
@@ -791,7 +791,7 @@ items that need to be implemented.
   you have to handle `EH_RETURN` in `TargetLowering`.
 
 If you don't leverage the existing runtime (`libstdc++` and `libgcc`),
-you have to take a look at [libc++] and
+you have to take a look at {external+libcxx:doc}`libc++ <index>` and
 [libunwind]
 to see what has to be done there. For `libunwind`, you have to do the following:
 
@@ -823,4 +823,3 @@ to see what has to be done there. For `libunwind`, you have to do the following:
 [CFI directives]: https://sourceware.org/binutils/docs/as/CFI-directives.html
 [libgcc]: https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html
 [libunwind]: https://clang.llvm.org/docs/Toolchain.html#unwind-library
-[libc++]: https://libcxx.llvm.org/
diff --git a/llvm/docs/FuzzingLLVM.rst b/llvm/docs/FuzzingLLVM.rst
index f1df0c979c9fe..7f88edb5a739e 100644
--- a/llvm/docs/FuzzingLLVM.rst
+++ b/llvm/docs/FuzzingLLVM.rst
@@ -41,11 +41,11 @@ level:
 clang-format-fuzzer
 -------------------
 
-A |generic fuzzer| that runs clang-format_ on C++ text fragments. Some of the
+A |generic fuzzer| that runs :external+clang:doc:`clang-format <ClangFormat>`
+on C++ text fragments. Some of the
 bugs this fuzzer has reported are `on bugzilla`__
 and `on OSS Fuzz's tracker`__.
 
-.. _clang-format: https://clang.llvm.org/docs/ClangFormat.html
 __ https://llvm.org/pr23052
 __ https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj-llvm+clang-format-fuzzer
 
diff --git a/llvm/docs/GettingInvolved.md b/llvm/docs/GettingInvolved.md
index 465115fd9a5e5..151f114d17b25 100644
--- a/llvm/docs/GettingInvolved.md
+++ b/llvm/docs/GettingInvolved.md
@@ -183,7 +183,7 @@ what to add to your calendar invite.
      -
      -
    * - OpenMP
-     - Multiple meeting series, [documented here](https://openmp.llvm.org/docs/SupportAndFAQ.html)
+     - Multiple meeting series, {external+openmp:doc}`documented here <SupportAndFAQ>`
      -
      -
    * - LLVM Alias Analysis
diff --git a/llvm/docs/GettingStarted.md b/llvm/docs/GettingStarted.md
index 1e78ca5203be1..1e269de06fa92 100644
--- a/llvm/docs/GettingStarted.md
+++ b/llvm/docs/GettingStarted.md
@@ -16,7 +16,7 @@ component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode
 -- and from there into object files, using LLVM.
 
 Other components include:
-the [libc++ C++ standard library](https://libcxx.llvm.org),
+the {external+libcxx:doc}`libc++ C++ standard library <index>`,
 the [LLD linker](https://lld.llvm.org), and more.
 
 (sources)=
@@ -631,11 +631,10 @@ with the latest Xcode:
 Note: There are some additional flags that need to be passed when building for
 iOS due to limitations in the iOS SDK.
 
-Check {doc}`HowToCrossCompileLLVM` and [Clang docs on how to cross-compile in general]
+Check {doc}`HowToCrossCompileLLVM` and
+{external+clang:doc}`Clang docs on how to cross-compile in general <CrossCompilation>`
 for more information about cross-compiling.
 
-[Clang docs on how to cross-compile in general]: https://clang.llvm.org/docs/CrossCompilation.html
-
 ### The Location of LLVM Object Files
 
 The LLVM build system is capable of sharing a single LLVM source tree among
diff --git a/llvm/docs/GwpAsan.rst b/llvm/docs/GwpAsan.rst
index 004f42aa60b78..4cf1495403a4d 100644
--- a/llvm/docs/GwpAsan.rst
+++ b/llvm/docs/GwpAsan.rst
@@ -24,7 +24,7 @@ depending on the average size of your allocations.
 GWP-ASan vs. ASan
 =================
 
-Unlike `AddressSanitizer <https://clang.llvm.org/docs/AddressSanitizer.html>`_,
+Unlike :external+clang:doc:`AddressSanitizer`,
 GWP-ASan does not induce a significant performance overhead. ASan often requires
 the use of dedicated canaries to be viable in production environments, and as
 such is often impractical. Moreover, ASan's runtime is not developed with
diff --git a/llvm/docs/HowToCrossCompileLLVM.md b/llvm/docs/HowToCrossCompileLLVM.md
index 5dcaa333bf8d0..be2ddc1301e02 100644
--- a/llvm/docs/HowToCrossCompileLLVM.md
+++ b/llvm/docs/HowToCrossCompileLLVM.md
@@ -6,7 +6,7 @@ This document contains information about building LLVM and
 Clang on a host machine, targeting another platform.
 
 For more information on how to use Clang as a cross-compiler,
-please check <https://clang.llvm.org/docs/CrossCompilation.html>.
+please check {external+clang:doc}`Cross-compilation using Clang <CrossCompilation>`.
 
 This document describes cross-building a compiler in a single stage, using an
 existing `clang` install as the host compiler.
diff --git a/llvm/docs/InstrProfileFormat.md b/llvm/docs/InstrProfileFormat.md
index 6672d7ec10138..0780f352cd12f 100644
--- a/llvm/docs/InstrProfileFormat.md
+++ b/llvm/docs/InstrProfileFormat.md
@@ -12,7 +12,7 @@ of interpretation across use cases, the documentation is based on IRPGO.
 
 :::{note}
 Frontend-generated profiles are used together with coverage mapping for
-[source-based code coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html). The {doc}`coverage mapping format <CoverageMappingFormat>` is different from
+{external+clang:doc}`source-based code coverage <SourceBasedCodeCoverage>`. The {doc}`coverage mapping format <CoverageMappingFormat>` is different from
 profile format.
 :::
 
diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 9dd68a4b5b2b2..5f3ee9cd21d3b 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -2696,7 +2696,7 @@ fn -> other_fn -> other_fn ; fn is norecurse
 
 `safestack`
 :   This attribute indicates that
-    [SafeStack](https://clang.llvm.org/docs/SafeStack.html)
+    {external+clang:doc}`SafeStack`
     protection is enabled for this function.
 
     If a function that has a `safestack` attribute is inlined into a
@@ -5610,7 +5610,7 @@ This is currently only supported for ELF binary formats.
 
 `no_cfi @func`
 
-With [Control-Flow Integrity (CFI)](https://clang.llvm.org/docs/ControlFlowIntegrity.html), a '`no_cfi`'
+With {external+clang:doc}`Control-Flow Integrity (CFI) <ControlFlowIntegrity>`, a '`no_cfi`'
 constant represents a function reference that does not get replaced with a
 reference to the CFI jump table in the `LowerTypeTests` pass. These constants
 may be useful in low-level programs, such as operating system kernels, which
@@ -9736,7 +9736,7 @@ different TBAA hierarchies (e.g., when mixing C and C++).
 
 ## ThinLTO Summary
 
-Compiling with [ThinLTO](https://clang.llvm.org/docs/ThinLTO.html)
+Compiling with {external+clang:doc}`ThinLTO`
 causes the building of a compact summary of the module that is emitted into
 the bitcode. The summary is emitted into the LLVM assembly and identified
 in syntax by a caret ('`^`').
@@ -9971,7 +9971,7 @@ value (e.g., `^1`).
 #### TypeIdInfo
 
 The optional `TypeIdInfo` field, used for
-[Control Flow Integrity](https://clang.llvm.org/docs/ControlFlowIntegrity.html),
+{external+clang:doc}`Control Flow Integrity <ControlFlowIntegrity>`,
 looks like:
 
 ```text
@@ -10042,7 +10042,7 @@ Where each ConstVCall has the format described for
 
 Each type id summary entry corresponds to a type identifier resolution
 which is generated during the LTO link portion of the compile when building
-with [Control Flow Integrity](https://clang.llvm.org/docs/ControlFlowIntegrity.html),
+with {external+clang:doc}`Control Flow Integrity <ControlFlowIntegrity>`,
 so these are only present in a combined summary index.
 
 Example:
@@ -27594,7 +27594,8 @@ The optimizer is allowed to inline the memory assignment when it's profitable to
 
 LLVM provides intrinsics that lower to Objective-C ARC runtime entry points.
 LLVM is aware of the semantics of these functions, and optimizes based on that
-knowledge. You can read more about the details of Objective-C ARC [here](https://clang.llvm.org/docs/AutomaticReferenceCounting.html).
+knowledge. You can read more about the details of Objective-C ARC
+{external+clang:doc}`here <AutomaticReferenceCounting>`.
 
 #### '`llvm.objc.autorelease`' Intrinsic
 
@@ -27605,7 +27606,7 @@ declare ptr @llvm.objc.autorelease(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_autorelease](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-autorelease).
+Lowers to a call to {external+clang:ref}`objc_autorelease <arc.runtime.objc_autorelease>`.
 
 #### '`llvm.objc.autoreleasePoolPop`' Intrinsic
 
@@ -27638,7 +27639,7 @@ declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_autoreleaseReturnValue](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-autoreleasereturnvalue).
+Lowers to a call to {external+clang:ref}`objc_autoreleaseReturnValue <arc.runtime.objc_autoreleasereturnvalue>`.
 
 #### '`llvm.objc.copyWeak`' Intrinsic
 
@@ -27671,7 +27672,7 @@ declare ptr @llvm.objc.initWeak(ptr, ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_initWeak](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-initweak).
+Lowers to a call to {external+clang:ref}`objc_initWeak <arc.runtime.objc_initweak>`.
 
 #### '`llvm.objc.loadWeak`' Intrinsic
 
@@ -27682,7 +27683,7 @@ declare ptr @llvm.objc.loadWeak(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_loadWeak](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-loadweak).
+Lowers to a call to {external+clang:ref}`objc_loadWeak <arc.runtime.objc_loadweak>`.
 
 #### '`llvm.objc.loadWeakRetained`' Intrinsic
 
@@ -27693,7 +27694,7 @@ declare ptr @llvm.objc.loadWeakRetained(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_loadWeakRetained](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-loadweakretained).
+Lowers to a call to {external+clang:ref}`objc_loadWeakRetained <arc.runtime.objc_loadweakretained>`.
 
 #### '`llvm.objc.moveWeak`' Intrinsic
 
@@ -27726,7 +27727,7 @@ declare ptr @llvm.objc.retain(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_retain](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-retain).
+Lowers to a call to {external+clang:ref}`objc_retain <arc.runtime.objc_retain>`.
 
 #### '`llvm.objc.retainAutorelease`' Intrinsic
 
@@ -27737,7 +27738,7 @@ declare ptr @llvm.objc.retainAutorelease(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_retainAutorelease](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-retainautorelease).
+Lowers to a call to {external+clang:ref}`objc_retainAutorelease <arc.runtime.objc_retainautorelease>`.
 
 #### '`llvm.objc.retainAutoreleaseReturnValue`' Intrinsic
 
@@ -27748,7 +27749,7 @@ declare ptr @llvm.objc.retainAutoreleaseReturnValue(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_retainAutoreleaseReturnValue](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-retainautoreleasereturnvalue).
+Lowers to a call to {external+clang:ref}`objc_retainAutoreleaseReturnValue <arc.runtime.objc_retainautoreleasereturnvalue>`.
 
 #### '`llvm.objc.retainAutoreleasedReturnValue`' Intrinsic
 
@@ -27759,7 +27760,7 @@ declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_retainAutoreleasedReturnValue](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-retainautoreleasedreturnvalue).
+Lowers to a call to {external+clang:ref}`objc_retainAutoreleasedReturnValue <arc.runtime.objc_retainautoreleasedreturnvalue>`.
 
 #### '`llvm.objc.retainBlock`' Intrinsic
 
@@ -27770,7 +27771,7 @@ declare ptr @llvm.objc.retainBlock(ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_retainBlock](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-retainblock).
+Lowers to a call to {external+clang:ref}`objc_retainBlock <arc.runtime.objc_retainblock>`.
 
 #### '`llvm.objc.storeStrong`' Intrinsic
 
@@ -27792,7 +27793,7 @@ declare ptr @llvm.objc.storeWeak(ptr, ptr)
 
 ##### Lowering:
 
-Lowers to a call to [objc_storeWeak](https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-storeweak).
+Lowers to a call to {external+clang:ref}`objc_storeWeak <arc.runtime.objc_storeweak>`.
 
 ### Preserving Debug Information Intrinsics
 
diff --git a/llvm/docs/Lexicon.md b/llvm/docs/Lexicon.md
index fc0e29c63a40a..7702d9b693fe5 100644
--- a/llvm/docs/Lexicon.md
+++ b/llvm/docs/Lexicon.md
@@ -97,7 +97,7 @@ This document is a work in progress!
 
 **ento**
 :   This namespace houses the
-    [Clang Static Analyzer](https://clang.llvm.org/docs/ClangStaticAnalyzer.html).
+    {external+clang:doc}`Clang Static Analyzer <ClangStaticAnalyzer>`.
     It is an abbreviation of [entomology](https://en.wikipedia.org/wiki/Entomology).
 
       *"Entomology is the scientific study of insects."*
diff --git a/llvm/docs/LibFuzzer.md b/llvm/docs/LibFuzzer.md
index cb2575e4b5514..9176b2c7b2583 100644
--- a/llvm/docs/LibFuzzer.md
+++ b/llvm/docs/LibFuzzer.md
@@ -609,7 +609,7 @@ you will want to know whether the function or the corpus can be improved further
 One easy to use metric is, of course, code coverage.
 
 We recommend to use
-[Clang Coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html),
+{external+clang:doc}`Clang Coverage <SourceBasedCodeCoverage>`,
 to visualize and study your code coverage
 ([example](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md#visualizing-coverage)).
 
@@ -846,19 +846,18 @@ this may be fixed in future.
 [pcre2]: http://www.pcre.org/
 [AFL]: http://lcamtuf.coredump.cx/afl/
 [Radamsa]: https://github.com/aoh/radamsa
-[SanitizerCoverage]: https://clang.llvm.org/docs/SanitizerCoverage.html
+[SanitizerCoverage]: inv:clang:std:doc#SanitizerCoverage
 [SanitizerCoverageTraceDataFlow]: https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow
-[AddressSanitizer]: https://clang.llvm.org/docs/AddressSanitizer.html
-[LeakSanitizer]: https://clang.llvm.org/docs/LeakSanitizer.html
+[AddressSanitizer]: inv:clang:std:doc#AddressSanitizer
+[LeakSanitizer]: inv:clang:std:doc#LeakSanitizer
 [Heartbleed]: http://en.wikipedia.org/wiki/Heartbleed
 [FuzzerInterface.h]: https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/fuzzer/FuzzerInterface.h
 [3.7.0]: https://llvm.org/releases/3.7.0/docs/LibFuzzer.html
 [building Clang from trunk]: https://clang.llvm.org/get_started.html
-[MemorySanitizer]: https://clang.llvm.org/docs/MemorySanitizer.html
-[UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
+[MemorySanitizer]: inv:clang:std:doc#MemorySanitizer
+[UndefinedBehaviorSanitizer]: inv:clang:std:doc#UndefinedBehaviorSanitizer
 [coverage counters]: https://clang.llvm.org/docs/SanitizerCoverage.html#coverage-counters
 [value profile]: #value-profile
 [caller-callee pairs]: https://clang.llvm.org/docs/SanitizerCoverage.html#caller-callee-coverage
 [BoringSSL]: https://boringssl.googlesource.com/boringssl/
 [Centipede]: https://github.com/google/centipede
-
diff --git a/llvm/docs/MemTagSanitizer.rst b/llvm/docs/MemTagSanitizer.rst
index 8fba126cd4c37..849a44e1e59e3 100644
--- a/llvm/docs/MemTagSanitizer.rst
+++ b/llvm/docs/MemTagSanitizer.rst
@@ -12,7 +12,9 @@ running MemTagSanitizer does not exist as of Oct 2019.
 
 MemTagSanitizer is a fast memory error detector and **a code hardening
 tool** based on the Armv8.5-A `Memory Tagging Extension`_. It
-detects a similar class of errors as `AddressSanitizer`_ or `HardwareAssistedAddressSanitizer`_, but with
+detects a similar class of errors as :external+clang:doc:`AddressSanitizer` or
+:external+clang:doc:`HardwareAssistedAddressSanitizer
+<HardwareAssistedAddressSanitizerDesign>`, but with
 **much** lower overhead.
 
 MemTagSanitizer overhead is expected to be in low single digits, both
@@ -39,7 +41,8 @@ adds the memory tagging feature, without changing anything else.
 Implementation
 ==============
 
-See `HardwareAssistedAddressSanitizer`_ for a general overview of a
+See :external+clang:doc:`HardwareAssistedAddressSanitizer
+<HardwareAssistedAddressSanitizerDesign>` for a general overview of a
 tag-based approach to memory safety.  MemTagSanitizer follows a
 similar implementation strategy, but with the tag storage (shadow)
 provided by the hardware.
@@ -97,5 +100,3 @@ More information
 * `Memory Tagging Whitepaper <https://arxiv.org/pdf/1802.09517.pdf>`_
 
 .. _Memory Tagging Extension: https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-a-profile-architecture-2018-developments-armv85a
-.. _AddressSanitizer: https://clang.llvm.org/docs/AddressSanitizer.html
-.. _HardwareAssistedAddressSanitizer: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
diff --git a/llvm/docs/PointerAuth.md b/llvm/docs/PointerAuth.md
index 62e0d3a2353d9..78cd4eba733e7 100644
--- a/llvm/docs/PointerAuth.md
+++ b/llvm/docs/PointerAuth.md
@@ -11,7 +11,7 @@ signature checked.  This prevents pointer values of unknown origin from being
 used to replace the signed pointer value.
 
 For more details, see the clang documentation page for
-[Pointer Authentication](https://clang.llvm.org/docs/PointerAuthentication.html).
+{external+clang:doc}`Pointer Authentication <PointerAuthentication>`.
 
 At the IR level, it is represented using:
 
diff --git a/llvm/docs/Remarks.md b/llvm/docs/Remarks.md
index 6f57e0a689e8d..cf454544d456b 100644
--- a/llvm/docs/Remarks.md
+++ b/llvm/docs/Remarks.md
@@ -51,7 +51,7 @@ LLVM: through remark diagnostics, or through serialized remarks.
 See also the clang flags
 [-Rpass](https://clang.llvm.org/docs/UsersManual.html#options-to-emit-optimization-reports)
 and
-[-fsave-optimization-record](http://clang.llvm.org/docs/UsersManual.html#cmdoption-f-no-save-optimization-record).
+{external+clang:option}`-fsave-optimization-record <-f[no-]save-optimization-record>`.
 
 ### Remark diagnostics
 
diff --git a/llvm/docs/SymbolizerMarkupFormat.md b/llvm/docs/SymbolizerMarkupFormat.md
index 45ff11ca58c8e..834b859c4d860 100644
--- a/llvm/docs/SymbolizerMarkupFormat.md
+++ b/llvm/docs/SymbolizerMarkupFormat.md
@@ -342,7 +342,7 @@ the external action can then be presented to the user.
   processes.
 
   An example of a type identifier is `sancov`, for dumps from LLVM
-  [SanitizerCoverage](https://clang.llvm.org/docs/SanitizerCoverage.html).
+  {external+clang:doc}`SanitizerCoverage`.
 
   Example:
 
diff --git a/llvm/docs/TestSuiteGuide.md b/llvm/docs/TestSuiteGuide.md
index f4780a7d6c855..b8d729db95c89 100644
--- a/llvm/docs/TestSuiteGuide.md
+++ b/llvm/docs/TestSuiteGuide.md
@@ -240,7 +240,7 @@ benchmarks. CMake can print a list of them:
 - `TEST_SUITE_FORTRAN`
 
   Activate that Fortran tests. This is a work in progress. More information can be
-  found in the [Flang documentation](https://flang.llvm.org/docs/FortranLLVMTestSuite.html)
+  found in the {external+flang:doc}`Flang documentation <FortranLLVMTestSuite>`
 
 - `TEST_SUITE_RUN_UNDER`
 
diff --git a/llvm/docs/TypeMetadata.rst b/llvm/docs/TypeMetadata.rst
index 5fa864dc8ab21..362b6f6b4a8c9 100644
--- a/llvm/docs/TypeMetadata.rst
+++ b/llvm/docs/TypeMetadata.rst
@@ -4,7 +4,8 @@ Type Metadata
 
 Type metadata is a mechanism that allows IR modules to co-operatively build
 pointer sets corresponding to addresses within a given set of globals. LLVM's
-`control flow integrity`_ implementation uses this metadata to efficiently
+:external+clang:doc:`control flow integrity <ControlFlowIntegrity>`
+implementation uses this metadata to efficiently
 check (at each call site) that a given address corresponds to either a
 valid vtable or function pointer for a given class or function type, and its
 whole-program devirtualization pass uses the metadata to identify potential
@@ -29,8 +30,6 @@ or functions.
 An intrinsic, :ref:`llvm.type.test <type.test>`, is used to test whether a
 given pointer is associated with a type identifier.
 
-.. _control flow integrity: https://clang.llvm.org/docs/ControlFlowIntegrity.html
-
 Representing Type Information using Type Metadata
 =================================================
 
@@ -141,7 +140,8 @@ the object file, construct bit vectors that map onto that memory region,
 and generate code at each of the ``llvm.type.test`` call sites to test
 pointers against those bit vectors. Because of the layout manipulation, the
 globals' definitions must be available at LTO time. For more information,
-see the `control flow integrity design document`_.
+see the :external+clang:doc:`control flow integrity design document
+<ControlFlowIntegrityDesign>`.
 
 A type identifier that identifies functions is transformed into a jump table,
 which is a block of code consisting of one branch instruction for each
@@ -160,8 +160,6 @@ as the former will be the jump table entry if a jump table is necessary.
 The `GlobalLayoutBuilder`_ class is responsible for laying out the globals
 efficiently to minimize the sizes of the underlying bitsets.
 
-.. _control flow integrity design document: https://clang.llvm.org/docs/ControlFlowIntegrityDesign.html
-
 :Example:
 
 ::
diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py
index 0a618b2643e0a..efa2e82d52fa5 100644
--- a/llvm/docs/conf.py
+++ b/llvm/docs/conf.py
@@ -250,7 +250,9 @@ def process_rst(name):
 # man_show_urls = False
 
 # FIXME: Define intersphinx configuration.
-intersphinx_mapping = {}
+intersphinx_mapping = get_llvm_intersphinx_mapping(
+    "clang", "libcxx", "openmp", "flang"
+)
 
 # Pygment lexer are sometimes out of date (when parsing LLVM for example) or
 # wrong. Suppress the warning so the build doesn't abort.

>From acdeb639f11e9a907075aa354e102c5c710e7fb4 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Fri, 11 Sep 2026 22:26:00 +0000
Subject: [PATCH 3/4] [docs] Use intersphinx for Clang cross-project links

Configure the Clang documentation with the external project inventories it
references and replace absolute cross-project documentation URLs with
validated intersphinx document and reference roles.

Part of #214861
---
 clang/Maintainers.md                          |  2 +-
 clang/docs/AddressSanitizer.md                |  2 +-
 clang/docs/BoundsSafetyAdoptionGuide.md       |  3 +--
 clang/docs/CIR/CleanupAndEHDesign.md          |  4 ++--
 clang/docs/ClangFormatStyleOptions.md         |  2 +-
 clang/docs/ClangOffloadBundler.md             |  9 ++++----
 clang/docs/ClangTools.md                      | 11 +++++-----
 clang/docs/ClangTransformerTutorial.md        |  2 +-
 clang/docs/ControlFlowIntegrity.md            |  2 +-
 clang/docs/ControlFlowIntegrityDesign.md      |  2 +-
 clang/docs/CrossCompilation.md                |  3 +--
 clang/docs/DebuggingCoroutines.md             |  3 +--
 clang/docs/HIPSupport.md                      |  4 ++--
 clang/docs/InternalsManual.md                 | 12 +++++-----
 clang/docs/LLVMExceptionHandlingCodeGen.md    |  3 +--
 clang/docs/LanguageExtensions.md              | 22 +++++++++----------
 clang/docs/LibASTMatchersTutorial.md          |  4 ++--
 clang/docs/MemorySanitizer.md                 |  2 +-
 clang/docs/OffloadingDesign.md                |  2 +-
 clang/docs/OpenCLSupport.md                   |  2 +-
 clang/docs/PCHInternals.md                    |  7 +++---
 clang/docs/RealtimeSanitizer.md               |  2 +-
 clang/docs/ReleaseNotes.md                    |  6 ++---
 clang/docs/SafeBuffers.md                     |  4 ++--
 clang/docs/SanitizerCoverage.md               |  2 +-
 clang/docs/SourceBasedCodeCoverage.md         |  4 ++--
 clang/docs/ThinLTO.md                         | 10 ++++-----
 clang/docs/ThreadSanitizer.md                 |  2 +-
 clang/docs/Toolchain.md                       |  4 ++--
 clang/docs/TypeSanitizer.md                   |  2 +-
 clang/docs/UndefinedBehaviorSanitizer.md      |  2 +-
 clang/docs/UsersManual.md                     |  2 +-
 .../PerformanceInvestigation.md               |  3 +--
 clang/docs/analyzer/user-docs/FilingBugs.md   |  3 +--
 clang/docs/conf.py                            |  5 +++++
 clang/include/clang/Basic/AttrDocs.td         |  8 +++----
 36 files changed, 79 insertions(+), 83 deletions(-)

diff --git a/clang/Maintainers.md b/clang/Maintainers.md
index 575445e4ba32a..8be0afc795a5d 100644
--- a/clang/Maintainers.md
+++ b/clang/Maintainers.md
@@ -1,7 +1,7 @@
 # Clang Maintainers
 
 This file is a list of the
-[maintainers](https://llvm.org/docs/DeveloperPolicy.html#maintainers)
+{external+llvm:ref}`maintainers <maintainers>`
 for Clang. The list of current Clang Area Team members can be found
 [here](https://github.com/llvm/llvm-project/blob/main/clang/AreaTeamMembers.txt).
 
diff --git a/clang/docs/AddressSanitizer.md b/clang/docs/AddressSanitizer.md
index 19276261b7562..28f63249559d7 100644
--- a/clang/docs/AddressSanitizer.md
+++ b/clang/docs/AddressSanitizer.md
@@ -20,7 +20,7 @@ Typical slowdown introduced by AddressSanitizer is **2x**.
 
 ## How to build
 
-Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html) and enable
+Build LLVM/Clang with {external+llvm:doc}`CMake <CMake>` and enable
 the `compiler-rt` runtime. An example CMake configuration that will allow
 for the use/testing of AddressSanitizer:
 
diff --git a/clang/docs/BoundsSafetyAdoptionGuide.md b/clang/docs/BoundsSafetyAdoptionGuide.md
index 875a42f39281a..2a6182c6f0ad8 100644
--- a/clang/docs/BoundsSafetyAdoptionGuide.md
+++ b/clang/docs/BoundsSafetyAdoptionGuide.md
@@ -8,7 +8,7 @@ feature is not available yet. In the mean time, the preview implementation is
 available
 [here](https://github.com/swiftlang/llvm-project/tree/stable/20240723) in a
 fork of `llvm-project`. Please follow
-[Building LLVM with CMake](https://llvm.org/docs/CMake.html) to build the
+{external+llvm:doc}`Building LLVM with CMake <CMake>` to build the
 compiler.
 
 ## Feature flag
@@ -76,4 +76,3 @@ run time.
 
 Once you've done with adopting a single C file, please repeat the same process
 for each remaining C file that you want to adopt.
-
diff --git a/clang/docs/CIR/CleanupAndEHDesign.md b/clang/docs/CIR/CleanupAndEHDesign.md
index de86de0697292..395c9ae893003 100644
--- a/clang/docs/CIR/CleanupAndEHDesign.md
+++ b/clang/docs/CIR/CleanupAndEHDesign.md
@@ -1211,8 +1211,8 @@ methods for use with the exception handling ABI.
 For each supported exception handling ABI, the operations and function
 calls used will have a direct correspondence to the LLVM IR instructions
 and runtime library functions used for that ABI. The LLVM IR exception
-handling model is described in detail here: [LLVM Exception
-Handling](https://llvm.org/docs/ExceptionHandling.html).
+handling model is described in detail here:
+{external+llvm:doc}`LLVM Exception Handling <ExceptionHandling>`.
 
 A personality function attribute will be added to functions that require
 it during the ABI lowering phase.
diff --git a/clang/docs/ClangFormatStyleOptions.md b/clang/docs/ClangFormatStyleOptions.md
index 81984ff185e53..f9e7badb84964 100644
--- a/clang/docs/ClangFormatStyleOptions.md
+++ b/clang/docs/ClangFormatStyleOptions.md
@@ -149,7 +149,7 @@ the configuration (without a prefix: `Auto`).
   Possible values:
 
   - `LLVM`
-    A style complying with the [LLVM coding standards](https://llvm.org/docs/CodingStandards.html)
+    A style complying with the {external+llvm:doc}`LLVM coding standards <CodingStandards>`
   - `Google`
     A style complying with [Google's C++ style guide](https://google.github.io/styleguide/cppguide.html)
   - `Chromium`
diff --git a/clang/docs/ClangOffloadBundler.md b/clang/docs/ClangOffloadBundler.md
index d9d1d263d1e1c..5cf7636d3cfcf 100644
--- a/clang/docs/ClangOffloadBundler.md
+++ b/clang/docs/ClangOffloadBundler.md
@@ -405,11 +405,10 @@ Target-specific information is available for the following:
 
 *AMD GPU*
 
-: AMD GPU supports target ID and target features. See [User Guide for AMDGPU
-  Backend](https://llvm.org/docs/AMDGPUUsage.html) which defines the
-  [processors](https://llvm.org/docs/AMDGPUUsage.html#amdgpu-processors) and
-  [target
-  features](https://llvm.org/docs/AMDGPUUsage.html#amdgpu-target-features)
+: AMD GPU supports target ID and target features. See
+  {external+llvm:doc}`User Guide for AMDGPU Backend <AMDGPUUsage>` which defines
+  the {external+llvm:ref}`processors <amdgpu-processors>` and
+  {external+llvm:ref}`target features <amdgpu-target-features>`
   supported.
 
 Most other targets do not support target IDs.
diff --git a/clang/docs/ClangTools.md b/clang/docs/ClangTools.md
index 3d6103dcf5b01..225471637d95e 100644
--- a/clang/docs/ClangTools.md
+++ b/clang/docs/ClangTools.md
@@ -82,19 +82,19 @@ provide its own user-focused documentation.
 
 ### `Clang-Doc`
 
-[Clang-Doc](https://clang.llvm.org/extra/clang-doc.html) is a tool for
+{external+clang-tools-extra:doc}`Clang-Doc <clang-doc>` is a tool for
 generating C and C++ documentation from source code and comments.
 
 ### `Clang-Include-Fixer`
 
-[Clang-Include-Fixer](https://clang.llvm.org/extra/clang-include-fixer.html)
+{external+clang-tools-extra:doc}`Clang-Include-Fixer <clang-include-fixer>`
 is a tool to automate the addition of missing `#include` directives in a C++
 file. It adds missing namespace qualifiers to unidentified symbols when
 necessary and also removes unused headers.
 
 ### `Clang-Tidy`
 
-[Clang-Tidy](https://clang.llvm.org/extra/clang-tidy/) is a Clang-based C++
+{external+clang-tools-extra:doc}`Clang-Tidy <clang-tidy/index>` is a Clang-based C++
 linter tool. It provides an extensible framework for building compiler-based
 static analyses detecting and fixing bug-prone patterns, performance,
 portability and maintainability issues. It also has checks for modernizing code
@@ -109,13 +109,13 @@ more.
 
 ### `Modularize`
 
-[Modularize](https://clang.llvm.org/extra/modularize.html) is a standalone
+{external+clang-tools-extra:doc}`Modularize <modularize>` is a standalone
 tool that checks whether a set of headers provides the consistent definitions
 required to use modules.
 
 ### `pp-trace`
 
-[pp-trace](https://clang.llvm.org/extra/pp-trace.html) is a standalone tool
+{external+clang-tools-extra:doc}`pp-trace` is a standalone tool
 that traces preprocessor activity. It’s also used as a test of Clang’s
 `PPCallbacks` interface.
 
@@ -172,4 +172,3 @@ that traces preprocessor activity. It’s also used as a test of Clang’s
   ```c++
   sort(v.begin(), v.end(), greater<>());
   ```
-
diff --git a/clang/docs/ClangTransformerTutorial.md b/clang/docs/ClangTransformerTutorial.md
index 28a7a428c7bec..a7ddbc1c29e7c 100644
--- a/clang/docs/ClangTransformerTutorial.md
+++ b/clang/docs/ClangTransformerTutorial.md
@@ -338,7 +338,7 @@ For additional documentation on these functions, see the header file
 ## Using a RewriteRule as a clang-tidy check
 
 Transformer supports executing a rewrite rule as a
-[clang-tidy](https://clang.llvm.org/extra/clang-tidy/) check, with the class
+{external+clang-tools-extra:doc}`clang-tidy <clang-tidy/index>` check, with the class
 `clang::tidy::utils::TransformerClangTidyCheck`. It is designed to require
 minimal code in the definition. For example, given a rule
 `MyCheckAsRewriteRule`, one can define a tidy check as follows:
diff --git a/clang/docs/ControlFlowIntegrity.md b/clang/docs/ControlFlowIntegrity.md
index c25a27fd910c5..fda6f82cb0181 100644
--- a/clang/docs/ControlFlowIntegrity.md
+++ b/clang/docs/ControlFlowIntegrity.md
@@ -408,4 +408,4 @@ Martin Abadi, Mihai Budiu, Úlfar Erlingsson, Jay Ligatti.
 Caroline Tice, Tom Roeder, Peter Collingbourne, Stephen Checkoway,
 Úlfar Erlingsson, Luis Lozano, Geoff Pike.
 
-[gold plugin]: https://llvm.org/docs/GoldPlugin.html
+[gold plugin]: inv:llvm:std:doc#GoldPlugin
diff --git a/clang/docs/ControlFlowIntegrityDesign.md b/clang/docs/ControlFlowIntegrityDesign.md
index 4dad111116acb..5fe5ce0659b26 100644
--- a/clang/docs/ControlFlowIntegrityDesign.md
+++ b/clang/docs/ControlFlowIntegrityDesign.md
@@ -781,4 +781,4 @@ ability to protect against invalid casts between polymorphic types.
 [intel cet]: https://software.intel.com/en-us/blogs/2016/06/09/intel-release-new-technology-specifications-protect-rop-attacks
 [rfg]: https://xlab.tencent.com/en/2016/11/02/return-flow-guard
 [safestack]: project:SafeStack.md
-[type metadata]: https://llvm.org/docs/TypeMetadata.html
+[type metadata]: inv:llvm:std:doc#TypeMetadata
diff --git a/clang/docs/CrossCompilation.md b/clang/docs/CrossCompilation.md
index d6a0134a8fb2b..1a5a6f3650664 100644
--- a/clang/docs/CrossCompilation.md
+++ b/clang/docs/CrossCompilation.md
@@ -11,7 +11,7 @@ However, this document is *not* a "how to" and won't help you setting your
 build system or Makefiles, nor choosing the right CMake options, etc.
 Also, it does not cover all the possible options, nor does it contain
 specific examples for specific architectures. For a concrete example, the
-[instructions for cross-compiling LLVM itself](https://llvm.org/docs/HowToCrossCompileLLVM.html) may be of interest.
+{external+llvm:doc}`instructions for cross-compiling LLVM itself <HowToCrossCompileLLVM>` may be of interest.
 
 After reading this document, you should be familiar with the main issues
 related to cross-compilation, and what main compiler options Clang provides
@@ -190,4 +190,3 @@ uses hard-float), Clang will pick the `armv7l-linux-gnueabi-ld`
 The same is true if you're compiling for different environments, like
 `gnueabi` and `androideabi`, and might even link and run, but produce
 run-time errors, which are much harder to track down and fix.
-
diff --git a/clang/docs/DebuggingCoroutines.md b/clang/docs/DebuggingCoroutines.md
index 03ea897cb0475..4abae5a330de7 100644
--- a/clang/docs/DebuggingCoroutines.md
+++ b/clang/docs/DebuggingCoroutines.md
@@ -600,7 +600,7 @@ gets emitted, but none of them are really interesting regarding debugging
 information.
 
 For more details on the IR representation of coroutines and the relevant
-optimization passes, see [Coroutines in LLVM](https://llvm.org/docs/Coroutines.html).
+optimization passes, see {external+llvm:doc}`Coroutines in LLVM <Coroutines>`.
 
 Emitting debug information inside `CoroSplit` forces us to generate
 insufficient debugging information. Usually, the compiler generates debug
@@ -1264,4 +1264,3 @@ The authors of the Folly libraries wrote a blog post series on how they debug co
 Besides some topics also covered here (stack traces from the debugger), Folly's blog post series also covers
 additional topics, such as capturing async stack traces in performance profiles via eBPF filters
 and printing async stack traces on crashes.
-
diff --git a/clang/docs/HIPSupport.md b/clang/docs/HIPSupport.md
index e3cfdd4f43427..9f7f07e245d06 100644
--- a/clang/docs/HIPSupport.md
+++ b/clang/docs/HIPSupport.md
@@ -730,7 +730,7 @@ We augment the `clang` driver with the following flags:
   point to the folder where the library is installed / built under a
   `/rocprim` subfolder;
 
-The [--offload-arch](https://llvm.org/docs/AMDGPUUsage.html#amdgpu-processors)
+The {external+llvm:ref}`--offload-arch <amdgpu-processors>`
 flag can be used to specify the accelerator for which offload code is to be
 generated.
 
@@ -874,7 +874,7 @@ At the moment, C++ Standard Parallelism Offload is only available for AMD GPUs,
 when the [ROCm](https://rocm.docs.amd.com/en/latest/) stack is used, on the
 Linux operating system. Support is synthesised in the following table:
 
-| [Processor](https://llvm.org/docs/AMDGPUUsage.html#amdgpu-processors) | HMM Mode | Interposition Mode |
+| {external+llvm:ref}`Processor <amdgpu-processors>` | HMM Mode | Interposition Mode |
 | ---------------------------------------------------------------------- | -------- | ------------------ |
 | GCN GFX9 (Vega)                                                        | YES      | YES                |
 | GCN GFX10.1 (RDNA 1)                                                   | *NO*     | YES                |
diff --git a/clang/docs/InternalsManual.md b/clang/docs/InternalsManual.md
index 0fef2920fee99..a71f49837ab0d 100644
--- a/clang/docs/InternalsManual.md
+++ b/clang/docs/InternalsManual.md
@@ -13,7 +13,7 @@ and does not describe any of the clients of the libraries.
 ## LLVM Support Library
 
 The LLVM `libSupport` library provides many underlying libraries and
-[data-structures](https://llvm.org/docs/ProgrammersManual.html), including
+{external+llvm:doc}`data-structures <ProgrammersManual>`, including
 command line option processing, various containers, and a system abstraction
 layer, which is used for file system access.
 
@@ -691,7 +691,7 @@ The clang Driver and library are documented {doc}`here <DriverInternals>`.
 
 Clang supports precompiled headers ({doc}`PCH <PCHInternals>`), which uses a
 serialized representation of Clang's internal data structures, encoded with the
-[LLVM bitstream format](https://llvm.org/docs/BitCodeFormat.html).
+{external+llvm:doc}`LLVM bitstream format <BitCodeFormat>`.
 
 ## The Frontend Library
 
@@ -2908,7 +2908,7 @@ diagnostics purpose, and inject that in the `ConstraintSatisfaction`.
 
 ## The CodeGen Library
 
-CodeGen takes an {ref}`AST <AST>` as input and produces [LLVM IR code](https://llvm.org/docs/LangRef.html) from it.
+CodeGen takes an {ref}`AST <AST>` as input and produces {external+llvm:doc}`LLVM IR code <LangRef>` from it.
 
 ## How to change Clang
 
@@ -3381,7 +3381,7 @@ are similar.
      to introduce a cleanup. You shouldn't have to deal with
      exception-handling directly.
    - Testing is extremely important in IR generation. Use `clang -cc1
-     -emit-llvm` and [FileCheck](https://llvm.org/docs/CommandGuide/FileCheck.html) to verify that you're
+     -emit-llvm` and {external+llvm:doc}`FileCheck <CommandGuide/FileCheck>` to verify that you're
      generating the right IR.
 
 6. Teach template instantiation how to cope with your AST node, which requires
@@ -3434,13 +3434,13 @@ the change in behavior. There are four kinds of tests:
   provisions for tests for C++ defect reports are described in
   {ref}`"C++ Defect Report Tests" <cxx-defect-report-tests>` section.
 - AST dump tests: such tests pass printable AST output to the
-  [FileCheck](https://llvm.org/docs/CommandGuide/FileCheck.html) utility,
+  {external+llvm:doc}`FileCheck <CommandGuide/FileCheck>` utility,
   which check presence of certain patterns (or lack of thereof).
 - LLVM IR tests: in such tests, the LLVM IR output of Clang is checked, which
   is needed in cases when checking diagnostics is not sufficient (e.g. when
   testing exception handling or object lifetime). Such tests pass LLVM IR
   output to the
-  [FileCheck](https://llvm.org/docs/CommandGuide/FileCheck.html) utility,
+  {external+llvm:doc}`FileCheck <CommandGuide/FileCheck>` utility,
   which check the presence of certain IR patterns (or lack of thereof).
 
 (verifying-diagnostics)=
diff --git a/clang/docs/LLVMExceptionHandlingCodeGen.md b/clang/docs/LLVMExceptionHandlingCodeGen.md
index 4a5720698c10e..c6a1ae8fba227 100644
--- a/clang/docs/LLVMExceptionHandlingCodeGen.md
+++ b/clang/docs/LLVMExceptionHandlingCodeGen.md
@@ -9,7 +9,7 @@ flow patterns used to model normal and exceptional exits, and it outlines how
 the generated IR differs across common ABI models.
 
 For details on the LLVM IR representation of exception handling, see
-[LLVM Exception Handling](https://llvm.org/docs/ExceptionHandling.html).
+{external+llvm:doc}`LLVM Exception Handling <ExceptionHandling>`.
 
 ## Core Model
 
@@ -232,4 +232,3 @@ void f() {
 The above function names and flow are accurate as of LLVM 22.0, but this is
 subject to change as the code evolves, and this document might not be updated to
 reflect the exact functions used.
-
diff --git a/clang/docs/LanguageExtensions.md b/clang/docs/LanguageExtensions.md
index 508d0e2fa3003..3ffe8ff25bd86 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -787,16 +787,16 @@ of different sizes and signs is forbidden in binary and ternary builtins.
 | T \_\_builtin_elementwise_canonicalize(T x)    | return the platform specific canonical encoding of a floating-point number                                                                                                                                                                                                                                         | floating point types                         |
 | T \_\_builtin_elementwise_copysign(T x, T y)   | return the magnitude of x with the sign of y.                                                                                                                                                                                                                                                                      | floating point types                         |
 | T \_\_builtin_elementwise_fmod(T x, T y)       | return the floating-point remainder of (x/y) whose sign matches the sign of x.                                                                                                                                                                                                                                     | floating point types                         |
-| T \_\_builtin_elementwise_max(T x, T y)        | return x or y, whichever is larger For floating point types, follows semantics of maxNum in IEEE 754-2008. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                   | integer floating point types (deprecated)    |
-| T \_\_builtin_elementwise_min(T x, T y)        | return x or y, whichever is smaller For floating point types, follows semantics of minNum in IEEE 754-2008. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                  | integer floating point types (deprecated)    |
-| T \_\_builtin_elementwise_maxnum(T x, T y)     | return x or y, whichever is larger. Follows IEEE 754-2008 semantics (maxNum) with +0.0>-0.0. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                                 | floating point types                         |
-| T \_\_builtin_elementwise_minnum(T x, T y)     | return x or y, whichever is smaller. Follows IEEE 754-2008 semantics (minNum) with +0.0>-0.0. See [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                                | floating point types                         |
+| T \_\_builtin_elementwise_max(T x, T y)        | return x or y, whichever is larger For floating point types, follows semantics of maxNum in IEEE 754-2008. See {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                   | integer floating point types (deprecated)    |
+| T \_\_builtin_elementwise_min(T x, T y)        | return x or y, whichever is smaller For floating point types, follows semantics of minNum in IEEE 754-2008. See {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                  | integer floating point types (deprecated)    |
+| T \_\_builtin_elementwise_maxnum(T x, T y)     | return x or y, whichever is larger. Follows IEEE 754-2008 semantics (maxNum) with +0.0>-0.0. See {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                                 | floating point types                         |
+| T \_\_builtin_elementwise_minnum(T x, T y)     | return x or y, whichever is smaller. Follows IEEE 754-2008 semantics (minNum) with +0.0>-0.0. See {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                                | floating point types                         |
 | T \_\_builtin_elementwise_add_sat(T x, T y)    | return the sum of x and y, clamped to the range of representable values for the signed/unsigned integer type.                                                                                                                                                                                                      | integer types                                |
 | T \_\_builtin_elementwise_sub_sat(T x, T y)    | return the difference of x and y, clamped to the range of representable values for the signed/unsigned integer type.                                                                                                                                                                                               | integer types                                |
-| T \_\_builtin_elementwise_maximum(T x, T y)    | return x or y, whichever is larger. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                                                         | floating point types                         |
-| T \_\_builtin_elementwise_minimum(T x, T y)    | return x or y, whichever is smaller. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                                                        | floating point types                         |
-| T \_\_builtin_elementwise_maximumnum(T x, T y) | return x or y, whichever is larger. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                                                         | floating point types                         |
-| T \_\_builtin_elementwise_minimumnum(T x, T y) | return x or y, whichever is smaller. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                                                                                                                                                        | floating point types                         |
+| T \_\_builtin_elementwise_maximum(T x, T y)    | return x or y, whichever is larger. Follows IEEE 754-2019 semantics, see {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                                                         | floating point types                         |
+| T \_\_builtin_elementwise_minimum(T x, T y)    | return x or y, whichever is smaller. Follows IEEE 754-2019 semantics, see {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                                                        | floating point types                         |
+| T \_\_builtin_elementwise_maximumnum(T x, T y) | return x or y, whichever is larger. Follows IEEE 754-2019 semantics, see {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                                                         | floating point types                         |
+| T \_\_builtin_elementwise_minimumnum(T x, T y) | return x or y, whichever is smaller. Follows IEEE 754-2019 semantics, see {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                                                                                                                                                        | floating point types                         |
 | T \_\_builtin_elementwise_fshl(T x, T y, T z)  | perform a funnel shift left. Concatenate x and y (x is the most significant bits of the wide value), the combined value is shifted left by z (modulo the bit width of the original arguments), and the most significant bits are extracted to produce a result that is the same size as the original arguments.    | integer types                                |
 | T \_\_builtin_elementwise_fshr(T x, T y, T z)  | perform a funnel shift right. Concatenate x and y (x is the most significant bits of the wide value), the combined value is shifted right by z (modulo the bit width of the original arguments), and the least significant bits are extracted to produce a result that is the same size as the original arguments. | integer types                                |
 | T \_\_builtin_elementwise_clzg(T x[, T y])     | return the number of leading 0 bits in the first argument. If the first argument is 0 and an optional second argument is provided, the second argument is returned. It is undefined behaviour if the first argument is 0 and no second argument is provided.                                                       | integer types                                |
@@ -840,8 +840,8 @@ Let `VT` be a vector type and `ET` the element type of `VT`.
 | ET \_\_builtin_reduce_and(VT a)                 | &                                                                                                                                                                                        | integer types                    |
 | ET \_\_builtin_reduce_or(VT a)                  | \|                                                                                                                                                                                       | integer types                    |
 | ET \_\_builtin_reduce_xor(VT a)                 | ^                                                                                                                                                                                        | integer types                    |
-| ET \_\_builtin_reduce_maximum(VT a)             | return the largest element of the vector. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                         | floating point types             |
-| ET \_\_builtin_reduce_minimum(VT a)             | return the smallest element of the vector. Follows IEEE 754-2019 semantics, see [LangRef](http://llvm.org/docs/LangRef.html#i-fminmax-family) for the comparison.                        | floating point types             |
+| ET \_\_builtin_reduce_maximum(VT a)             | return the largest element of the vector. Follows IEEE 754-2019 semantics, see {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                         | floating point types             |
+| ET \_\_builtin_reduce_minimum(VT a)             | return the smallest element of the vector. Follows IEEE 754-2019 semantics, see {external+llvm:ref}`LangRef <i_fminmax_family>` for the comparison.                        | floating point types             |
 | ET \_\_builtin_reduce_assoc_fadd(VT a[, ET s])  | associative floating-point add reduction.                                                                                                                                                | floating point types             |
 | ET \_\_builtin_reduce_in_order_fadd(VT a, ET s) | in order floating-point add reduction, initializing the accumulator with `(ET)s`, then adding each lane of the `a` in-order, starting from lane 0. The additions cannot be reassociated. | floating point types             |
 
@@ -5481,7 +5481,7 @@ The pointer argument must point to the global or generic address space.
 These builtins are supported on gfx9, gfx10, gfx11, and gfx12 targets.
 
 They map to the LLVM intrinsics `llvm.amdgcn.av.load.b128` and
-`llvm.amdgcn.av.store.b128` documented in [User Guide for AMDGPU Backend](https://llvm.org/docs/AMDGPUUsage.html).
+`llvm.amdgcn.av.store.b128` documented in {external+llvm:doc}`User Guide for AMDGPU Backend <AMDGPUUsage>`.
 
 ### ARM/AArch64 Language Extensions
 
diff --git a/clang/docs/LibASTMatchersTutorial.md b/clang/docs/LibASTMatchersTutorial.md
index b12e3960f99f2..3781b698f0f55 100644
--- a/clang/docs/LibASTMatchersTutorial.md
+++ b/clang/docs/LibASTMatchersTutorial.md
@@ -14,8 +14,8 @@ AST <IntroductionToTheClangAST>`
 
 As Clang is part of the LLVM project, you'll need to download LLVM's
 source code first. Both Clang and LLVM are in the same git repository,
-under different directories. For further information, see the [getting
-started guide](https://llvm.org/docs/GettingStarted.html).
+under different directories. For further information, see the
+{external+llvm:doc}`getting started guide <GettingStarted>`.
 
 ```console
 mkdir ~/clang-llvm && cd ~/clang-llvm
diff --git a/clang/docs/MemorySanitizer.md b/clang/docs/MemorySanitizer.md
index fdc7b7e0935f0..2bcdcce633a53 100644
--- a/clang/docs/MemorySanitizer.md
+++ b/clang/docs/MemorySanitizer.md
@@ -17,7 +17,7 @@ Here is a not comprehensive of list cases when MemorySanitizer will report an er
 
 ## How to build
 
-Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html).
+Build LLVM/Clang with {external+llvm:doc}`CMake <CMake>`.
 
 ## Usage
 
diff --git a/clang/docs/OffloadingDesign.md b/clang/docs/OffloadingDesign.md
index 6b9346f5d6b05..b4ced2fdf7a03 100644
--- a/clang/docs/OffloadingDesign.md
+++ b/clang/docs/OffloadingDesign.md
@@ -17,7 +17,7 @@ Clang and then executed using the `libomptarget` runtime and the associated
 plugin for the target architecture, e.g. `libomptarget.rtl.cuda`. This section
 describes the steps necessary to create a functioning device image that can be
 loaded by the OpenMP runtime. More information on the OpenMP runtimes can be
-found at the [OpenMP documentation page](https://openmp.llvm.org).
+found at the {external+openmp:doc}`OpenMP documentation page <index>`.
 
 (offloading-overview)=
 
diff --git a/clang/docs/OpenCLSupport.md b/clang/docs/OpenCLSupport.md
index f72258743ec22..d592dc64d6032 100644
--- a/clang/docs/OpenCLSupport.md
+++ b/clang/docs/OpenCLSupport.md
@@ -386,7 +386,7 @@ Feel free to contact us on [the Discourse forums (Clang Frontend category)](http
 
 ### C++ libraries for OpenCL
 
-There is ongoing work to support C++ standard libraries from [LLVM's libcxx](https://libcxx.llvm.org/) in OpenCL kernel code using C++ for OpenCL mode.
+There is ongoing work to support C++ standard libraries from {external+libcxx:doc}`LLVM's libcxx <index>` in OpenCL kernel code using C++ for OpenCL mode.
 
 It is currently possible to include `type_traits` from C++17 in the kernel
 sources when the following clang extensions are enabled
diff --git a/clang/docs/PCHInternals.md b/clang/docs/PCHInternals.md
index c7fa0e3f235fc..53f972910b1eb 100644
--- a/clang/docs/PCHInternals.md
+++ b/clang/docs/PCHInternals.md
@@ -62,7 +62,7 @@ Clang's AST files are designed with a compact on-disk representation, which
 minimizes both creation time and the time required to initially load the AST
 file. The AST file itself contains a serialized representation of Clang's
 abstract syntax trees and supporting data structures, stored using the same
-compressed bitstream as [LLVM's bitcode file format](https://llvm.org/docs/BitCodeFormat.html).
+compressed bitstream as {external+llvm:doc}`LLVM's bitcode file format <BitCodeFormat>`.
 
 Clang's AST files are loaded "lazily" from disk. When an AST file is initially
 loaded, Clang reads only a small amount of data from the AST file to establish
@@ -125,7 +125,7 @@ only contain the serialized AST.
 The `clangast` section is organized into several different blocks, each of
 which contains the serialized representation of a part of Clang's internal
 representation. Each of the blocks corresponds to either a block or a record
-within [LLVM's bitstream format](https://llvm.org/docs/BitCodeFormat.html).
+within {external+llvm:doc}`LLVM's bitstream format <BitCodeFormat>`.
 The contents of each of these logical blocks are described below.
 
 ```{image} PCHLayout.png
@@ -134,7 +134,7 @@ The contents of each of these logical blocks are described below.
 The `llvm-objdump` utility provides a `-raw-clang-ast` option to extract the
 binary contents of the AST section from an object file container.
 
-The [llvm-bcanalyzer](https://llvm.org/docs/CommandGuide/llvm-bcanalyzer.html)
+The {external+llvm:doc}`llvm-bcanalyzer <CommandGuide/llvm-bcanalyzer>`
 utility can be used to examine the actual structure of the bitstream for the AST
 section. This information can be used both to help understand the structure of
 the AST section and to isolate areas where the AST representation can still be
@@ -564,4 +564,3 @@ Name Visibility
   existing, non-visible, already-deserialized AST nodes visible; it is the
   responsibility of the AST reader to find and update these AST nodes when it
   is notified of the import.
-
diff --git a/clang/docs/RealtimeSanitizer.md b/clang/docs/RealtimeSanitizer.md
index a333090b86000..bf3eb4ce8a464 100644
--- a/clang/docs/RealtimeSanitizer.md
+++ b/clang/docs/RealtimeSanitizer.md
@@ -21,7 +21,7 @@ The runtime slowdown introduced by RealtimeSanitizer is negligible.
 
 ## How to build
 
-Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html) and enable the
+Build LLVM/Clang with {external+llvm:doc}`CMake <CMake>` and enable the
 `compiler-rt` runtime. An example CMake configuration that will allow for the
 use/testing of RealtimeSanitizer:
 
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 043a0ddae2a6c..621cf1add884c 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -30,9 +30,9 @@ This document contains the release notes for the Clang C/C++/Objective-C
 frontend, part of the LLVM Compiler Infrastructure, release {{env.config.release}}. Here we
 describe the status of Clang in some detail, including major
 improvements from the previous release and new feature work. For the
-general LLVM release notes, see [the LLVM
-documentation](https://llvm.org/docs/ReleaseNotes.html). For the libc++ release notes,
-see [this page](https://libcxx.llvm.org/ReleaseNotes.html). All LLVM releases
+general LLVM release notes, see
+{external+llvm:doc}`the LLVM documentation <ReleaseNotes>`. For the libc++ release notes,
+see {external+libcxx:doc}`this page <ReleaseNotes>`. All LLVM releases
 may be downloaded from the [LLVM releases web site](https://llvm.org/releases/).
 
 For more information about Clang or LLVM, including information about the
diff --git a/clang/docs/SafeBuffers.md b/clang/docs/SafeBuffers.md
index 7159581bc18fc..6a1ce65d31cc5 100644
--- a/clang/docs/SafeBuffers.md
+++ b/clang/docs/SafeBuffers.md
@@ -13,7 +13,7 @@ it combines:
   during compilation to help you update your code to encapsulate and propagate
   the bounds information associated with pointers;
 - runtime assertions implemented as part of
-  ([libc++ hardening modes](https://libcxx.llvm.org/Hardening.html))
+  ({external+libcxx:doc}`libc++ hardening modes <Hardening>`)
   that eliminate undefined behavior as long as the coding convention
   is followed and the bounds information is therefore available and correct.
 
@@ -37,7 +37,7 @@ In order to achieve bounds safety, your codebase needs to have access to
 well-encapsulated bounds-safe container, view, and iterator types.
 If your project uses libc++, standard container and view types such as
 `std::vector` and `std::span` can be made bounds-safe by enabling
-the "fast" [hardening mode](https://libcxx.llvm.org/Hardening.html)
+the "fast" {external+libcxx:doc}`hardening mode <Hardening>`
 (passing `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST`) to your
 compiler) or any of the stricter hardening modes.
 
diff --git a/clang/docs/SanitizerCoverage.md b/clang/docs/SanitizerCoverage.md
index 5630d46900f17..c1aa35bba38a6 100644
--- a/clang/docs/SanitizerCoverage.md
+++ b/clang/docs/SanitizerCoverage.md
@@ -272,7 +272,7 @@ around comparison instructions and switch statements.
 Similarly, with `-fsanitize-coverage=trace-div` the compiler will instrument
 integer division instructions (to capture the right argument of division)
 and with `-fsanitize-coverage=trace-gep` --
-the [LLVM GEP instructions](https://llvm.org/docs/GetElementPtr.html)
+the {external+llvm:doc}`LLVM GEP instructions <GetElementPtr>`
 (to capture array indices).
 Similarly, with `-fsanitize-coverage=trace-loads` and `-fsanitize-coverage=trace-stores`
 the compiler will instrument loads and stores, respectively.
diff --git a/clang/docs/SourceBasedCodeCoverage.md b/clang/docs/SourceBasedCodeCoverage.md
index 8d43c5cfa360c..c3e345fe4b124 100644
--- a/clang/docs/SourceBasedCodeCoverage.md
+++ b/clang/docs/SourceBasedCodeCoverage.md
@@ -120,7 +120,7 @@ copy that's mapped into memory). This implementation can be also enabled for
 other platforms by passing the `-runtime-counter-relocation` option to the
 backend during compilation.
 
-For a program such as the [Lit](https://llvm.org/docs/CommandGuide/lit.html)
+For a program such as the {external+llvm:doc}`Lit <CommandGuide/lit>`
 testing tool, which invokes other programs, it may be necessary to set
 `LLVM_PROFILE_FILE` for each invocation. The pattern strings "%p" or "%Nm"
 may help to avoid corruption due to concurrency. Note that "%p" is also a Lit
@@ -224,7 +224,7 @@ TOTAL                   13                 0   100.00%           3
 
 The `llvm-cov` tool supports specifying a custom demangler, writing out
 reports in a directory structure, and generating HTML reports. For the full
-list of options, please refer to the [command guide](https://llvm.org/docs/CommandGuide/llvm-cov.html).
+list of options, please refer to the {external+llvm:doc}`command guide <CommandGuide/llvm-cov>`.
 
 A few final notes:
 
diff --git a/clang/docs/ThinLTO.md b/clang/docs/ThinLTO.md
index 4487b348c0e92..1ba7f369a24f9 100644
--- a/clang/docs/ThinLTO.md
+++ b/clang/docs/ThinLTO.md
@@ -39,7 +39,7 @@ the performance improvement.
 The 3.9 release of clang includes ThinLTO support. However, ThinLTO
 is under active development, and new features, improvements and bugfixes
 are being added for the next release. For the latest ThinLTO support,
-[build a recent version of clang and LLVM](https://llvm.org/docs/CMake.html).
+{external+llvm:doc}`build a recent version of clang and LLVM <CMake>`.
 
 ### Linkers
 
@@ -51,7 +51,7 @@ ThinLTO is currently supported for the following linkers:
 
 - **gold (via the gold-plugin)**:
   Similar to monolithic LTO, this requires using
-  a [gold linker configured with plugins enabled](https://llvm.org/docs/GoldPlugin.html).
+  a {external+llvm:doc}`gold linker configured with plugins enabled <GoldPlugin>`.
 - **ld64**:
   Starting with [Xcode 8](https://developer.apple.com/xcode/).
 - **lld**:
@@ -197,8 +197,8 @@ with ThinLTO, follow these steps:
 
 1. The host [compiler](#compiler) must be a version of clang that supports ThinLTO.
 2. The host [linker](#linker) must support ThinLTO (and in the case of gold, must be
-   [configured with plugins enabled](https://llvm.org/docs/GoldPlugin.html)).
-3. Use the following additional [CMake variables](https://llvm.org/docs/CMake.html#options-and-variables)
+   {external+llvm:doc}`configured with plugins enabled <GoldPlugin>`).
+3. Use the following additional {external+llvm:ref}`CMake variables <options and variables>`
    when configuring the bootstrap compiler build:
 
 > - `-DLLVM_ENABLE_LTO=Thin`
@@ -233,7 +233,7 @@ Integrated Distributed ThinLTO (DTLTO) enables the distribution of backend
 ThinLTO compilations via external distribution systems, such as Incredibuild,
 during the traditional link step.
 
-The implementation is documented here: <https://llvm.org/docs/DTLTO.html>.
+The implementation is {external+llvm:doc}`documented here <DTLTO>`.
 
 #### Command-Line Options
 
diff --git a/clang/docs/ThreadSanitizer.md b/clang/docs/ThreadSanitizer.md
index 7f48a7470e254..ee9f6daffebf5 100644
--- a/clang/docs/ThreadSanitizer.md
+++ b/clang/docs/ThreadSanitizer.md
@@ -9,7 +9,7 @@ ThreadSanitizer is about **5x-10x**.
 
 ## How to build
 
-Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html).
+Build LLVM/Clang with {external+llvm:doc}`CMake <CMake>`.
 
 ## Supported Platforms
 
diff --git a/clang/docs/Toolchain.md b/clang/docs/Toolchain.md
index 8ed3c5515132e..0afc1a8abd3d2 100644
--- a/clang/docs/Toolchain.md
+++ b/clang/docs/Toolchain.md
@@ -105,7 +105,7 @@ Clang can be configured to use one of several different linkers:
 - MSVC's link.exe
 
 Link-time optimization is natively supported by lld, and supported via
-a [linker plugin](https://llvm.org/docs/GoldPlugin.html) when using gold.
+a {external+llvm:doc}`linker plugin <GoldPlugin>` when using gold.
 
 The default linker varies between targets, and can be overridden via the
 `-fuse-ld=<linker name>` flag.
@@ -295,7 +295,7 @@ of the [C++ standard library](https://en.cppreference.com/w/cpp).
 
 #### libc++ (LLVM)
 
-[libc++](https://libcxx.llvm.org/) is LLVM's implementation of the C++
+{external+libcxx:doc}`libc++ <index>` is LLVM's implementation of the C++
 standard library, aimed at being a complete implementation of the C++
 standards from C++11 onwards.
 
diff --git a/clang/docs/TypeSanitizer.md b/clang/docs/TypeSanitizer.md
index 28a1300dd0292..a802029a3fc32 100644
--- a/clang/docs/TypeSanitizer.md
+++ b/clang/docs/TypeSanitizer.md
@@ -56,7 +56,7 @@ same function for the library calls.
 
 ## How to build
 
-Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html) and enable
+Build LLVM/Clang with {external+llvm:doc}`CMake <CMake>` and enable
 the `compiler-rt` runtime. An example CMake configuration that will allow
 for the use/testing of TypeSanitizer:
 
diff --git a/clang/docs/UndefinedBehaviorSanitizer.md b/clang/docs/UndefinedBehaviorSanitizer.md
index 25fdb741c6a2b..04cb446c54a78 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.md
+++ b/clang/docs/UndefinedBehaviorSanitizer.md
@@ -21,7 +21,7 @@ The checks have small runtime cost and no impact on address space layout or ABI.
 
 ## How to build
 
-Build LLVM/Clang with [CMake](https://llvm.org/docs/CMake.html).
+Build LLVM/Clang with {external+llvm:doc}`CMake <CMake>`.
 
 ## Usage
 
diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index 3bec20612c048..7e9f71987d30b 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -5174,7 +5174,7 @@ $ clang --target=spirv64 test1.cl test2.cl
 ```
 
 More information about the SPIR-V target settings and supported versions of SPIR-V
-format can be found in [the SPIR-V target guide](https://llvm.org/docs/SPIRVUsage.html).
+format can be found in {external+llvm:doc}`the SPIR-V target guide <SPIRVUsage>`.
 
 (clang-cl)=
 
diff --git a/clang/docs/analyzer/developer-docs/PerformanceInvestigation.md b/clang/docs/analyzer/developer-docs/PerformanceInvestigation.md
index 3d3ad508e444e..ee575b2962a35 100644
--- a/clang/docs/analyzer/developer-docs/PerformanceInvestigation.md
+++ b/clang/docs/analyzer/developer-docs/PerformanceInvestigation.md
@@ -54,7 +54,7 @@ It's easy to start profiling, you only have 2 prerequisites.
 Build with `-fno-omit-frame-pointer` and debug info (`-g`).
 You can use release builds, but probably the easiest is to set the `CMAKE_BUILD_TYPE=RelWithDebInfo`
 along with `CMAKE_CXX_FLAGS="-fno-omit-frame-pointer"` when configuring `llvm`.
-Here is how to [get started](https://llvm.org/docs/CMake.html#quick-start) if you are in trouble.
+Here is how to {external+llvm:ref}`get started <quick start>` if you are in trouble.
 
 ```{code-block} bash
 :caption: Running the Clang Static Analyzer through ``perf`` to gather samples of the
@@ -135,4 +135,3 @@ cat trace.json | grep -Po '"name":"(.+)"' | sort | uniq -c | sort -nr | head -n
 ```
 
 `uftrace` can also dump the report as a Flame graph using `uftrace dump --flame-graph`.
-
diff --git a/clang/docs/analyzer/user-docs/FilingBugs.md b/clang/docs/analyzer/user-docs/FilingBugs.md
index ab3fedbe2a155..d88085b9d79d8 100644
--- a/clang/docs/analyzer/user-docs/FilingBugs.md
+++ b/clang/docs/analyzer/user-docs/FilingBugs.md
@@ -11,6 +11,5 @@ following:
   are seeing, including what you thought should have been the expected behavior
   and why.
 
-Please [file bugs and feature requests](https://llvm.org/docs/HowToSubmitABug.html)
+Please {external+llvm:doc}`file bugs and feature requests <HowToSubmitABug>`
 in [LLVM's issue tracker](https://github.com/llvm/llvm-project/issues) and label the report with the `clang:static analyzer` label.
-
diff --git a/clang/docs/conf.py b/clang/docs/conf.py
index 82e4385e504bd..a909a797a73f6 100644
--- a/clang/docs/conf.py
+++ b/clang/docs/conf.py
@@ -26,12 +26,17 @@
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions += [
+    "sphinx.ext.intersphinx",
     "sphinx.ext.todo",
     "sphinx.ext.mathjax",
     "sphinx.ext.graphviz",
     "llvm_sphinx.ext.ghlinks",
 ]
 
+intersphinx_mapping = get_llvm_intersphinx_mapping(
+    "llvm", "clang-tools-extra", "libcxx", "openmp"
+)
+
 import sphinx
 
 # General information about the project.
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b5f25e36f7a62..3d48186555388 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -231,7 +231,7 @@ extensions. Section 5 covers named address spaces.
 
 [amdgpu usage guide]: https://llvm.org/docs/AMDGPUUsage.html#address-spaces
 [iso tr18037]: https://standards.iso.org/ittf/PubliclyAvailableStandards/c051126_ISO_IEC_TR_18037_2008.zip
-[nvptx usage guide]: https://llvm.org/docs/NVPTXUsage.html#address-spaces
+[nvptx usage guide]: inv:llvm:std:label#address-spaces
   }];
 }
 
@@ -3638,8 +3638,8 @@ An error will be given if:
 def AMDGPUAvailableVisibleDocs : Documentation {
   let Category = DocCatAMDGPUAttributes;
   let Content = [{
-This attribute controls availability and visibility as described in the [AMDGPU
-Memory Model](https://llvm.org/docs/AMDGPUMemoryModel.html). When placed on
+This attribute controls availability and visibility as described in the
+{external+llvm:doc}`AMDGPU Memory Model <AMDGPUMemoryModel>`. When placed on
 an atomic expression or fence, the resulting atomic or fence instruction carries
 the corresponding *AV Metadata*.
 
@@ -7723,7 +7723,7 @@ should be enabled for the function body. This can also be applied to a method
 in Objective C. This attribute will take precedence over the command line flag
 in the case where {option}`-mno-speculative-load-hardening` is specified.
 
-[slh]: https://llvm.org/docs/SpeculativeLoadHardening.html
+[slh]: inv:llvm:std:doc#SpeculativeLoadHardening
 
 Speculative Load Hardening is a best-effort mitigation against
 information leak attacks that make use of control flow

>From fb94e63040b26d326ba9e4b51c1daba001cc37ef Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Wed, 9 Sep 2026 23:10:00 +0000
Subject: [PATCH 4/4] [docs] Enable absolute documentation link checks

Configure the LLVM and Clang documentation URL prefixes so their Sphinx
builds reject absolute links to documents in the same project or a configured
intersphinx project.

Part of #214861
---
 clang/docs/conf.py |  3 +++
 llvm/docs/conf.py  | 12 +++++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/clang/docs/conf.py b/clang/docs/conf.py
index a909a797a73f6..b40f6bce1e0a7 100644
--- a/clang/docs/conf.py
+++ b/clang/docs/conf.py
@@ -30,6 +30,7 @@
     "sphinx.ext.todo",
     "sphinx.ext.mathjax",
     "sphinx.ext.graphviz",
+    "llvm_sphinx.ext.absolute_links",
     "llvm_sphinx.ext.ghlinks",
 ]
 
@@ -37,6 +38,8 @@
     "llvm", "clang-tools-extra", "libcxx", "openmp"
 )
 
+llvm_sphinx_doc_url_prefixes = ("https://clang.llvm.org/docs/",)
+
 import sphinx
 
 # General information about the project.
diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py
index efa2e82d52fa5..82ed3dfd554ef 100644
--- a/llvm/docs/conf.py
+++ b/llvm/docs/conf.py
@@ -22,7 +22,17 @@
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions += ["sphinx.ext.intersphinx", "sphinx.ext.todo", "llvm_sphinx.ext.checks"]
+extensions += [
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.todo",
+    "llvm_sphinx.ext.absolute_links",
+    "llvm_sphinx.ext.checks",
+]
+
+llvm_sphinx_doc_url_prefixes = (
+    "https://llvm.org/docs/",
+    "https://www.llvm.org/docs/",
+)
 
 myst_enable_extensions += ["deflist"]
 myst_url_schemes = {



More information about the llvm-branch-commits mailing list