https://github.com/AaronBallman updated https://github.com/llvm/llvm-project/pull/205881
>From 68494a288840ee4458891b8456162108e0de8de5 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <[email protected]> Date: Thu, 25 Jun 2026 14:25:16 -0400 Subject: [PATCH 1/4] Document the const and pure attributes These attributes are ancient and their implmentation predate requirements to have documentation. I based this documentation off the implementation I was seeing in CGCall.cpp. --- clang/include/clang/Basic/Attr.td | 4 +-- clang/include/clang/Basic/AttrDocs.td | 49 +++++++++++++++++++++++++++ clang/test/AST/undocumented-attrs.cpp | 4 +-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index f1ae66bd7f2bb..8a5dec2e1a00b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1497,7 +1497,7 @@ def Common : InheritableAttr { def Const : InheritableAttr { let Spellings = [GCC<"const">, GCC<"__const">]; - let Documentation = [Undocumented]; + let Documentation = [ConstDocs]; let SimpleHandler = 1; } @@ -3157,7 +3157,7 @@ def ArmLocallyStreaming : InheritableAttr, TargetSpecificAttr<TargetAArch64> { def Pure : InheritableAttr { let Spellings = [GCC<"pure">]; - let Documentation = [Undocumented]; + let Documentation = [PureDocs]; let SimpleHandler = 1; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index d806adb4be4b8..19fc8ae008e71 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -10253,3 +10253,52 @@ The attribute is also supported with blocks and in Objective-C. } }]; } + +def ConstDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``const`` attribute can be applied to the declaration of a function to signal that repeated calls to the function with the same argument values may be safe to elide because the subsequent calls will always return the same value as the initial call. + +The attribute informs the optimizer that the function cannot read or write to memory, does not support unwinding, will return (has no infinite loops), and that any pointer or reference arguments to the call will not be read from or written to. + +The attribute generally should only be used on functions with a non-``void`` return type which do not accept a pointer or reference argument. +The ``const`` attribute imposes greater restrictions than the related ``pure`` attribute; applying both attributes to a declaration will be diagnosed and ``pure`` will be ignored. + +The following trivial example demonstrates how the attribute can be used: + +.. code-block:: c++ + + __attribute__((const)) int add_one(int x) { return x + 1; } + + int main(void) { + int x = add_one(1); + int y = add_one(1); // Call can be elided + } + }]; +} + +def PureDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``pure`` attribute can be applied to the declaration of a function to signal that repeated calls to the function with the same argument values may be safe to elide because the subsequent calls will always return the same value as the initial call. + +The attribute informs the optimizer that the function cannot write to memory, does not support unwinding, will return (has no infinite loops), and that any pointer or reference arguments to the call will not be written to. + +Unlike the ``const`` attribute, the ``pure`` attribute allows memory to be read, even if it changes between subsequent calls. + +The attribute generally should only be used on functions with a non-``void`` return type. +The ``pure`` attribute imposes weaker restrictions than the related ``const`` attribute; applying both attributes to a declaration will be diagnosed and ``pure`` will be ignored. + +The following trivial example demonstrates how the attribute can be used: + +.. code-block:: c++ + + __attribute__((pure)) int get_char(const char *buffer, int idx) { return buffer[idx]; } + + int main(void) { + const char *str = "testing"; + int x = get_char(str, 0); + int y = get_char(str, 0); // Call can be elided + } + }]; +} diff --git a/clang/test/AST/undocumented-attrs.cpp b/clang/test/AST/undocumented-attrs.cpp index 64c7d165915cc..cbeddddcb5516 100644 --- a/clang/test/AST/undocumented-attrs.cpp +++ b/clang/test/AST/undocumented-attrs.cpp @@ -25,7 +25,6 @@ CHECK-NEXT: CUDALaunchBounds CHECK-NEXT: CUDAShared CHECK-NEXT: Capability CHECK-NEXT: Common -CHECK-NEXT: Const CHECK-NEXT: ConsumableAutoCast CHECK-NEXT: ConsumableSetOnRead CHECK-NEXT: FormatArg @@ -73,7 +72,6 @@ CHECK-NEXT: Pascal CHECK-NEXT: PointerFieldProtection CHECK-NEXT: PtGuardedBy CHECK-NEXT: PtGuardedVar -CHECK-NEXT: Pure CHECK-NEXT: ReentrantCapability CHECK-NEXT: ReqdWorkGroupSize CHECK-NEXT: RequiresCapability @@ -89,4 +87,4 @@ CHECK-NEXT: Visibility CHECK-NEXT: WeakImport CHECK-NEXT: WeakRef CHECK-NEXT: WorkGroupSizeHint -CHECK-NEXT: Total: 83 +CHECK-NEXT: Total: 81 >From bd3bbeadc4f39e5778d3c50064f91aca728a6173 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <[email protected]> Date: Fri, 26 Jun 2026 08:15:52 -0400 Subject: [PATCH 2/4] Update based on review feedback --- clang/include/clang/Basic/AttrDocs.td | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 19fc8ae008e71..0a8b5dac4ae78 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -10257,14 +10257,14 @@ The attribute is also supported with blocks and in Objective-C. def ConstDocs : Documentation { let Category = DocCatFunction; let Content = [{ -The ``const`` attribute can be applied to the declaration of a function to signal that repeated calls to the function with the same argument values may be safe to elide because the subsequent calls will always return the same value as the initial call. +The ``const`` attribute can be applied to the declaration of a function to signal that calls to the function with the same argument values may be elided because all of the calls will always return the same value. -The attribute informs the optimizer that the function cannot read or write to memory, does not support unwinding, will return (has no infinite loops), and that any pointer or reference arguments to the call will not be read from or written to. +The attribute informs the optimizer that the function cannot read or write to memory, does not support unwinding, will return (has no infinite loops, does not call a ``noreturn`` function, etc), and that any pointer or reference arguments to the call will not be read from or written to. -The attribute generally should only be used on functions with a non-``void`` return type which do not accept a pointer or reference argument. -The ``const`` attribute imposes greater restrictions than the related ``pure`` attribute; applying both attributes to a declaration will be diagnosed and ``pure`` will be ignored. +The attribute generally should only be used on functions with a non-``void`` return type and which do not accept a pointer or reference argument. +The ``const`` attribute imposes greater restrictions than the related ``pure`` attribute; applying both attributes to a declaration will be diagnosed and the ``const`` attribute takes precedence. -The following trivial example demonstrates how the attribute can be used: +The following example demonstrates how the attribute can be used: .. code-block:: c++ @@ -10280,16 +10280,16 @@ The following trivial example demonstrates how the attribute can be used: def PureDocs : Documentation { let Category = DocCatFunction; let Content = [{ -The ``pure`` attribute can be applied to the declaration of a function to signal that repeated calls to the function with the same argument values may be safe to elide because the subsequent calls will always return the same value as the initial call. +The ``pure`` attribute can be applied to the declaration of a function to signal that calls to the function with the same argument values may be elided if no global state has changed in the meantime because all of the calls will always return the same value. -The attribute informs the optimizer that the function cannot write to memory, does not support unwinding, will return (has no infinite loops), and that any pointer or reference arguments to the call will not be written to. +The attribute informs the optimizer that the function cannot write to memory, does not support unwinding, will return (has no infinite loops, does not call a ``noreturn`` function, etc), and that any pointer or reference arguments to the call will not be written to. Unlike the ``const`` attribute, the ``pure`` attribute allows memory to be read, even if it changes between subsequent calls. The attribute generally should only be used on functions with a non-``void`` return type. -The ``pure`` attribute imposes weaker restrictions than the related ``const`` attribute; applying both attributes to a declaration will be diagnosed and ``pure`` will be ignored. +The ``pure`` attribute imposes weaker restrictions than the related ``const`` attribute; applying both attributes to a declaration will be diagnosed and the ``const`` attribute takes precedence. -The following trivial example demonstrates how the attribute can be used: +The following example demonstrates how the attribute can be used: .. code-block:: c++ >From 7aea2525773b597f4f6c2ee8eb44b8daf03384b8 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <[email protected]> Date: Fri, 26 Jun 2026 08:36:55 -0400 Subject: [PATCH 3/4] Combine into one set of docs for both attributes; reword accordingly --- clang/include/clang/Basic/Attr.td | 4 +-- clang/include/clang/Basic/AttrDocs.td | 35 +++++++++++---------------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 8a5dec2e1a00b..d3d89bad9aa24 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1497,7 +1497,7 @@ def Common : InheritableAttr { def Const : InheritableAttr { let Spellings = [GCC<"const">, GCC<"__const">]; - let Documentation = [ConstDocs]; + let Documentation = [ConstPureDocs]; let SimpleHandler = 1; } @@ -3157,7 +3157,7 @@ def ArmLocallyStreaming : InheritableAttr, TargetSpecificAttr<TargetAArch64> { def Pure : InheritableAttr { let Spellings = [GCC<"pure">]; - let Documentation = [PureDocs]; + let Documentation = [ConstPureDocs]; let SimpleHandler = 1; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 0a8b5dac4ae78..5bb1d95d25d6d 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -10254,17 +10254,23 @@ The attribute is also supported with blocks and in Objective-C. }]; } -def ConstDocs : Documentation { +def ConstPureDocs : Documentation { let Category = DocCatFunction; let Content = [{ -The ``const`` attribute can be applied to the declaration of a function to signal that calls to the function with the same argument values may be elided because all of the calls will always return the same value. +The ``const`` or ``pure`` attributes can be applied to the declaration of a function to signal that calls to the function with the same argument values may be elided under some circumstances. +The ``const`` attribute imposes greater restrictions than the related ``pure`` attribute; applying both attributes to a declaration will be diagnosed and the ``const`` attribute takes precedence. -The attribute informs the optimizer that the function cannot read or write to memory, does not support unwinding, will return (has no infinite loops, does not call a ``noreturn`` function, etc), and that any pointer or reference arguments to the call will not be read from or written to. +The ``pure`` attribute informs the optimizer that the function cannot write to memory, does not support unwinding, will return (has no infinite loops, does not call a ``noreturn`` function, etc), and that any pointer or reference parameters will not be written to. -The attribute generally should only be used on functions with a non-``void`` return type and which do not accept a pointer or reference argument. -The ``const`` attribute imposes greater restrictions than the related ``pure`` attribute; applying both attributes to a declaration will be diagnosed and the ``const`` attribute takes precedence. +The ``const`` attribute is similar except that the function cannot read or write to memory and that any pointer or reference parameters will not be read from or written to. + +Neither attribute should be used on a function which has side effects or uses external data to compute the returned value. +Therefore, both attributes are diagnosed when applied to a function with a non-``void`` return type. + +Because of the prohibition against reading memory, the ``const`` attribute generally should not be used on a function which accepts a pointer or reference argument. +The ``pure`` attribute allows (non-volatile) memory to be read; calls will only be elided if the optimizer can prove the memory accessed cannot be changed between successive calls to the function. -The following example demonstrates how the attribute can be used: +The following example demonstrates how the ``const`` attribute can be used: .. code-block:: c++ @@ -10274,22 +10280,8 @@ The following example demonstrates how the attribute can be used: int x = add_one(1); int y = add_one(1); // Call can be elided } - }]; -} -def PureDocs : Documentation { - let Category = DocCatFunction; - let Content = [{ -The ``pure`` attribute can be applied to the declaration of a function to signal that calls to the function with the same argument values may be elided if no global state has changed in the meantime because all of the calls will always return the same value. - -The attribute informs the optimizer that the function cannot write to memory, does not support unwinding, will return (has no infinite loops, does not call a ``noreturn`` function, etc), and that any pointer or reference arguments to the call will not be written to. - -Unlike the ``const`` attribute, the ``pure`` attribute allows memory to be read, even if it changes between subsequent calls. - -The attribute generally should only be used on functions with a non-``void`` return type. -The ``pure`` attribute imposes weaker restrictions than the related ``const`` attribute; applying both attributes to a declaration will be diagnosed and the ``const`` attribute takes precedence. - -The following example demonstrates how the attribute can be used: +The ``pure`` attribute can be used similarly: .. code-block:: c++ @@ -10300,5 +10292,6 @@ The following example demonstrates how the attribute can be used: int x = get_char(str, 0); int y = get_char(str, 0); // Call can be elided } + }]; } >From 400ac6778c27a7260fd2f5a9ead391e386cf9885 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <[email protected]> Date: Fri, 26 Jun 2026 08:49:05 -0400 Subject: [PATCH 4/4] Document #42620, per review comment --- clang/include/clang/Basic/AttrDocs.td | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5bb1d95d25d6d..8077e5a9114cc 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -10270,6 +10270,9 @@ Therefore, both attributes are diagnosed when applied to a function with a non-` Because of the prohibition against reading memory, the ``const`` attribute generally should not be used on a function which accepts a pointer or reference argument. The ``pure`` attribute allows (non-volatile) memory to be read; calls will only be elided if the optimizer can prove the memory accessed cannot be changed between successive calls to the function. +An important difference between the Clang and GCC implementations of these attributes is that Clang does not allow unwinding while GCC does. +In Clang, a function marked with ``const`` or ``pure`` is implicitly ``noexcept`` in C++. + The following example demonstrates how the ``const`` attribute can be used: .. code-block:: c++ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
