38 changes: 35 additions & 3 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ Objective-C
Miscellaneous
^^^^^^^^^^^^^

- The DefineOutline tweak now handles member functions of class templates.

Improvements to clang-doc
-------------------------

Expand All @@ -109,12 +111,24 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^

- New :doc:`bugprone-bitwise-pointer-cast
<clang-tidy/checks/bugprone/bitwise-pointer-cast>` check.

Warns about code that tries to cast between pointers by means of
``std::bit_cast`` or ``memcpy``.

- New :doc:`bugprone-tagged-union-member-count
<clang-tidy/checks/bugprone/tagged-union-member-count>` check.

Gives warnings for tagged unions, where the number of tags is
different from the number of data members inside the union.

- New :doc:`portability-template-virtual-member-function
<clang-tidy/checks/portability/template-virtual-member-function>` check.

Finds cases when an uninstantiated virtual member function in a template class
causes cross-compiler incompatibility.

New check aliases
^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -144,7 +158,7 @@ Changes in existing checks
- Improved :doc:`bugprone-sizeof-expression
<clang-tidy/checks/bugprone/sizeof-expression>` check to find suspicious
usages of ``sizeof()``, ``alignof()``, and ``offsetof()`` when adding or
subtracting from a pointer.
subtracting from a pointer directly or when used to scale a numeric value.

- Improved :doc:`bugprone-unchecked-optional-access
<clang-tidy/checks/bugprone/unchecked-optional-access>` to support
Expand Down Expand Up @@ -181,6 +195,10 @@ Changes in existing checks
<clang-tidy/checks/modernize/loop-convert>` check to fix false positive when
using loop variable in initializer of lambda capture.

- Improved :doc:`misc-use-internal-linkage
<clang-tidy/checks/misc/use-internal-linkage>` check to insert ``static`` keyword
before type qualifiers such as ``const`` and ``volatile``.

- Improved :doc:`modernize-min-max-use-initializer-list
<clang-tidy/checks/modernize/min-max-use-initializer-list>` check by fixing
a false positive when only an implicit conversion happened inside an
Expand All @@ -190,18 +208,28 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-nullptr>` check to also recognize
``NULL``/``__null`` (but not ``0``) when used with a templated type.

- Improved :doc:`modernize-use-starts-ends-with
<clang-tidy/checks/modernize/use-starts-ends-with>` check to handle two cases
that can be replaced with ``ends_with``

- Improved :doc:`modernize-use-std-format
<clang-tidy/checks/modernize/use-std-format>` check to support replacing
member function calls too.
member function calls too and to only expand macros starting with ``PRI``
and ``__PRI`` from ``<inttypes.h>`` in the format string.

- Improved :doc:`modernize-use-std-print
<clang-tidy/checks/modernize/use-std-print>` check to support replacing
member function calls too.
member function calls too and to only expand macros starting with ``PRI``
and ``__PRI`` from ``<inttypes.h>`` in the format string.

- Improved :doc:`performance-avoid-endl
<clang-tidy/checks/performance/avoid-endl>` check to use ``std::endl`` as
placeholder when lexer cannot get source text.

- Improved :doc:`performance-move-const-arg
<clang-tidy/checks/performance/move-const-arg>` check to fix a crash when
an argument type is declared but not defined.

- Improved :doc:`readability-container-contains
<clang-tidy/checks/readability/container-contains>` check to let it work on
any class that has a ``contains`` method.
Expand All @@ -220,6 +248,10 @@ Changes in existing checks
<clang-tidy/checks/readability/redundant-smartptr-get>` check to
remove `->`, when redundant `get()` is removed.

- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check to
validate ``namespace`` aliases.

Removed checks
^^^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.. title:: clang-tidy - bugprone-bitwise-pointer-cast

bugprone-bitwise-pointer-cast
=============================

Warns about code that tries to cast between pointers by means of
``std::bit_cast`` or ``memcpy``.

The motivation is that ``std::bit_cast`` is advertised as the safe alternative
to type punning via ``reinterpret_cast`` in modern C++. However, one should not
blindly replace ``reinterpret_cast`` with ``std::bit_cast``, as follows:

.. code-block:: c++

int x{};
-float y = *reinterpret_cast<float*>(&x);
+float y = *std::bit_cast<float*>(&x);

The drop-in replacement behaves exactly the same as ``reinterpret_cast``, and
Undefined Behavior is still invoked. ``std::bit_cast`` is copying the bytes of
the input pointer, not the pointee, into an output pointer of a different type,
which may violate the strict aliasing rules. However, simply looking at the
code, it looks "safe", because it uses ``std::bit_cast`` which is advertised as
safe.

The solution to safe type punning is to apply ``std::bit_cast`` on value types,
not on pointer types:

.. code-block:: c++

int x{};
float y = std::bit_cast<float>(x);

This way, the bytes of the input object are copied into the output object, which
is much safer. Do note that Undefined Behavior can still occur, if there is no
value of type ``To`` corresponding to the value representation produced.
Compilers may be able to optimize this copy and generate identical assembly to
the original ``reinterpret_cast`` version.

Code before C++20 may backport ``std::bit_cast`` by means of ``memcpy``, or
simply call ``memcpy`` directly, which is equally problematic. This is also
detected by this check:

.. code-block:: c++

int* x{};
float* y{};
std::memcpy(&y, &x, sizeof(x));

Alternatively, if a cast between pointers is truly wanted, ``reinterpret_cast``
should be used, to clearly convey the intent and enable warnings from compilers
and linters, which should be addressed accordingly.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Violating the naming rules above results in undefined behavior.
int _g(); // disallowed in global namespace only

The check can also be inverted, i.e. it can be configured to flag any
identifier that is _not_ a reserved identifier. This mode is for use by e.g.
identifier that is *not* a reserved identifier. This mode is for use by e.g.
standard library implementors, to ensure they don't infringe on the user
namespace.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,17 @@ and the result is typically unintended, often out of bounds.
``Ptr + sizeof(T)`` will offset the pointer by ``sizeof(T)`` elements,
effectively exponentiating the scaling factor to the power of 2.

Similarly, multiplying or dividing a numeric value with the ``sizeof`` of an
element or the whole buffer is suspicious, because the dimensional connection
between the numeric value and the actual ``sizeof`` result can not always be
deduced.
While scaling an integer up (multiplying) with ``sizeof`` is likely **always**
an issue, a scaling down (division) is not always inherently dangerous, in case
the developer is aware that the division happens between an appropriate number
of _bytes_ and a ``sizeof`` value.
Turning :option:`WarnOnOffsetDividedBySizeOf` off will restrict the
warnings to the multiplication case.

This case also checks suspicious ``alignof`` and ``offsetof`` usages in
pointer arithmetic, as both return the "size" in bytes and not elements,
potentially resulting in doubly-scaled offsets.
Expand Down Expand Up @@ -299,3 +310,9 @@ Options
``sizeof`` is an expression that produces a pointer (except for a few
idiomatic expressions that are probably intentional and correct).
This detects occurrences of CWE 467. Default is `false`.

.. option:: WarnOnOffsetDividedBySizeOf

When `true`, the check will warn on pointer arithmetic where the
element count is obtained from a division with ``sizeof(...)``,
e.g., ``Ptr + Bytes / sizeof(*T)``. Default is `true`.
2 changes: 2 additions & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Clang-Tidy Checks
:doc:`bugprone-assert-side-effect <bugprone/assert-side-effect>`,
:doc:`bugprone-assignment-in-if-condition <bugprone/assignment-in-if-condition>`,
:doc:`bugprone-bad-signal-to-kill-thread <bugprone/bad-signal-to-kill-thread>`,
:doc:`bugprone-bitwise-pointer-cast <bugprone/bitwise-pointer-cast>`,
:doc:`bugprone-bool-pointer-implicit-conversion <bugprone/bool-pointer-implicit-conversion>`, "Yes"
:doc:`bugprone-branch-clone <bugprone/branch-clone>`,
:doc:`bugprone-casting-through-void <bugprone/casting-through-void>`,
Expand Down Expand Up @@ -347,6 +348,7 @@ Clang-Tidy Checks
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
:doc:`portability-template-virtual-member-function <portability/template-virtual-member-function>`,
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`, "Yes"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ modernize-use-starts-ends-with
==============================

Checks for common roundabout ways to express ``starts_with`` and ``ends_with``
and suggests replacing with ``starts_with`` when the method is available.
Notably, this will work with ``std::string`` and ``std::string_view``.
and suggests replacing with the simpler method when it is available. Notably,
this will work with ``std::string`` and ``std::string_view``.

.. code-block:: c++

std::string s = "...";
if (s.find("prefix") == 0) { /* do something */ }
if (s.rfind("prefix", 0) == 0) { /* do something */ }
if (s.compare(0, strlen("prefix"), "prefix") == 0) { /* do something */ }
if (s.compare(s.size() - strlen("suffix"), strlen("suffix"), "suffix") == 0) {
/* do something */
}
if (s.rfind("suffix") == (s.length() - 6)) {
/* do something */
}
becomes

Expand All @@ -22,3 +28,5 @@ becomes
if (s.starts_with("prefix")) { /* do something */ }
if (s.starts_with("prefix")) { /* do something */ }
if (s.starts_with("prefix")) { /* do something */ }
if (s.ends_with("suffix")) { /* do something */ }
if (s.ends_with("suffix")) { /* do something */ }
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ into:

The check uses the same format-string-conversion algorithm as
`modernize-use-std-print <../modernize/use-std-print.html>`_ and its
shortcomings are described in the documentation for that check.
shortcomings and behaviour in combination with macros are described in the
documentation for that check.

Options
-------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,15 @@ into:
std::println(stderr, "The {} is {:3}", description, value);

If the `ReplacementPrintFunction` or `ReplacementPrintlnFunction` options
are left, or assigned to their default values then this check is only
enabled with `-std=c++23` or later.
are left at or set to their default values then this check is only enabled
with `-std=c++23` or later.

Macros starting with ``PRI`` and ``__PRI`` from `<inttypes.h>` are
expanded, escaping is handled and adjacent strings are concatenated to form
a single ``StringLiteral`` before the format string is converted. Use of
any other macros in the format string will cause a warning message to be
emitted and no conversion will be performed. The converted format string
will always be a single string literal.

The check doesn't do a bad job, but it's not perfect. In particular:

Expand All @@ -34,13 +41,10 @@ The check doesn't do a bad job, but it's not perfect. In particular:
possible.

- At the point that the check runs, the AST contains a single
``StringLiteral`` for the format string and any macro expansion, token
pasting, adjacent string literal concatenation and escaping has been
handled. Although it's possible for the check to automatically put the
escapes back, they may not be exactly as they were written (e.g.
``"\x0a"`` will become ``"\n"`` and ``"ab" "cd"`` will become
``"abcd"``.) This is helpful since it means that the ``PRIx`` macros from
``<inttypes.h>`` are removed correctly.
``StringLiteral`` for the format string where escapes have been expanded.
The check tries to reconstruct escape sequences, they may not be the same
as they were written (e.g. ``"\x41\x0a"`` will become ``"A\n"`` and
``"ab" "cd"`` will become ``"abcd"``.)

- It supports field widths, precision, positional arguments, leading zeros,
leading ``+``, alignment and alternative forms.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.. title:: clang-tidy - portability-template-virtual-member-function

portability-template-virtual-member-function
============================================

Finds cases when an uninstantiated virtual member function in a template class causes
cross-compiler incompatibility.

Upon instantiating a template class, non-virtual member functions don't have to be
instantiated unless they are used. Virtual member function instantiation on the other hand
is unspecified and depends on the implementation of the compiler.

In the following snippets the virtual member function is not instantiated by GCC and Clang,
but it is instantiated by MSVC, so while the snippet is accepted by the former compilers,
it is rejected by the latter.

.. code:: c++

template<typename T>
struct CrossPlatformError {
virtual ~CrossPlatformError() = default;

static void used() {}

virtual void unused() {
T MSVCError = this;
};
};

int main() {
CrossPlatformError<int>::used();
return 0;
}

Cross-platform projects that need to support MSVC on Windows might see compiler errors
because certain virtual member functions are instantiated, which are not instantiated
by other compilers on other platforms. This check highlights such virtual member functions.
2 changes: 1 addition & 1 deletion clang-tools-extra/docs/clang-tidy/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ An overview of all the command-line options:
FormatStyle - Same as '--format-style'.
HeaderFileExtensions - File extensions to consider to determine if a
given diagnostic is located in a header file.
HeaderFilterRegex - Same as '--header-filter-regex'.
HeaderFilterRegex - Same as '--header-filter'.
ImplementationFileExtensions - File extensions to consider to determine if a
given diagnostic is located in an
implementation file.
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/include-cleaner/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(LLVM_LINK_COMPONENTS Support)

add_clang_library(clangIncludeCleaner
add_clang_library(clangIncludeCleaner STATIC
Analysis.cpp
IncludeSpeller.cpp
FindHeaders.cpp
Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/include-cleaner/test/tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,13 @@ int x = foo();
// RUN: clang-include-cleaner -edit --ignore-headers="foobar\.h,foo\.h" %t.cpp -- -I%S/Inputs/
// RUN: FileCheck --match-full-lines --check-prefix=EDIT2 %s < %t.cpp
// EDIT2-NOT: {{^}}#include "foo.h"{{$}}

// RUN: rm -rf %t.dir && mkdir -p %t.dir
// RUN: cp %s %t.cpp
// RUN: echo "[{\"directory\":\"%t.dir\",\"file\":\"../%{t:stem}.tmp.cpp\",\"command\":\":clang++ -I%S/Inputs/ ../%{t:stem}.tmp.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t.dir/compile_commands.json
// RUN: pushd %t.dir
// RUN: clang-include-cleaner -p %{t:stem}.tmp.dir -edit ../%{t:stem}.tmp.cpp
// RUN: popd
// RUN: FileCheck --match-full-lines --check-prefix=EDIT3 %s < %t.cpp
// EDIT3: #include "foo.h"
// EDIT3-NOT: {{^}}#include "foobar.h"{{$}}
70 changes: 63 additions & 7 deletions clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,11 @@ class Action : public clang::ASTFrontendAction {
if (!HTMLReportPath.empty())
writeHTML();

llvm::StringRef Path =
SM.getFileEntryRefForID(SM.getMainFileID())->getName();
assert(!Path.empty() && "Main file path not known?");
// Source File's path of compiler invocation, converted to absolute path.
llvm::SmallString<256> AbsPath(
SM.getFileEntryRefForID(SM.getMainFileID())->getName());
assert(!AbsPath.empty() && "Main file path not known?");
SM.getFileManager().makeAbsolutePath(AbsPath);
llvm::StringRef Code = SM.getBufferData(SM.getMainFileID());

auto Results =
Expand All @@ -185,7 +187,7 @@ class Action : public clang::ASTFrontendAction {
Results.Missing.clear();
if (!Remove)
Results.Unused.clear();
std::string Final = fixIncludes(Results, Path, Code, getStyle(Path));
std::string Final = fixIncludes(Results, AbsPath, Code, getStyle(AbsPath));

if (Print.getNumOccurrences()) {
switch (Print) {
Expand All @@ -202,7 +204,7 @@ class Action : public clang::ASTFrontendAction {
}

if (!Results.Missing.empty() || !Results.Unused.empty())
EditedFiles.try_emplace(Path, Final);
EditedFiles.try_emplace(AbsPath, Final);
}

void writeHTML() {
Expand Down Expand Up @@ -280,6 +282,48 @@ std::function<bool(llvm::StringRef)> headerFilter() {
};
}

// Maps absolute path of each files of each compilation commands to the
// absolute path of the input file.
llvm::Expected<std::map<std::string, std::string>>
mapInputsToAbsPaths(clang::tooling::CompilationDatabase &CDB,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const std::vector<std::string> &Inputs) {
std::map<std::string, std::string> CDBToAbsPaths;
// Factory.editedFiles()` will contain the final code, along with the
// path given in the compilation database. That path can be
// absolute or relative, and if it is relative, it is relative to the
// "Directory" field in the compilation database. We need to make it
// absolute to write the final code to the correct path.
for (auto &Source : Inputs) {
llvm::SmallString<256> AbsPath(Source);
if (auto Err = VFS->makeAbsolute(AbsPath)) {
llvm::errs() << "Failed to get absolute path for " << Source << " : "
<< Err.message() << '\n';
return llvm::errorCodeToError(Err);
}
std::vector<clang::tooling::CompileCommand> Cmds =
CDB.getCompileCommands(AbsPath);
if (Cmds.empty()) {
// It should be found in the compilation database, even user didn't
// specify the compilation database, the `FixedCompilationDatabase` will
// create an entry from the arguments. So it is an error if we can't
// find the compile commands.
std::string ErrorMsg =
llvm::formatv("No compile commands found for {0}", AbsPath).str();
llvm::errs() << ErrorMsg << '\n';
return llvm::make_error<llvm::StringError>(
ErrorMsg, llvm::inconvertibleErrorCode());
}
for (const auto &Cmd : Cmds) {
llvm::SmallString<256> CDBPath(Cmd.Filename);
std::string Directory(Cmd.Directory);
llvm::sys::fs::make_absolute(Cmd.Directory, CDBPath);
CDBToAbsPaths[std::string(CDBPath)] = std::string(AbsPath);
}
}
return CDBToAbsPaths;
}

} // namespace
} // namespace include_cleaner
} // namespace clang
Expand All @@ -305,8 +349,16 @@ int main(int argc, const char **argv) {
}
}

clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
OptionsParser->getSourcePathList());
auto VFS = llvm::vfs::getRealFileSystem();
auto &CDB = OptionsParser->getCompilations();
// CDBToAbsPaths is a map from the path in the compilation database to the
// writable absolute path of the file.
auto CDBToAbsPaths =
mapInputsToAbsPaths(CDB, VFS, OptionsParser->getSourcePathList());
if (!CDBToAbsPaths)
return 1;

clang::tooling::ClangTool Tool(CDB, OptionsParser->getSourcePathList());

auto HeaderFilter = headerFilter();
if (!HeaderFilter)
Expand All @@ -316,6 +368,10 @@ int main(int argc, const char **argv) {
if (Edit) {
for (const auto &NameAndContent : Factory.editedFiles()) {
llvm::StringRef FileName = NameAndContent.first();
if (auto It = CDBToAbsPaths->find(FileName.str());
It != CDBToAbsPaths->end())
FileName = It->second;

const std::string &FinalCode = NameAndContent.second;
if (auto Err = llvm::writeToOutput(
FileName, [&](llvm::raw_ostream &OS) -> llvm::Error {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not clang-query --invalid-arg 2>&1 | FileCheck %s

// CHECK: error: clang-query{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: 'clang-query{{(\.exe)?}} --help'
// CHECK: error: clang-query{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: '{{.*}}clang-query{{(\.exe)?}} --help'
// CHECK-NEXT: clang-query{{(\.exe)?}}: Did you mean '--extra-arg'?
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,46 @@ typedef __UINT32_TYPE__ uint32_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT8_TYPE__ uint8_t;

#define PRIdMAX "lld"
#define PRId64 "lld"
#if __WORDSIZE == 64
# define __PRI64_PREFIX "l"
#else
# define __PRI64_PREFIX "ll"
#endif

#define PRIdMAX __PRI64_PREFIX "d"
#define PRId64 __PRI64_PREFIX "d"
#define PRId32 "d"
#define PRId16 "hd"
#define PRId8 "hhd"

#define PRIiMAX "lli"
#define PRIi64 "lli"
#define PRIiMAX __PRI64_PREFIX "i"
#define PRIi64 __PRI64_PREFIX "i"
#define PRIi32 "i"
#define PRIi16 "hi"
#define PRIi8 "hhi"

#define PRIiFAST64 "lli"
#define PRIiFAST64 __PRI64_PREFIX "i"
#define PRIiFAST32 "i"
#define PRIiFAST16 "hi"
#define PRIiFAST8 "hhi"

#define PRIiLEAST64 "lli"
#define PRIiLEAST64 __PRI64_PREFIX "i"
#define PRIiLEAST32 "i"
#define PRIiLEAST16 "hi"
#define PRIiLEAST8 "hhi"

#define PRIuMAX "llu"
#define PRIu64 "llu"
#define PRIuMAX __PRI64_PREFIX "u"
#define PRIu64 __PRI64_PREFIX "u"
#define PRIu32 "u"
#define PRIu16 "hu"
#define PRIu8 "hhu"

#define PRIuFAST64 "llu"
#define PRIuFAST64 __PRI64_PREFIX "u"
#define PRIuFAST32 "u"
#define PRIuFAST16 "hu"
#define PRIuFAST8 "hhu"

#define PRIuLEAST64 "llu"
#define PRIuLEAST64 __PRI64_PREFIX "u"
#define PRIuLEAST32 "u"
#define PRIuLEAST16 "hu"
#define PRIuLEAST8 "hhu"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ struct basic_string {
constexpr bool starts_with(C ch) const noexcept;
constexpr bool starts_with(const C* s) const;

constexpr bool ends_with(std::basic_string_view<C, T> sv) const noexcept;
constexpr bool ends_with(C ch) const noexcept;
constexpr bool ends_with(const C* s) const;

_Type& operator[](size_type);
const _Type& operator[](size_type) const;

Expand Down Expand Up @@ -108,6 +112,10 @@ struct basic_string_view {
constexpr bool starts_with(C ch) const noexcept;
constexpr bool starts_with(const C* s) const;

constexpr bool ends_with(basic_string_view sv) const noexcept;
constexpr bool ends_with(C ch) const noexcept;
constexpr bool ends_with(const C* s) const;

constexpr int compare(basic_string_view sv) const noexcept;

static constexpr size_t npos = -1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// RUN: %check_clang_tidy -std=c++20 %s bugprone-bitwise-pointer-cast %t

void memcpy(void* to, void* dst, unsigned long long size)
{
// Dummy implementation for the purpose of the test
}

namespace std
{
template <typename To, typename From>
To bit_cast(From from)
{
// Dummy implementation for the purpose of the test
To to{};
return to;
}

using ::memcpy;
}

void pointer2pointer()
{
int x{};
float bad = *std::bit_cast<float*>(&x); // UB, but looks safe due to std::bit_cast
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use 'std::bit_cast' to cast between pointers [bugprone-bitwise-pointer-cast]
float good = std::bit_cast<float>(x); // Well-defined

using IntPtr = int*;
using FloatPtr = float*;
IntPtr x2{};
float bad2 = *std::bit_cast<FloatPtr>(x2);
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: do not use 'std::bit_cast' to cast between pointers [bugprone-bitwise-pointer-cast]
}

void pointer2pointer_memcpy()
{
int x{};
int* px{};
float y{};
float* py{};

memcpy(&py, &px, sizeof(px));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]
std::memcpy(&py, &px, sizeof(px));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]

std::memcpy(&y, &x, sizeof(x));
}

// Pointer-integer conversions are allowed by this check
void int2pointer()
{
unsigned long long addr{};
float* p = std::bit_cast<float*>(addr);
std::memcpy(&p, &addr, sizeof(addr));
}

void pointer2int()
{
float* p{};
auto addr = std::bit_cast<unsigned long long>(p);
std::memcpy(&addr, &p, sizeof(p));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %check_clang_tidy %s bugprone-bitwise-pointer-cast %t

void memcpy(void* to, void* dst, unsigned long long size)
{
// Dummy implementation for the purpose of the test
}

namespace std
{
using ::memcpy;
}

void pointer2pointer()
{
int x{};
int* px{};
float y{};
float* py{};

memcpy(&py, &px, sizeof(px));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]
std::memcpy(&py, &px, sizeof(px));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'memcpy' to cast between pointers [bugprone-bitwise-pointer-cast]

std::memcpy(&y, &x, sizeof(x));
}

// Pointer-integer conversions are allowed by this check
void int2pointer()
{
unsigned long long addr{};
float* p{};
std::memcpy(&p, &addr, sizeof(addr));
}

void pointer2int()
{
unsigned long long addr{};
float* p{};
std::memcpy(&addr, &p, sizeof(p));
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ template <typename T>
class CRTP {
public:
CRTP() = default;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:
// CHECK-FIXES: friend T;
};
Expand All @@ -39,7 +39,7 @@ template <typename T>
class CRTP {
public:
CRTP(int) {}
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public:
// CHECK-FIXES: friend T;
};
Expand All @@ -52,10 +52,10 @@ template <typename T>
class CRTP {
public:
CRTP(int) {}
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public:
CRTP(float) {}
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public:

// CHECK-FIXES: friend T;
Expand All @@ -70,13 +70,13 @@ template <typename T>
class CRTP {
protected:
CRTP(int) {}
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected constructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected:
CRTP() = default;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected constructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected:
CRTP(float) {}
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected constructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected:

// CHECK-FIXES: friend T;
Expand All @@ -101,7 +101,7 @@ namespace struct_default_ctor {
template <typename T>
struct CRTP {
CRTP() = default;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility]
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:
// CHECK-FIXES: friend T;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- \
// RUN: -config='{CheckOptions: { \
// RUN: bugprone-sizeof-expression.WarnOnOffsetDividedBySizeOf: false \
// RUN: }}'

typedef __SIZE_TYPE__ size_t;

void situational14(int *Buffer, size_t BufferSize) {
int *P = &Buffer[0];
while (P < Buffer + BufferSize / sizeof(*Buffer)) {
// NO-WARNING: This test opted out of "P +- N */ sizeof(...)" warnings.
++P;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -352,21 +352,30 @@ void good13(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
while (P < (Buffer + sizeof(Buffer) / sizeof(int))) {
while (P < Buffer + sizeof(Buffer) / sizeof(int)) {
// NO-WARNING: Calculating the element count of the buffer here, which is
// safe with this idiom (as long as the types don't change).
++P;
}

while (P < (Buffer + sizeof(Buffer) / sizeof(Buffer[0]))) {
while (P < Buffer + sizeof(Buffer) / sizeof(Buffer[0])) {
// NO-WARNING: Calculating the element count of the buffer here, which is
// safe with this idiom.
++P;
}

while (P < (Buffer + sizeof(Buffer) / sizeof(*P))) {
while (P < Buffer + sizeof(Buffer) / sizeof(*P)) {
// NO-WARNING: Calculating the element count of the buffer here, which is
// safe with this idiom.
++P;
}
}

void situational14(int *Buffer, size_t BufferSize) {
int *P = &Buffer[0];
while (P < Buffer + BufferSize / sizeof(*Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:21: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
++P;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,41 @@ void func_cpp_inc();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc'
// CHECK-FIXES: static void func_cpp_inc();

int* func_cpp_inc_return_ptr();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'func_cpp_inc_return_ptr'
// CHECK-FIXES: static int* func_cpp_inc_return_ptr();

const int* func_cpp_inc_return_const_ptr();
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 'func_cpp_inc_return_const_ptr'
// CHECK-FIXES: static const int* func_cpp_inc_return_const_ptr();

int const* func_cpp_inc_return_ptr_const();
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: function 'func_cpp_inc_return_ptr_const'
// CHECK-FIXES: static int const* func_cpp_inc_return_ptr_const();

int * const func_cpp_inc_return_const();
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: function 'func_cpp_inc_return_const'
// CHECK-FIXES: static int * const func_cpp_inc_return_const();

volatile const int* func_cpp_inc_return_volatile_const_ptr();
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: function 'func_cpp_inc_return_volatile_const_ptr'
// CHECK-FIXES: static volatile const int* func_cpp_inc_return_volatile_const_ptr();

[[nodiscard]] void func_nodiscard();
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: function 'func_nodiscard'
// CHECK-FIXES: {{\[\[nodiscard\]\]}} static void func_nodiscard();

#define NDS [[nodiscard]]
#define NNDS

NDS void func_nds();
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'func_nds'
// CHECK-FIXES: NDS static void func_nds();

NNDS void func_nnds();
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'func_nnds'
// CHECK-FIXES: NNDS static void func_nnds();

#include "func_cpp.inc"

void func_h_inc();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ T global_template;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: variable 'global_template'
// CHECK-FIXES: static T global_template;

int const* ptr_const_star;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'ptr_const_star'
// CHECK-FIXES: static int const* ptr_const_star;

const int* const_ptr_star;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'const_ptr_star'
// CHECK-FIXES: static const int* const_ptr_star;

const volatile int* const_volatile_ptr_star;
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: variable 'const_volatile_ptr_star'
// CHECK-FIXES: static const volatile int* const_volatile_ptr_star;

int gloabl_header;

extern int global_extern;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,9 @@ struct prefer_underscore_version_flip {
size_t find(const char *s, size_t pos = 0) const;
};

struct prefer_underscore_version_inherit : public string_like {
bool startsWith(const char *s) const;
};

void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
string_like sl, string_like_camel slc, prefer_underscore_version puv,
prefer_underscore_version_flip puvf,
prefer_underscore_version_inherit puvi) {
prefer_underscore_version_flip puvf) {
s.find("a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of find() == 0
// CHECK-FIXES: s.starts_with("a");
Expand Down Expand Up @@ -153,12 +148,6 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: puvf.starts_with("a");

// Here, the subclass has startsWith, the superclass has starts_with.
// We prefer the version from the subclass.
puvi.find("a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use startsWith
// CHECK-FIXES: puvi.startsWith("a");

s.compare(0, 1, "a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare() == 0
// CHECK-FIXES: s.starts_with("a");
Expand Down Expand Up @@ -208,6 +197,62 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
// CHECK-FIXES: !s.starts_with(sv);

s.compare(s.size() - 6, 6, "suffix") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with("suffix");

s.compare(s.size() - 6, strlen("abcdef"), "suffix") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with("suffix");

std::string suffix = "suffix";
s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

s.rfind("suffix") == s.size() - 6;
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with("suffix");

s.rfind("suffix") == s.size() - strlen("suffix");
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with("suffix");

s.rfind(suffix) == s.size() - suffix.size();
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

s.rfind(suffix, std::string::npos) == s.size() - suffix.size();
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

s.rfind(suffix) == (s.size() - suffix.size());
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

s.rfind(suffix, s.npos) == (s.size() - suffix.size());
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

s.rfind(suffix, s.npos) == (((s.size()) - (suffix.size())));
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

s.rfind(suffix) != s.size() - suffix.size();
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: !s.ends_with(suffix);

(s.size() - suffix.size()) == s.rfind(suffix);
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: s.ends_with(suffix);

struct S {
std::string s;
} t;
t.s.rfind(suffix) == (t.s.size() - suffix.size());
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
// CHECK-FIXES: t.s.ends_with(suffix);

// Expressions that don't trigger the check are here.
#define EQ(x, y) ((x) == (y))
EQ(s.find("a"), 0);
Expand All @@ -219,4 +264,5 @@ void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
STARTS_WITH_COMPARE(s, s) == 0;

s.compare(0, 1, "ab") == 0;
s.rfind(suffix, 1) == s.size() - suffix.size();
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// RUN: %check_clang_tidy \
// RUN: -std=c++20 %s modernize-use-std-format %t -- \
// RUN: -config="{CheckOptions: {StrictMode: true}}" \
// RUN: -- -isystem %clang_tidy_headers
// RUN: -- -isystem %clang_tidy_headers \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\""
// RUN: %check_clang_tidy \
// RUN: -std=c++20 %s modernize-use-std-format %t -- \
// RUN: -config="{CheckOptions: {StrictMode: false}}" \
// RUN: -- -isystem %clang_tidy_headers
// RUN: -- -isystem %clang_tidy_headers \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\""
#include <string>
// CHECK-FIXES: #include <format>
#include <inttypes.h>

namespace absl
{
Expand Down Expand Up @@ -102,18 +107,74 @@ std::string StrFormat_macros() {
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: std::format("Hello {}", 42);

// The format string is replaced even though it comes from a macro, this
// behaviour is required so that that <inttypes.h> macros are replaced.
#define FORMAT_STRING "Hello %s"
auto s2 = absl::StrFormat(FORMAT_STRING, 42);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: std::format("Hello {}", 42);

// Arguments that are macros aren't replaced with their value, even if they are rearranged.
#define VALUE 3.14159265358979323846
#define WIDTH 10
#define PRECISION 4
auto s3 = absl::StrFormat("Hello %*.*f", WIDTH, PRECISION, VALUE);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: std::format("Hello {:{}.{}f}", VALUE, WIDTH, PRECISION);

const uint64_t u64 = 42;
const uint32_t u32 = 32;
std::string s;

auto s4 = absl::StrFormat("Replaceable macro at end %" PRIu64, u64);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: std::format("Replaceable macro at end {}", u64);

auto s5 = absl::StrFormat("Replaceable macros in middle %" PRIu64 " %" PRIu32 "\n", u64, u32);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: std::format("Replaceable macros in middle {} {}\n", u64, u32);

// These need PRI and __PRI prefixes so that the check get as far as looking for
// where the macro comes from.
#define PRI_FMT_MACRO "s"
#define __PRI_FMT_MACRO "s"

auto s6 = absl::StrFormat("Unreplaceable macro at end %" PRI_FMT_MACRO, s.c_str());
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-format]

auto s7 = absl::StrFormat(__PRI_FMT_MACRO " Unreplaceable macro at beginning %s", s);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro '__PRI_FMT_MACRO' [modernize-use-std-format]

auto s8 = absl::StrFormat("Unreplacemable macro %" PRI_FMT_MACRO " in the middle", s);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-format]

auto s9 = absl::StrFormat("First macro is replaceable %" PRIu64 " but second one is not %" __PRI_FMT_MACRO, u64, s);
// CHECK-MESSAGES: [[@LINE-1]]:13: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro '__PRI_FMT_MACRO' [modernize-use-std-format]

// Needs a PRI prefix so that we get as far as looking for where the macro comes from
auto s10 = absl::StrFormat(" macro from command line %" PRI_CMDLINE_MACRO, s);
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro 'PRI_CMDLINE_MACRO' [modernize-use-std-format]

// Needs a __PRI prefix so that we get as far as looking for where the macro comes from
auto s11 = absl::StrFormat(" macro from command line %" __PRI_CMDLINE_MACRO, s);
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro '__PRI_CMDLINE_MACRO' [modernize-use-std-format]

// We ought to be able to fix this since the macro surrounds the whole call
// and therefore can't change the format string independently. This is
// required to be able to fix calls inside Catch2 macros for example.
#define SURROUND_ALL(x) x
auto s12 = SURROUND_ALL(absl::StrFormat("Macro surrounding entire invocation %" PRIu64, u64));
// CHECK-MESSAGES: [[@LINE-1]]:27: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: auto s12 = SURROUND_ALL(std::format("Macro surrounding entire invocation {}", u64));

// But having that surrounding macro shouldn't stop us ignoring an
// unreplaceable macro elsewhere.
auto s13 = SURROUND_ALL(absl::StrFormat("Macro surrounding entire invocation with unreplaceable macro %" PRI_FMT_MACRO, s));
// CHECK-MESSAGES: [[@LINE-1]]:27: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-format]

// At the moment at least the check will replace occurrences where the
// function name is the result of expanding a macro.
#define SURROUND_FUNCTION_NAME(x) absl:: x
auto s14 = SURROUND_FUNCTION_NAME(StrFormat)("Hello %d", 4442);
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: use 'std::format' instead of 'StrFormat' [modernize-use-std-format]
// CHECK-FIXES: auto s14 = std::format("Hello {}", 4442);

// We can't safely fix occurrences where the macro may affect the format
// string differently in different builds.
#define SURROUND_FORMAT(x) "!" x
auto s15 = absl::StrFormat(SURROUND_FORMAT("Hello %d"), 4443);
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: unable to use 'std::format' instead of 'StrFormat' because format string contains unreplaceable macro 'SURROUND_FORMAT' [modernize-use-std-format]
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// RUN: %check_clang_tidy -check-suffixes=,STRICT \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \
// RUN: -config="{CheckOptions: {StrictMode: true}}" \
// RUN: -- -isystem %clang_tidy_headers -fexceptions
// RUN: -- -isystem %clang_tidy_headers -fexceptions \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\""
// RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \
// RUN: -std=c++23 %s modernize-use-std-print %t -- \
// RUN: -config="{CheckOptions: {StrictMode: false}}" \
// RUN: -- -isystem %clang_tidy_headers -fexceptions
// RUN: -- -isystem %clang_tidy_headers -fexceptions \
// RUN: -DPRI_CMDLINE_MACRO="\"s\"" \
// RUN: -D__PRI_CMDLINE_MACRO="\"s\""
#include <cstddef>
#include <cstdint>
#include <cstdio>
Expand Down Expand Up @@ -1571,3 +1575,68 @@ void p(S s1, S *s2)
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
// CHECK-FIXES: std::print("Not std::string {} {}", s1.data(), s2->data());
}

// These need PRI and __PRI prefixes so that the check gets as far as looking
// for where the macro comes from.
#define PRI_FMT_MACRO "s"
#define __PRI_FMT_MACRO "s"

void macro_expansion(const char *s)
{
const uint64_t u64 = 42;
const uint32_t u32 = 32;

printf("Replaceable macro at end %" PRIu64, u64);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
// CHECK-FIXES: std::print("Replaceable macro at end {}", u64);

printf("Replaceable macros in middle %" PRIu64 " %" PRIu32 "\n", u64, u32);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
// CHECK-FIXES: std::println("Replaceable macros in middle {} {}", u64, u32);

printf("Unreplaceable macro at end %" PRI_FMT_MACRO, s);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-print]

printf(PRI_FMT_MACRO " Unreplaceable macro at beginning %s", s);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-print]

printf("Unreplacemable macro %" __PRI_FMT_MACRO " in the middle", s);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro '__PRI_FMT_MACRO' [modernize-use-std-print]

printf("First macro is replaceable %" PRIu64 " but second one is not %" PRI_FMT_MACRO, u64, s);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-print]

// Needs a PRI prefix so that we get as far as looking for where the macro comes from
printf(" macro from command line %" PRI_CMDLINE_MACRO, s);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro 'PRI_CMDLINE_MACRO' [modernize-use-std-print]

// Needs a __PRI prefix so that we get as far as looking for where the macro comes from
printf(" macro from command line %" __PRI_CMDLINE_MACRO, s);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro '__PRI_CMDLINE_MACRO' [modernize-use-std-print]

// We ought to be able to fix this since the macro surrounds the whole call
// and therefore can't change the format string independently. This is
// required to be able to fix calls inside Catch2 macros for example.
#define SURROUND_ALL(x) x
SURROUND_ALL(printf("Macro surrounding entire invocation %" PRIu64, u64));
// CHECK-MESSAGES: [[@LINE-1]]:16: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
// CHECK-FIXES: SURROUND_ALL(std::print("Macro surrounding entire invocation {}", u64));

// But having that surrounding macro shouldn't stop us ignoring an
// unreplaceable macro elsewhere.
SURROUND_ALL(printf("Macro surrounding entire invocation with unreplaceable macro %" PRI_FMT_MACRO, s));
// CHECK-MESSAGES: [[@LINE-1]]:16: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro 'PRI_FMT_MACRO' [modernize-use-std-print]

// At the moment at least the check will replace occurrences where the
// function name is the result of expanding a macro.
#define SURROUND_FUNCTION_NAME(x) x
SURROUND_FUNCTION_NAME(printf)("Hello %d", 4442);
// CHECK-MESSAGES: [[@LINE-1]]:26: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
// CHECK-FIXES: std::print("Hello {}", 4442);

// We can't safely fix occurrences where the macro may affect the format
// string differently in different builds.
#define SURROUND_FORMAT(x) "!" x
printf(SURROUND_FORMAT("Hello %d"), 4443);
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::print' instead of 'printf' because format string contains unreplaceable macro 'SURROUND_FORMAT' [modernize-use-std-print]
}
Original file line number Diff line number Diff line change
Expand Up @@ -546,3 +546,17 @@ void testAlsoNonMoveable() {
}

} // namespace issue_62550

namespace GH111450 {
struct Status;

struct Error {
Error(const Status& S);
};

struct Result {
Error E;
Result(Status&& S) : E(std::move(S)) {}
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
};
} // namespace GH111450
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// RUN: %check_clang_tidy %s portability-template-virtual-member-function %t
namespace UninstantiatedVirtualMember {
template<typename T>
struct CrossPlatformError {
virtual ~CrossPlatformError() = default;

static void used() {}

// CHECK-MESSAGES: [[#@LINE+1]]:18: warning: unspecified virtual member function instantiation
virtual void unused() {
T MSVCError = this;
};
};

int main() {
// CHECK-MESSAGES: [[#@LINE+1]]:5: note: template instantiated here
CrossPlatformError<int>::used();
return 0;
}
} // namespace UninstantiatedVirtualMember

namespace UninstantiatedVirtualMembers {
template<typename T>
struct CrossPlatformError {
virtual ~CrossPlatformError() = default;

static void used() {}

// CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
// CHECK-MESSAGES: [[#@LINE+13]]:5: note: template instantiated here
virtual void unused() {
T MSVCError = this;
};

// CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
// CHECK-MESSAGES: [[#@LINE+7]]:5: note: template instantiated here
virtual void unused2() {
T MSVCError = this;
};
};

int main() {
CrossPlatformError<int>::used();
return 0;
}
} // namespace UninstantiatedVirtualMembers

namespace UninstantiatedVirtualDestructor {
template<typename T>
struct CrossPlatformError {
// CHECK-MESSAGES: [[#@LINE+2]]:13: warning: unspecified virtual member function instantiation
// CHECK-MESSAGES: [[#@LINE+9]]:5: note: template instantiated here
virtual ~CrossPlatformError() {
T MSVCError = this;
};

static void used() {}
};

int main() {
CrossPlatformError<int>::used();
return 0;
}
} // namespace UninstantiatedVirtualDestructor

namespace MultipleImplicitInstantiations {
template<typename T>
struct CrossPlatformError {
virtual ~CrossPlatformError() = default;

static void used() {}

// CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
// CHECK-MESSAGES: [[#@LINE+7]]:5: note: template instantiated here
virtual void unused() {
T MSVCError = this;
};
};

int main() {
CrossPlatformError<int>::used();
CrossPlatformError<float>::used();
CrossPlatformError<long>::used();
return 0;
}
} // namespace MultipleImplicitInstantiations

namespace SomeImplicitInstantiationError {
template <typename T> struct CrossPlatformError {
virtual ~CrossPlatformError() = default;

static void used() {}

// CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
// CHECK-MESSAGES: [[#@LINE+5]]:5: note: template instantiated here
virtual void unused(){};
};

int main() {
CrossPlatformError<int>::used();
CrossPlatformError<float> NoError;
return 0;
}
} // namespace SomeImplicitInstantiationError

namespace InstantiatedVirtualMemberFunctions {
template<typename T>
struct NoError {
virtual ~NoError() {};
virtual void unused() {};
virtual void unused2() {};
virtual void unused3() {};
};

int main() {
NoError<int> Ne;
return 0;
}
} // namespace InstantiatedVirtualMemberFunctions

namespace UninstantiatedNonVirtualMemberFunctions {
template<typename T>
struct NoError {
static void used() {};
void unused() {};
void unused2() {};
void unused3() {};
};

int main() {
NoError<int>::used();
return 0;
}
} // namespace UninstantiatedNonVirtualMemberFunctions

namespace PartialSpecializationError {
template<typename T, typename U>
struct CrossPlatformError {};

template<typename U>
struct CrossPlatformError<int, U>{
virtual ~CrossPlatformError() = default;

static void used() {}

// CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
// CHECK-MESSAGES: [[#@LINE+7]]:5: note: template instantiated here
virtual void unused() {
U MSVCError = this;
};
};

int main() {
CrossPlatformError<int, float>::used();
return 0;
}
} // namespace PartialSpecializationError

namespace PartialSpecializationNoInstantiation {
template<typename T, typename U>
struct NoInstantiation {};

template<typename U>
struct NoInstantiation<int, U>{
virtual ~NoInstantiation() = default;

static void used() {}

virtual void unused() {
U MSVCError = this;
};
};
} // namespace PartialSpecializationNoInstantiation
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ inline namespace InlineNamespace {
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for inline namespace 'InlineNamespace'
// CHECK-FIXES: {{^}}inline namespace inline_namespace {{{$}}

namespace FOO_ALIAS = FOO_NS;
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for namespace 'FOO_ALIAS' [readability-identifier-naming]
// CHECK-FIXES: {{^}}namespace foo_alias = FOO_NS;{{$}}

SYSTEM_NS::structure g_s1;
// NO warnings or fixes expected as SYSTEM_NS and structure are declared in a header file

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not clang-tidy --invalid-arg 2>&1 | FileCheck %s

// CHECK: error: clang-tidy{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: 'clang-tidy{{(\.exe)?}} --help'
// CHECK: error: clang-tidy{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: '{{.*}}clang-tidy{{(\.exe)?}} --help'
// CHECK-NEXT: clang-tidy{{(\.exe)?}}: Did you mean '--extra-arg'?
44 changes: 20 additions & 24 deletions clang/CodeOwners.rst → clang/Maintainers.rst
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
=================
Clang Code Owners
Clang Maintainers
=================

This file is a list of the
`code owners <https://llvm.org/docs/DeveloperPolicy.html#code-owners>`_ for
`maintainers <https://llvm.org/docs/DeveloperPolicy.html#maintainers>`_ for
Clang.

.. contents::
:depth: 2
:local:

Current Code Owners
===================
The following people are the active code owners for the project. Please reach
Active Maintainers
==================
The following people are the active maintainers for the project. Please reach
out to them for code reviews, questions about their area of expertise, or other
assistance.

All parts of Clang not covered by someone else
----------------------------------------------
Lead Maintainer
---------------
| Aaron Ballman
| aaron\@aaronballman.com (email), aaron.ballman (Phabricator), AaronBallman (GitHub), AaronBallman (Discourse), aaronballman (Discord), AaronBallman (IRC)

Contained Components
--------------------
These code owners are responsible for particular high-level components within
These maintainers are responsible for particular high-level components within
Clang that are typically contained to one area of the compiler.

AST matchers
~~~~~~~~~~~~
| Manuel Klimek
| klimek\@google.com (email), klimek (Phabricator), r4nt (GitHub)
| Aaron Ballman
| aaron\@aaronballman.com (email), aaron.ballman (Phabricator), AaronBallman (GitHub), AaronBallman (Discourse), aaronballman (Discord), AaronBallman (IRC)

Clang LLVM IR generation
Expand Down Expand Up @@ -60,7 +60,7 @@ Analysis & CFG
Experimental new constant interpreter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Timm Bäder
| tbaeder\@redhat.com (email), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord)
| tbaeder\@redhat.com (em), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord)

Modules & serialization
Expand Down Expand Up @@ -125,14 +125,9 @@ Driver parts not covered by someone else

Tools
-----
These code owners are responsible for user-facing tools under the Clang
These maintainers are responsible for user-facing tools under the Clang
umbrella or components used to support such tools.

Tooling library
~~~~~~~~~~~~~~~
| Manuel Klimek
| klimek\@google.com (email), klimek (Phabricator), r4nt (GitHub)

clang-format
~~~~~~~~~~~~
Expand Down Expand Up @@ -255,19 +250,20 @@ SYCL conformance
| alexey.bader\@intel.com (email), bader (Phabricator), bader (GitHub)

Former Code Owners
==================
The following people have graciously spent time performing code ownership
Inactive Maintainers
====================
The following people have graciously spent time performing maintainership
responsibilities but are no longer active in that role. Thank you for all your
help with the success of the project!

Emeritus owners
---------------
Emeritus Lead Maintainers
-------------------------
| Doug Gregor (dgregor\@apple.com)
| Richard Smith (richard\@metafoo.co.uk)

Former component owners
-----------------------
Inactive component maintainers
------------------------------
| Chandler Carruth (chandlerc\@gmail.com, chandlerc\@google.com) -- CMake, library layering
| Devin Coughlin (dcoughlin\@apple.com) -- Clang static analyzer
| Manuel Klimek (klimek\@google.com (email), klimek (Phabricator), r4nt (GitHub)) -- Tooling, AST matchers
13 changes: 13 additions & 0 deletions clang/bindings/python/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ if(${LLVM_NATIVE_ARCH} MATCHES "^(AArch64|Hexagon|Sparc|SystemZ)$")
set(RUN_PYTHON_TESTS FALSE)
endif()

# Tests will fail if cross-compiling for a different target, as tests will try
# to use the host Python3_EXECUTABLE and make FFI calls to functions in target
# libraries.
if(CMAKE_CROSSCOMPILING)
# FIXME: Consider a solution that allows better control over these tests in
# a crosscompiling scenario. e.g. registering them with lit to allow them to
# be explicitly skipped via appropriate LIT_ARGS, or adding a mechanism to
# allow specifying a python interpreter compiled for the target that could
# be executed using qemu-user.
message(WARNING "check-clang-python not added to check-all as these tests fail in a cross-build setup")
set(RUN_PYTHON_TESTS FALSE)
endif()

if(RUN_PYTHON_TESTS)
set_property(GLOBAL APPEND PROPERTY
LLVM_ALL_ADDITIONAL_TEST_TARGETS check-clang-python)
Expand Down
1 change: 0 additions & 1 deletion clang/cmake/caches/Android.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ set(CLANG_VENDOR Android CACHE STRING "")

set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "")

set(HAVE_LIBCXXABI ON CACHE BOOL "")
set(LLVM_BUILD_TOOLS OFF CACHE BOOL "")
set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(LLVM_ENABLE_THREADS OFF CACHE BOOL "")
Expand Down
2 changes: 2 additions & 0 deletions clang/cmake/caches/Fuchsia-stage2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi)
set(RUNTIMES_${target}_LIBCXX_CXX_ABI none CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_STATIC ON CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_SHARED_OUTPUT_NAME "c++-shared" CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_LIBC "llvm-libc" CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_FILESYSTEM OFF CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_RANDOM_DEVICE OFF CACHE BOOL "")
Expand Down Expand Up @@ -396,6 +397,7 @@ foreach(target riscv32-unknown-elf)
set(RUNTIMES_${target}_LIBCXX_CXX_ABI none CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_STATIC ON CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_SHARED_OUTPUT_NAME "c++-shared" CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_LIBC "llvm-libc" CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_FILESYSTEM OFF CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_RANDOM_DEVICE OFF CACHE BOOL "")
Expand Down
11 changes: 11 additions & 0 deletions clang/cmake/modules/AddClang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,17 @@ macro(add_clang_library name)
endif()
llvm_add_library(${name} ${LIBTYPE} ${ARG_UNPARSED_ARGUMENTS} ${srcs})

if(MSVC AND NOT CLANG_LINK_CLANG_DYLIB)
# Make sure all consumers also turn off visibility macros so there not trying to dllimport symbols.
target_compile_definitions(${name} PUBLIC CLANG_BUILD_STATIC)
if(TARGET "obj.${name}")
target_compile_definitions("obj.${name}" PUBLIC CLANG_BUILD_STATIC)
endif()
elseif(NOT ARG_SHARED AND NOT ARG_STATIC)
# Clang component libraries linked in to clang-cpp are declared without SHARED or STATIC
target_compile_definitions("obj.${name}" PUBLIC CLANG_EXPORTS)
endif()

set(libs ${name})
if(ARG_SHARED AND ARG_STATIC)
list(APPEND libs ${name}_static)
Expand Down
8 changes: 8 additions & 0 deletions clang/docs/AddressSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,14 @@ Limitations
usually expected.
* Static linking of executables is not supported.

Security Considerations
=======================

AddressSanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
AddressSanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.

Supported Platforms
===================

Expand Down
2 changes: 1 addition & 1 deletion clang/docs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ if (LLVM_ENABLE_SPHINX)
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}"

COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/../CodeOwners.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/../Maintainers.rst"
"${CMAKE_CURRENT_BINARY_DIR}"
)

Expand Down
259 changes: 210 additions & 49 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ the configuration (without a prefix: ``Auto``).
.. _AlignArrayOfStructures:

**AlignArrayOfStructures** (``ArrayInitializerAlignmentStyle``) :versionbadge:`clang-format 13` :ref:`¶ <AlignArrayOfStructures>`
if not ``None``, when using initialization for an array of structs
If not ``None``, when using initialization for an array of structs
aligns the fields into columns.


Expand Down Expand Up @@ -307,11 +307,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -392,6 +393,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -449,11 +465,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -534,6 +551,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -591,11 +623,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -676,6 +709,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -734,11 +782,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -819,6 +868,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -996,11 +1060,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1081,6 +1146,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -1136,11 +1216,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1221,6 +1302,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -1276,11 +1372,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1361,6 +1458,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -5294,22 +5406,46 @@ the configuration (without a prefix: ``Auto``).

.. _ReflowComments:

**ReflowComments** (``Boolean``) :versionbadge:`clang-format 3.8` :ref:`¶ <ReflowComments>`
If ``true``, clang-format will attempt to re-flow comments. That is it
will touch a comment and *reflow* long comments into new lines, trying to
obey the ``ColumnLimit``.
**ReflowComments** (``ReflowCommentsStyle``) :versionbadge:`clang-format 3.8` :ref:`¶ <ReflowComments>`
Comment reformatting style.

.. code-block:: c++
Possible values:

* ``RCS_Never`` (in configuration: ``Never``)
Leave comments untouched.

.. code-block:: c++

// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
/* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
* and a misaligned second line */
* ``RCS_IndentOnly`` (in configuration: ``IndentOnly``)
Only apply indentation rules, moving comments left or right, without
changing formatting inside the comments.

.. code-block:: c++

// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */
/* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
* and a misaligned second line */
* ``RCS_Always`` (in configuration: ``Always``)
Apply indentation rules and reflow long comments into new lines, trying
to obey the ``ColumnLimit``.

.. code-block:: c++

// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
// information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information */
/* third veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information and a misaligned second line */
false:
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */

true:
// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
// information
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
* information */

.. _RemoveBracesLLVM:

Expand Down Expand Up @@ -5369,6 +5505,31 @@ the configuration (without a prefix: ``Auto``).
}
}

.. _RemoveEmptyLinesInUnwrappedLines:

**RemoveEmptyLinesInUnwrappedLines** (``Boolean``) :versionbadge:`clang-format 20` :ref:`¶ <RemoveEmptyLinesInUnwrappedLines>`
Remove empty lines within unwrapped lines.

.. code-block:: c++

false: true:

int c vs. int c = a + b;

= a + b;

enum : unsigned vs. enum : unsigned {
AA = 0,
{ BB
AA = 0, } myEnum;
BB
} myEnum;

while ( vs. while (true) {
}
true) {
}

.. _RemoveParentheses:

**RemoveParentheses** (``RemoveParenthesesStyle``) :versionbadge:`clang-format 17` :ref:`¶ <RemoveParentheses>`
Expand Down
17 changes: 12 additions & 5 deletions clang/docs/ClangPlugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,6 @@ The members of ``ParsedAttrInfo`` that a plugin attribute must define are:
attribute, each of which consists of an attribute syntax and how the
attribute name is spelled for that syntax. If the syntax allows a scope then
the spelling must be "scope::attr" if a scope is present or "::attr" if not.
* ``handleDeclAttribute``, which is the function that applies the attribute to
a declaration. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an ``Attr`` to the
``Decl``. It returns either ``AttributeApplied``, to indicate that the
attribute was successfully applied, or ``AttributeNotApplied`` if it wasn't.

The members of ``ParsedAttrInfo`` that may need to be defined, depending on the
attribute, are:
Expand All @@ -105,6 +100,18 @@ attribute, are:
arguments to the attribute.
* ``diagAppertainsToDecl``, which checks if the attribute has been used on the
right kind of declaration and issues a diagnostic if not.
* ``handleDeclAttribute``, which is the function that applies the attribute to
a declaration. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an ``Attr`` to the
``Decl``. It returns either ``AttributeApplied``, to indicate that the
attribute was successfully applied, or ``AttributeNotApplied`` if it wasn't.
* ``diagAppertainsToStmt``, which checks if the attribute has been used on the
right kind of statement and issues a diagnostic if not.
* ``handleStmtAttribute``, which is the function that applies the attribute to
a statement. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an ``Attr`` to the
``Stmt``. It returns either ``AttributeApplied``, to indicate that the
attribute was successfully applied, or ``AttributeNotApplied`` if it wasn't.
* ``diagLangOpts``, which checks if the attribute is permitted for the current
language mode and issues a diagnostic if not.
* ``existsInTarget``, which checks if the attribute is permitted for the given
Expand Down
1 change: 0 additions & 1 deletion clang/docs/CodeOwners.rst

This file was deleted.

8 changes: 8 additions & 0 deletions clang/docs/HardwareAssistedAddressSanitizerDesign.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ than that of AddressSanitizer:
`1/TG` extra memory for the shadow
and some overhead due to `TG`-aligning all objects.

Security Considerations
=======================

HWASAN is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
HWASAN's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.

Supported architectures
=======================
HWASAN relies on `Address Tagging`_ which is only available on AArch64.
Expand Down
23 changes: 23 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5883,3 +5883,26 @@ specify the starting offset to begin embedding from. The resources is treated
as being empty if the specified offset is larger than the number of bytes in
the resource. The offset will be applied *before* any ``limit`` parameters are
applied.
Union and aggregate initialization in C
=======================================
In C23 (N2900), when an object is initialized from initializer ``= {}``, all
elements of arrays, all members of structs, and the first members of unions are
empty-initialized recursively. In addition, all padding bits are initialized to
zero.
Clang guarantees the following behaviors:
* ``1:`` Clang supports initializer ``= {}`` mentioned above in all C
standards.
* ``2:`` When unions are initialized from initializer ``= {}``, bytes outside
of the first members of unions are also initialized to zero.
* ``3:`` When unions, structures and arrays are initialized from initializer
``= { initializer-list }``, all members not explicitly initialized in
the initializer list are empty-initialized recursively. In addition, all
padding bits are initialized to zero.
Currently, the above extension only applies to C source code, not C++.
8 changes: 8 additions & 0 deletions clang/docs/LeakSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ To use LeakSanitizer in stand-alone mode, link your program with
link step, so that it would link in proper LeakSanitizer run-time library
into the final executable.

Security Considerations
=======================

LeakSanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
LeakSanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.

Supported Platforms
===================

Expand Down
4 changes: 2 additions & 2 deletions clang/docs/LibASTMatchersReference.html
Original file line number Diff line number Diff line change
Expand Up @@ -7239,9 +7239,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
cxxMemberCallExpr(onImplicitObjectArgument(hasType(
cxxRecordDecl(hasName("Y")))))
matches `y.m()`, `x.m()` and (g()).m(), but not `x.g()`.
matches `y.m()`, `x.m()` and (`g()).m()`, but not `x.g()`).
cxxMemberCallExpr(on(callExpr()))
does not match `(g()).m()`, because the parens are not ignored.
only matches `(g()).m()` (the parens are ignored).

FIXME: Overload to allow directly matching types?
</pre></td></tr>
Expand Down
1 change: 1 addition & 0 deletions clang/docs/Maintainers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: ../Maintainers.rst
8 changes: 8 additions & 0 deletions clang/docs/MemorySanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ uninstrumented libc. For example, the authors were able to bootstrap
MemorySanitizer-instrumented Clang compiler by linking it with
self-built instrumented libc++ (as a replacement for libstdc++).

Security Considerations
=======================

MemorySanitizer is a bug detection tool and its runtime is not meant to be
linked against production executables. While it may be useful for testing,
MemorySanitizer's runtime was not developed with security-sensitive
constraints in mind and may compromise the security of the resulting executable.

Supported Platforms
===================

Expand Down
4 changes: 2 additions & 2 deletions clang/docs/Multilib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ For a more comprehensive example see
# If there is no multilib available for a particular set of flags, and the
# other multilibs are not adequate fallbacks, then you can define a variant
# record with a FatalError key in place of the Dir key.
- FatalError: this multilib collection has no hard-float ABI support
# record with an Error key in place of the Dir key.
- Error: this multilib collection has no hard-float ABI support
Flags: [--target=thumbv7m-none-eabi, -mfloat-abi=hard]
Expand Down
80 changes: 60 additions & 20 deletions clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Introduction
============
RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and C++
projects. RTSan can be used to detect real-time violations, i.e. calls to methods
that are not safe for use in functions with deterministic runtime requirements.
that are not safe for use in functions with deterministic run time requirements.
RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
to be a real-time function. If RTSan detects a call to ``malloc``, ``free``,
``pthread_mutex_lock``, or anything else that could have a non-deterministic
Expand Down Expand Up @@ -58,31 +58,71 @@ code.
return 0;
}
# Compile and link
% clang++ -fsanitize=realtime -g example_realtime_violation.cpp
% clang++ -fsanitize=realtime example_realtime_violation.cpp
If a real-time safety violation is detected in a ``[[clang::nonblocking]]``
context, or any function invoked by that function, the program will exit with a
non-zero exit code.

.. code-block:: console
% clang++ -fsanitize=realtime -g example_realtime_violation.cpp
% clang++ -fsanitize=realtime example_realtime_violation.cpp
% ./a.out
Real-time violation: intercepted call to real-time unsafe function `malloc` in real-time context! Stack trace:
#0 0x000102893034 in __rtsan::PrintStackTrace() rtsan_stack.cpp:45
#1 0x000102892e64 in __rtsan::Context::ExpectNotRealtime(char const*) rtsan_context.cpp:78
#2 0x00010289397c in malloc rtsan_interceptors.cpp:286
#3 0x000195bd7bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
#4 0x5c7f00010230f07c (<unknown module>)
#5 0x00010230f058 in std::__1::__libcpp_allocate[abi:ue170006](unsigned long, unsigned long) new:324
#6 0x00010230effc in std::__1::allocator<float>::allocate[abi:ue170006](unsigned long) allocator.h:114
... snip ...
#10 0x00010230e4bc in std::__1::vector<float, std::__1::allocator<float>>::__append(unsigned long) vector:1162
#11 0x00010230dcdc in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long) vector:1981
#12 0x00010230dc28 in violation() main.cpp:5
#13 0x00010230dd64 in main main.cpp:9
#14 0x0001958960dc (<unknown module>)
#15 0x2f557ffffffffffc (<unknown module>)
==76290==ERROR: RealtimeSanitizer: unsafe-library-call
Intercepted call to real-time unsafe function `malloc` in real-time context!
#0 0x000102a7b884 in malloc rtsan_interceptors.cpp:426
#1 0x00019c326bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
#2 0xa30d0001024f79a8 (<unknown module>)
#3 0x0001024f794c in std::__1::__libcpp_allocate[abi:ne200000](unsigned long, unsigned long)+0x44
#4 0x0001024f78c4 in std::__1::allocator<float>::allocate[abi:ne200000](unsigned long)+0x44
... snip ...
#9 0x0001024f6868 in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long)+0x48
#10 0x0001024f67b4 in violation()+0x24
#11 0x0001024f68f0 in main+0x18 (a.out:arm64+0x1000028f0)
#12 0x00019bfe3150 (<unknown module>)
#13 0xed5efffffffffffc (<unknown module>)
Blocking functions
------------------

Calls to system library functions such as ``malloc`` are automatically caught by
RealtimeSanitizer. Real-time programmers may also write their own blocking
(real-time unsafe) functions that they wish RealtimeSanitizer to be aware of.
RealtimeSanitizer will raise an error at run time if any function attributed
with ``[[clang::blocking]]`` is called in a ``[[clang::nonblocking]]`` context.

.. code-block:: console
$ cat example_blocking_violation.cpp
#include <atomic>
#include <thread>
std::atomic<bool> has_permission{false};
int wait_for_permission() [[clang::blocking]] {
while (has_permission.load() == false)
std::this_thread::yield();
return 0;
}
int real_time_function() [[clang::nonblocking]] {
return wait_for_permission();
}
int main() {
return real_time_function();
}
$ clang++ -fsanitize=realtime example_blocking_violation.cpp && ./a.out
==76131==ERROR: RealtimeSanitizer: blocking-call
Call to blocking function `wait_for_permission()` in real-time context!
#0 0x0001000c3db0 in wait_for_permission()+0x10 (a.out:arm64+0x100003db0)
#1 0x0001000c3e3c in real_time_function()+0x10 (a.out:arm64+0x100003e3c)
#2 0x0001000c3e68 in main+0x10 (a.out:arm64+0x100003e68)
#3 0x00019bfe3150 (<unknown module>)
#4 0x5a27fffffffffffc (<unknown module>)
Run-time flags
--------------
Expand Down Expand Up @@ -159,7 +199,7 @@ Disabling

In some circumstances, you may want to suppress error reporting in a specific scope.

In C++, this is achieved via ``__rtsan::ScopedDisabler``. Within the scope where the ``ScopedDisabler`` object is instantiated, all sanitizer error reports are suppressed. This suppression applies to the current scope as well as all invoked functions, including any functions called transitively.
In C++, this is achieved via ``__rtsan::ScopedDisabler``. Within the scope where the ``ScopedDisabler`` object is instantiated, all sanitizer error reports are suppressed. This suppression applies to the current scope as well as all invoked functions, including any functions called transitively.

.. code-block:: c++

Expand All @@ -174,7 +214,7 @@ In C++, this is achieved via ``__rtsan::ScopedDisabler``. Within the scope wher

If RealtimeSanitizer is not enabled at compile time (i.e., the code is not compiled with the ``-fsanitize=realtime`` flag), the ``ScopedDisabler`` is compiled as a no-op.

In C, you can use the ``__rtsan_disable()`` and ``rtsan_enable()`` functions to manually disable and re-enable RealtimeSanitizer checks.
In C, you can use the ``__rtsan_disable()`` and ``rtsan_enable()`` functions to manually disable and re-enable RealtimeSanitizer checks.

.. code-block:: c++

Expand Down
113 changes: 101 additions & 12 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,40 @@ C++ Specific Potentially Breaking Changes
// Was error, now evaluates to false.
constexpr bool b = f() == g();
- Clang will now correctly not consider pointers to non classes for covariance
and disallow changing return type to a type that doesn't have the same or less cv-qualifications.

.. code-block:: c++

struct A {
virtual const int *f() const;
virtual const std::string *g() const;
};
struct B : A {
// Return type has less cv-qualification but doesn't point to a class.
// Error will be generated.
int *f() const override;
// Return type doesn't have more cv-qualification also not the same or
// less cv-qualification.
// Error will be generated.
volatile std::string *g() const override;
};
- The warning ``-Wdeprecated-literal-operator`` is now on by default, as this is
something that WG21 has shown interest in removing from the language. The
result is that anyone who is compiling with ``-Werror`` should see this
diagnostic. To fix this diagnostic, simply removing the space character from
between the ``operator""`` and the user defined literal name will make the
source no longer deprecated. This is consistent with `CWG2521 <https://cplusplus.github.io/CWG/issues/2521.html>_`.

.. code-block:: c++

// Now diagnoses by default.
unsigned operator"" _udl_name(unsigned long long);
// Fixed version:
unsigned operator""_udl_name(unsigned long long);

ABI Changes in This Version
---------------------------

Expand Down Expand Up @@ -171,13 +205,12 @@ C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- Removed the restriction to literal types in constexpr functions in C++23 mode.

- Extend lifetime of temporaries in mem-default-init for P2718R0. Clang now fully
supports `P2718R0 Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_.

C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^

C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- The implementation of the relaxed template template argument matching rules is
more complete and reliable, and should provide more accurate diagnostics.

Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -216,6 +249,10 @@ Resolutions to C++ Defect Reports
- Clang now allows trailing requires clause on explicit deduction guides.
(`CWG2707: Deduction guides cannot have a trailing requires-clause <https://cplusplus.github.io/CWG/issues/2707.html>`_).

- Clang now diagnoses a space in the first production of a ``literal-operator-id``
by default.
(`CWG2521: User-defined literals and reserved identifiers <https://cplusplus.github.io/CWG/issues/2521.html>`_).

C Language Changes
------------------

Expand All @@ -233,6 +270,9 @@ Non-comprehensive list of changes in this release
- The floating point comparison builtins (``__builtin_isgreater``,
``__builtin_isgreaterequal``, ``__builtin_isless``, etc.) and
``__builtin_signbit`` can now be used in constant expressions.
- Plugins can now define custom attributes that apply to statements
as well as declarations.
- ``__builtin_abs`` function can now be used in constant expressions.

New Compiler Flags
------------------
Expand Down Expand Up @@ -335,10 +375,6 @@ Improvements to Clang's diagnostics

- Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391.

- Clang now properly explains the reason a template template argument failed to
match a template template parameter, in terms of the C++17 relaxed matching rules
instead of the old ones.

- Don't emit duplicated dangling diagnostics. (#GH93386).

- Improved diagnostic when trying to befriend a concept. (#GH45182).
Expand Down Expand Up @@ -378,6 +414,16 @@ Improvements to Clang's diagnostics

- Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638).

- Clang now omits warnings for extra parentheses in fold expressions with single expansion (#GH101863).

- The warning for an unsupported type for a named register variable is now phrased ``unsupported type for named register variable``,
instead of ``bad type for named register variable``. This makes it clear that the type is not supported at all, rather than being
suboptimal in some way the error fails to mention (#GH111550).

- Clang now emits a ``-Wdepredcated-literal-operator`` diagnostic, even if the
name was a reserved name, which we improperly allowed to suppress the
diagnostic.

Improvements to Clang's time-trace
----------------------------------

Expand All @@ -393,6 +439,8 @@ Bug Fixes in This Version
- Fixed a crash when trying to transform a dependent address space type. Fixes #GH101685.
- Fixed a crash when diagnosing format strings and encountering an empty
delimited escape sequence (e.g., ``"\o{}"``). #GH102218
- The warning emitted for an unsupported register variable type now points to
the unsupported type instead of the ``register`` keyword (#GH109776).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -404,6 +452,8 @@ Bug Fixes to Compiler Builtins

- ``__noop`` can now be used in a constant expression. (#GH102064)

- Fix ``__has_builtin`` incorrectly returning ``false`` for some C++ type traits. (#GH111477)

Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -438,8 +488,6 @@ Bug Fixes to C++ Support
- Correctly check constraints of explicit instantiations of member functions. (#GH46029)
- When performing partial ordering of function templates, clang now checks that
the deduction was consistent. Fixes (#GH18291).
- Fixes to several issues in partial ordering of template template parameters, which
were documented in the test suite.
- Fixed an assertion failure about a constraint of a friend function template references to a value with greater
template depth than the friend function template. (#GH98258)
- Clang now rebuilds the template parameters of out-of-line declarations and specializations in the context
Expand Down Expand Up @@ -471,8 +519,26 @@ Bug Fixes to C++ Support
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
- Fixes crashes with function template member specializations, and increases
conformance of explicit instantiation behaviour with MSVC. (#GH111266)
- Fixed a bug in constraint expression comparison where the ``sizeof...`` expression was not handled properly
in certain friend declarations. (#GH93099)
- Clang now instantiates the correct lambda call operator when a lambda's class type is
merged across modules. (#GH110401)
- Clang now uses the correct set of template argument lists when comparing the constraints of
out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of
a class template. (#GH102320)
- Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460)
- Fixed an assertion failure when invoking recovery call expressions with explicit attributes
and undeclared templates. (#GH107047), (#GH49093)
- Clang no longer crashes when a lambda contains an invalid block declaration that contains an unexpanded
parameter pack. (#GH109148)
- Fixed overload handling for object parameters with top-level cv-qualifiers in explicit member functions (#GH100394)
- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in
certain situations. (#GH47400), (#GH90896)
- Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441)
- During the lookup for a base class name, non-type names are ignored. (#GH16855)
- Fix a crash when recovering an invalid expression involving an explicit object member conversion operator. (#GH112559)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -510,6 +576,10 @@ OpenACC Specific Changes
Target Specific Changes
-----------------------

- Clang now implements the Solaris-specific mangling of ``std::tm`` as
``tm``, same for ``std::div_t``, ``std::ldiv_t``, and
``std::lconv``, for Solaris ABI compatibility. (#GH33114)

AMDGPU Support
^^^^^^^^^^^^^^

Expand Down Expand Up @@ -551,12 +621,19 @@ X86 Support
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^

- In the ARM Target, the frame pointer (FP) of a leaf function can be retained
by using the ``-fno-omit-frame-pointer`` option. If you want to eliminate the FP
in leaf functions after enabling ``-fno-omit-frame-pointer``, you can do so by adding
the ``-momit-leaf-frame-pointer`` option.

Android Support
^^^^^^^^^^^^^^^

Windows Support
^^^^^^^^^^^^^^^

- clang-cl now supports ``/std:c++23preview`` which enables C++23 features.

- Clang no longer allows references inside a union when emulating MSVC 1900+ even if `fms-extensions` is enabled.
Starting with VS2015, MSVC 1900, this Microsoft extension is no longer allowed and always results in an error.
Clang now follows the MSVC behavior in this scenario.
Expand All @@ -576,6 +653,8 @@ CUDA/HIP Language Changes

CUDA Support
^^^^^^^^^^^^
- Clang now supports CUDA SDK up to 12.6
- Added support for sm_100

AIX Support
^^^^^^^^^^^
Expand All @@ -589,6 +668,8 @@ WebAssembly Support
AVR Support
^^^^^^^^^^^

- Reject C/C++ compilation for avr1 devices which have no SRAM.

DWARF Support in Clang
----------------------

Expand All @@ -611,11 +692,19 @@ AST Matchers

- Fixed a crash when traverse lambda expr with invalid captures. (#GH106444)

- Ensure ``hasName`` matches template specializations across inline namespaces,
making `matchesNodeFullSlow` and `matchesNodeFullFast` consistent.

clang-format
------------

- Adds ``BreakBinaryOperations`` option.
- Adds ``TemplateNames`` option.
- Adds ``AlignFunctionDeclarations`` option to ``AlignConsecutiveDeclarations``.
- Adds ``IndentOnly`` suboption to ``ReflowComments`` to fix the indentation of
multi-line comments without touching their contents, renames ``false`` to
``Never``, and ``true`` to ``Always``.
- Adds ``RemoveEmptyLinesInUnwrappedLines`` option.

libclang
--------
Expand All @@ -635,8 +724,8 @@ New features
if class of allocation and deallocation function mismatches.
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-mismatcheddeallocator-c-c>`__.

- Function effects, e.g. the ``nonblocking`` and ``nonallocating`` "performance constraint"
attributes, are now verified. For example, for functions declared with the ``nonblocking``
- Function effects, e.g. the ``nonblocking`` and ``nonallocating`` "performance constraint"
attributes, are now verified. For example, for functions declared with the ``nonblocking``
attribute, the compiler can generate warnings about the use of any language features, or calls to
other functions, which may block.

Expand Down
Loading