Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ bool isUnaryLogicalNotOperator(const Stmt *Statement) {

void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast, const Stmt *Parent,
ASTContext &Context) {
ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
// In case of expressions like (! integer), we should remove the redundant not
// operator and use inverted comparison (integer == 0).
bool InvertComparison =
Expand Down Expand Up @@ -112,9 +113,14 @@ void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
EndLocInsertion += " != ";
}

EndLocInsertion += getZeroLiteralToCompareWithForType(
const StringRef ZeroLiteral = getZeroLiteralToCompareWithForType(
Cast->getCastKind(), SubExpr->getType(), Context);

if (UseUpperCaseLiteralSuffix)
EndLocInsertion += ZeroLiteral.upper();
else
EndLocInsertion += ZeroLiteral;

if (NeedOuterParens) {
EndLocInsertion += ")";
}
Expand Down Expand Up @@ -248,12 +254,15 @@ ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
AllowIntegerConditions(Options.get("AllowIntegerConditions", false)),
AllowPointerConditions(Options.get("AllowPointerConditions", false)) {}
AllowPointerConditions(Options.get("AllowPointerConditions", false)),
UseUpperCaseLiteralSuffix(
Options.get("UseUpperCaseLiteralSuffix", false)) {}

void ImplicitBoolConversionCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "AllowIntegerConditions", AllowIntegerConditions);
Options.store(Opts, "AllowPointerConditions", AllowPointerConditions);
Options.store(Opts, "UseUpperCaseLiteralSuffix", UseUpperCaseLiteralSuffix);
}

void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
Expand Down Expand Up @@ -378,7 +387,8 @@ void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
if (!EquivalentLiteral.empty()) {
Diag << tooling::fixit::createReplacement(*Cast, EquivalentLiteral);
} else {
fixGenericExprCastToBool(Diag, Cast, Parent, Context);
fixGenericExprCastToBool(Diag, Cast, Parent, Context,
UseUpperCaseLiteralSuffix);
}
}

Expand All @@ -392,8 +402,16 @@ void ImplicitBoolConversionCheck::handleCastFromBool(

if (const auto *BoolLiteral =
dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr()->IgnoreParens())) {
Diag << tooling::fixit::createReplacement(
*Cast, getEquivalentForBoolLiteral(BoolLiteral, DestType, Context));

const auto EquivalentForBoolLiteral =
getEquivalentForBoolLiteral(BoolLiteral, DestType, Context);
if (UseUpperCaseLiteralSuffix)
Diag << tooling::fixit::createReplacement(
*Cast, EquivalentForBoolLiteral.upper());
else
Diag << tooling::fixit::createReplacement(*Cast,
EquivalentForBoolLiteral);

} else {
fixGenericExprCastFromBool(Diag, Cast, Context, DestType.getAsString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class ImplicitBoolConversionCheck : public ClangTidyCheck {

const bool AllowIntegerConditions;
const bool AllowPointerConditions;
const bool UseUpperCaseLiteralSuffix;
};

} // namespace clang::tidy::readability
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/TUScheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1838,7 +1838,7 @@ DebouncePolicy::compute(llvm::ArrayRef<clock::duration> History) const {
// Base the result on the median rebuild.
// nth_element needs a mutable array, take the chance to bound the data size.
History = History.take_back(15);
llvm::SmallVector<clock::duration, 15> Recent(History.begin(), History.end());
llvm::SmallVector<clock::duration, 15> Recent(History);
auto *Median = Recent.begin() + Recent.size() / 2;
std::nth_element(Recent.begin(), Median, Recent.end());

Expand Down
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-std-print>` check to support replacing
member function calls too.

- Improved :doc:`readablility-implicit-bool-conversion
<clang-tidy/checks/readability/implicit-bool-conversion>` check
by adding the option `UseUpperCaseLiteralSuffix` to select the
case of the literal suffix in fixes.

- Improved :doc:`readability-redundant-smartptr-get
<clang-tidy/checks/readability/redundant-smartptr-get>` check to
remove `->`, when redundant `get()` is removed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,17 @@ Options

When `true`, the check will allow conditional pointer conversions. Default
is `false`.

.. option:: UseUpperCaseLiteralSuffix

When `true`, the replacements will use an uppercase literal suffix in the
provided fixes. Default is `false`.

Example

.. code-block:: c++

uint32_t foo;
if (foo) {}
// ^ propose replacement default: if (foo != 0u) {}
// ^ propose replacement with option `UseUpperCaseLiteralSuffix`: if (foo != 0U) {}
4 changes: 2 additions & 2 deletions clang-tools-extra/include-cleaner/lib/WalkAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,11 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
}

bool VisitCXXNewExpr(CXXNewExpr *E) {
report(E->getExprLoc(), E->getOperatorNew());
report(E->getExprLoc(), E->getOperatorNew(), RefType::Ambiguous);
return true;
}
bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
report(E->getExprLoc(), E->getOperatorDelete());
report(E->getExprLoc(), E->getOperatorDelete(), RefType::Ambiguous);
return true;
}
};
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,9 +557,9 @@ TEST(WalkAST, FriendDecl) {
}

TEST(WalkAST, OperatorNewDelete) {
testWalk("void* $explicit^operator new(decltype(sizeof(int)), void*);",
testWalk("void* $ambiguous^operator new(decltype(sizeof(int)), void*);",
"struct Bar { void foo() { Bar b; ^new (&b) Bar; } };");
testWalk("struct A { static void $explicit^operator delete(void*); };",
testWalk("struct A { static void $ambiguous^operator delete(void*); };",
"void foo() { A a; ^delete &a; }");
}
} // namespace
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c23
// RUN: %check_clang_tidy -check-suffix=UPPER-CASE %s readability-implicit-bool-conversion %t -- \
// RUN: -config='{CheckOptions: { \
// RUN: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix: true \
// RUN: }}' -- -std=c23

#undef NULL
#define NULL 0L
Expand Down Expand Up @@ -95,6 +99,7 @@ void implicitConversionFromBoolLiterals() {
functionTakingUnsignedLong(false);
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'bool' -> 'unsigned long'
// CHECK-FIXES: functionTakingUnsignedLong(0u);
// CHECK-FIXES-UPPER-CASE: functionTakingUnsignedLong(0U);

functionTakingSignedChar(true);
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'bool' -> 'signed char'
Expand All @@ -103,6 +108,7 @@ void implicitConversionFromBoolLiterals() {
functionTakingFloat(false);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion 'bool' -> 'float'
// CHECK-FIXES: functionTakingFloat(0.0f);
// CHECK-FIXES-UPPER-CASE: functionTakingFloat(0.0F);

functionTakingDouble(true);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'bool' -> 'double'
Expand Down Expand Up @@ -160,11 +166,13 @@ void implicitConversionToBoolSimpleCases() {
functionTakingBool(unsignedLong);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'unsigned long' -> 'bool'
// CHECK-FIXES: functionTakingBool(unsignedLong != 0u);
// CHECK-FIXES-UPPER-CASE: functionTakingBool(unsignedLong != 0U);

float floating = 0.0f;
functionTakingBool(floating);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: functionTakingBool(floating != 0.0f);
// CHECK-FIXES-UPPER-CASE: functionTakingBool(floating != 0.0F);

double doubleFloating = 1.0f;
functionTakingBool(doubleFloating);
Expand Down Expand Up @@ -194,6 +202,7 @@ void implicitConversionToBoolInSingleExpressions() {
boolComingFromFloat = floating;
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: boolComingFromFloat = (floating != 0.0f);
// CHECK-FIXES-UPPER-CASE: boolComingFromFloat = (floating != 0.0F);

signed char character = 'a';
bool boolComingFromChar;
Expand Down Expand Up @@ -288,6 +297,7 @@ void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
functionTakingBool(-0.0f);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: functionTakingBool((-0.0f) != 0.0f);
// CHECK-FIXES-UPPER-CASE: functionTakingBool((-0.0f) != 0.0F);

functionTakingBool(-0.0);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'double' -> 'bool'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t
// RUN: %check_clang_tidy -check-suffix=UPPER-CASE %s readability-implicit-bool-conversion %t -- \
// RUN: -config='{CheckOptions: { \
// RUN: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix: true \
// RUN: }}'

// We need NULL macro, but some buildbots don't like including <cstddef> header
// This is a portable way of getting it to work
Expand Down Expand Up @@ -99,6 +103,7 @@ void implicitConversionFromBoolLiterals() {
functionTaking<unsigned long>(false);
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'bool' -> 'unsigned long'
// CHECK-FIXES: functionTaking<unsigned long>(0u);
// CHECK-FIXES-UPPER-CASE: functionTaking<unsigned long>(0U);

functionTaking<signed char>(true);
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit conversion 'bool' -> 'signed char'
Expand All @@ -107,6 +112,7 @@ void implicitConversionFromBoolLiterals() {
functionTaking<float>(false);
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'bool' -> 'float'
// CHECK-FIXES: functionTaking<float>(0.0f);
// CHECK-FIXES-UPPER-CASE: functionTaking<float>(0.0F);

functionTaking<double>(true);
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit conversion 'bool' -> 'double'
Expand Down Expand Up @@ -178,11 +184,13 @@ void implicitConversionToBoolSimpleCases() {
functionTaking<bool>(unsignedLong);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'unsigned long' -> 'bool'
// CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
// CHECK-FIXES-UPPER-CASE: functionTaking<bool>(unsignedLong != 0U);

float floating = 0.0f;
functionTaking<bool>(floating);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
// CHECK-FIXES-UPPER-CASE: functionTaking<bool>(floating != 0.0F);

double doubleFloating = 1.0f;
functionTaking<bool>(doubleFloating);
Expand Down Expand Up @@ -215,6 +223,7 @@ void implicitConversionToBoolInSingleExpressions() {
bool boolComingFromFloat = floating;
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
// CHECK-FIXES-UPPER-CASE: bool boolComingFromFloat = floating != 0.0F;

signed char character = 'a';
bool boolComingFromChar = character;
Expand All @@ -240,6 +249,7 @@ void implicitConversionToBoolInComplexExpressions() {
bool boolComingFromFloating = floating - 0.3f || boolean;
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
// CHECK-FIXES-UPPER-CASE: bool boolComingFromFloating = ((floating - 0.3f) != 0.0F) || boolean;

double doubleFloating = 0.3;
bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
Expand All @@ -257,6 +267,7 @@ void implicitConversionInNegationExpressions() {
bool boolComingFromNegatedFloat = ! floating;
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
// CHECK-FIXES-UPPER-CASE: bool boolComingFromNegatedFloat = floating == 0.0F;

signed char character = 'a';
bool boolComingFromNegatedChar = (! character);
Expand Down Expand Up @@ -284,6 +295,7 @@ void implicitConversionToBoolInControlStatements() {
while (floating) {}
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: while (floating != 0.0f) {}
// CHECK-FIXES-UPPER-CASE: while (floating != 0.0F) {}

double doubleFloating = 0.4;
do {} while (doubleFloating);
Expand All @@ -296,6 +308,7 @@ bool implicitConversionToBoolInReturnValue() {
return floating;
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: return floating != 0.0f;
// CHECK-FIXES-UPPER-CASE: return floating != 0.0F;
}

void implicitConversionToBoolFromLiterals() {
Expand Down Expand Up @@ -355,6 +368,7 @@ void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
functionTaking<bool>(-0.0f);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'float' -> 'bool'
// CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
// CHECK-FIXES-UPPER-CASE: functionTaking<bool>((-0.0f) != 0.0F);

functionTaking<bool>(-0.0);
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'double' -> 'bool'
Expand Down
6 changes: 4 additions & 2 deletions clang/cmake/caches/CrossWinToARMLinux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ endif()

message(STATUS "Toolchain target to build: ${LLVM_TARGETS_TO_BUILD}")

# Allow to override libc++ ABI version. Use 2 by default.
# Allow to override libc++ ABI version (1 is default).
if (NOT DEFINED LIBCXX_ABI_VERSION)
set(LIBCXX_ABI_VERSION 2)
set(LIBCXX_ABI_VERSION 1)
endif()

message(STATUS "Toolchain's Libc++ ABI version: ${LIBCXX_ABI_VERSION}")
Expand Down Expand Up @@ -217,6 +217,8 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_SHARED
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ABI_VERSION ${LIBCXX_ABI_VERSION} CACHE STRING "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_CXX_ABI "libcxxabi" CACHE STRING "") #!!!
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "")
# Merge libc++ and libc++abi libraries into the single libc++ library file.
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")

# Avoid searching for the python3 interpreter during the runtimes configuration for the cross builds.
# It starts searching the python3 package using the target's sysroot path, that usually is not compatible with the build host.
Expand Down
51 changes: 36 additions & 15 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,7 @@ the configuration (without a prefix: ``Auto``).
**AllowAllParametersOfDeclarationOnNextLine** (``Boolean``) :versionbadge:`clang-format 3.3` :ref:`¶ <AllowAllParametersOfDeclarationOnNextLine>`
If the function declaration doesn't fit on a line,
allow putting all parameters of a function declaration onto
the next line even if ``BinPackParameters`` is ``false``.
the next line even if ``BinPackParameters`` is ``OnePerLine``.

.. code-block:: c++

Expand Down Expand Up @@ -2067,20 +2067,41 @@ the configuration (without a prefix: ``Auto``).

.. _BinPackParameters:

**BinPackParameters** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <BinPackParameters>`
If ``false``, a function declaration's or function definition's
parameters will either all be on the same line or will have one line each.
**BinPackParameters** (``BinPackParametersStyle``) :versionbadge:`clang-format 3.7` :ref:`¶ <BinPackParameters>`
The bin pack parameters style to use.

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

* ``BPPS_BinPack`` (in configuration: ``BinPack``)
Bin-pack parameters.

.. code-block:: c++

void f(int a, int bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
int ccccccccccccccccccccccccccccccccccccccccccc);

* ``BPPS_OnePerLine`` (in configuration: ``OnePerLine``)
Put all parameters on the current line if they fit.
Otherwise, put each one on its own line.

.. code-block:: c++

void f(int a, int b, int c);

void f(int a,
int b,
int ccccccccccccccccccccccccccccccccccccc);

* ``BPPS_AlwaysOnePerLine`` (in configuration: ``AlwaysOnePerLine``)
Always put each parameter on its own line.

.. code-block:: c++

void f(int a,
int b,
int c);

true:
void f(int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}

false:
void f(int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaa,
int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}

.. _BitFieldColonSpacing:

Expand Down Expand Up @@ -4817,7 +4838,7 @@ the configuration (without a prefix: ``Auto``).
items into as few lines as possible when they go over ``ColumnLimit``.

If ``Auto`` (the default), delegates to the value in
``BinPackParameters``. If that is ``true``, bin-packs Objective-C
``BinPackParameters``. If that is ``BinPack``, bin-packs Objective-C
protocol conformance list items into as few lines as possible
whenever they go over ``ColumnLimit``.

Expand All @@ -4831,13 +4852,13 @@ the configuration (without a prefix: ``Auto``).

.. code-block:: objc
Always (or Auto, if BinPackParameters=true):
Always (or Auto, if BinPackParameters==BinPack):
@interface ccccccccccccc () <
ccccccccccccc, ccccccccccccc,
ccccccccccccc, ccccccccccccc> {
}
Never (or Auto, if BinPackParameters=false):
Never (or Auto, if BinPackParameters!=BinPack):
@interface ddddddddddddd () <
ddddddddddddd,
ddddddddddddd,
Expand Down
2 changes: 1 addition & 1 deletion clang/docs/InternalsManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3200,7 +3200,7 @@ are similar.
always involve two functions: an ``ActOnXXX`` function that will be called
directly from the parser, and a ``BuildXXX`` function that performs the
actual semantic analysis and will (eventually!) build the AST node. It's
fairly common for the ``ActOnCXX`` function to do very little (often just
fairly common for the ``ActOnXXX`` function to do very little (often just
some minor translation from the parser's representation to ``Sema``'s
representation of the same thing), but the separation is still important:
C++ template instantiation, for example, should always call the ``BuildXXX``
Expand Down
4 changes: 2 additions & 2 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3987,7 +3987,7 @@ ellipsis (``...``) in the function signature. Alternatively, in C23 mode or
later, it may be the integer literal ``0`` if there is no parameter preceding
the ellipsis. This function initializes the given ``__builtin_va_list`` object.
It is undefined behavior to call this function on an already initialized
``__builin_va_list`` object.
``__builtin_va_list`` object.
* ``void __builtin_va_end(__builtin_va_list list)``
Expand Down Expand Up @@ -4321,7 +4321,7 @@ an appropriate value during the emission.
Note that there is no builtin matching the `llvm.coro.save` intrinsic. LLVM
automatically will insert one if the first argument to `llvm.coro.suspend` is
token `none`. If a user calls `__builin_suspend`, clang will insert `token none`
token `none`. If a user calls `__builtin_suspend`, clang will insert `token none`
as the first argument to the intrinsic.
Source location builtins
Expand Down
85 changes: 85 additions & 0 deletions clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
=================
RealtimeSanitizer
=================

.. contents::
:local:

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.
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
execution time in a function marked ``[[clang::nonblocking]]``
RTSan raises an error.

The runtime slowdown introduced by RealtimeSanitizer is negligible.

How to build
============

Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>` and enable the
``compiler-rt`` runtime. An example CMake configuration that will allow for the
use/testing of RealtimeSanitizer:

.. code-block:: console
$ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm
Usage
=====

There are two requirements:

1. The code must be compiled with the ``-fsanitize=realtime`` flag.
2. Functions that are subject to real-time constraints must be marked
with the ``[[clang::nonblocking]]`` attribute.

Typically, these attributes should be added onto the functions that are entry
points for threads with real-time priority. These threads are subject to a fixed
callback time, such as audio callback threads or rendering loops in video game
code.

.. code-block:: console
% cat example_realtime_violation.cpp
#include <vector>
void violation() [[clang::nonblocking]]{
std::vector<float> v;
v.resize(100);
}
int main() {
violation();
return 0;
}
# Compile and link
% clang++ -fsanitize=realtime -g 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
% ./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>)
111 changes: 96 additions & 15 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ C++ Specific Potentially Breaking Changes
ABI Changes in This Version
---------------------------

- Fixed Microsoft name mangling of placeholder, auto and decltype(auto), return types for MSVC 1920+. This change resolves incompatibilities with code compiled by MSVC 1920+ but will introduce incompatibilities with code compiled by earlier versions of Clang unless such code is built with the compiler option -fms-compatibility-version=19.14 to imitate the MSVC 1914 mangling behavior.

AST Dumping Potentially Breaking Changes
----------------------------------------

Expand Down Expand Up @@ -107,19 +109,6 @@ C++ Language Changes
constant expression. Supports the `V.xyzw` syntax and other tidbits
as seen in OpenCL. Selecting multiple elements is left as a future work.

C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^

C++14 Feature Support
^^^^^^^^^^^^^^^^^^^^^

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

C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- Removed the restriction to literal types in constexpr functions in C++23 mode.

C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -131,6 +120,16 @@ C++2c Feature Support

- Implemented `P2893R3 Variadic Friends <https://wg21.link/P2893>`_

- Implemented `P2747R2 constexpr placement new <https://wg21.link/P2747R2>`_.

C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- Removed the restriction to literal types in constexpr functions in C++23 mode.

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


Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -149,6 +148,12 @@ Resolutions to C++ Defect Reports
of the target type, even if the type of the bit-field is larger.
(`CWG2627: Bit-fields and narrowing conversions <https://cplusplus.github.io/CWG/issues/2627.html>`_)

- ``nullptr`` is now promoted to ``void*`` when passed to a C-style variadic function.
(`CWG722: Can nullptr be passed to an ellipsis? <https://cplusplus.github.io/CWG/issues/722.html>`_)

- Allow ``void{}`` as a prvalue of type ``void``.
(`CWG2351: void{} <https://cplusplus.github.io/CWG/issues/2351.html>`_).

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

Expand All @@ -168,14 +173,23 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------

- The ``-fc++-static-destructors={all,thread-local,none}`` flag was
added to control which C++ variables have static destructors
registered: all (the default) does so for all variables, thread-local
only for thread-local variables, and none (which corresponds to the
existing ``-fno-c++-static-destructors`` flag) skips all static
destructors registration.

Deprecated Compiler Flags
-------------------------

- ``-fheinous-gnu-extensions`` is deprecated; it is now equivalent to
specifying ``-Wno-error=invalid-gnu-asm-cast`` and may be removed in the
future.

Modified Compiler Flags
-----------------------

- The compiler flag `-fbracket-depth` default value is increased from 256 to 2048.

- The ``-ffp-model`` option has been updated to enable a more limited set of
optimizations when the ``fast`` argument is used and to accept a new argument,
``aggressive``. The behavior of ``-ffp-model=aggressive`` is equivalent
Expand Down Expand Up @@ -233,6 +247,20 @@ Improvements to Clang's diagnostics

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

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

- Improved diagnostic when trying to befriend a concept. (#GH45182).

- Added the ``-Winvalid-gnu-asm-cast`` diagnostic group to control warnings
about use of "noop" casts for lvalues (a GNU extension). This diagnostic is
a warning which defaults to being an error, is enabled by default, and is
also controlled by the now-deprecated ``-fheinous-gnu-extensions`` flag.

- Added the ``-Wdecls-in-multiple-modules`` option to assist users to identify
multiple declarations in different modules, which is the major reason of the slow
compilation speed with modules. This warning is disabled by default and it needs
to be explicitly enabled or by ``-Weverything``.

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

Expand Down Expand Up @@ -284,6 +312,12 @@ Bug Fixes to C++ Support
- Clang now properly handles the order of attributes in `extern` blocks. (#GH101990).
- Fixed an assertion failure by preventing null explicit object arguments from being deduced. (#GH102025).
- Correctly check constraints of explicit instantiations of member functions. (#GH46029)
- 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
of the current instantiation in all cases.
- Fix evaluation of the index of dependent pack indexing expressions/types specifiers (#GH105900)
- Correctly handle subexpressions of an immediate invocation in the presence of implicit casts. (#GH105558)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -302,6 +336,12 @@ Miscellaneous Clang Crashes Fixed
- Fixed a crash caused by long chains of ``sizeof`` and other similar operators
that can be followed by a non-parenthesized expression. (#GH45061)

- Fixed an crash when compiling ``#pragma STDC FP_CONTRACT DEFAULT`` with
``-ffp-contract=fast-honor-pragmas``. (#GH104830)

- Fixed a crash when function has more than 65536 parameters.
Now a diagnostic is emitted. (#GH35741)

OpenACC Specific Changes
------------------------

Expand Down Expand Up @@ -434,6 +474,47 @@ Moved checkers

Sanitizers
----------
- Introduced Realtime Sanitizer, activated by using the -fsanitize=realtime
flag. This sanitizer detects unsafe system library calls, such as memory
allocations and mutex locks. If any such function is called during invocation
of a function marked with the ``[[clang::nonblocking]]`` attribute, an error
is printed to the console and the process exits non-zero.

- Added the ``-fsanitize-undefined-ignore-overflow-pattern`` flag which can be
used to disable specific overflow-dependent code patterns. The supported
patterns are: ``add-signed-overflow-test``, ``add-unsigned-overflow-test``,
``negated-unsigned-const``, and ``unsigned-post-decr-while``. The sanitizer
instrumentation can be toggled off for all available patterns by specifying
``all``. Conversely, you may disable all exclusions with ``none`` which is
the default.

.. code-block:: c++

/// specified with ``-fsanitize-undefined-ignore-overflow-pattern=add-unsigned-overflow-test``
int common_overflow_check_pattern(unsigned base, unsigned offset) {
if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented
}
/// specified with ``-fsanitize-undefined-ignore-overflow-pattern=add-signed-overflow-test``
int common_overflow_check_pattern_signed(signed int base, signed int offset) {
if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings, won't be instrumented
}
/// specified with ``-fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const``
void negation_overflow() {
unsigned long foo = -1UL; // No longer causes a negation overflow warning
unsigned long bar = -2UL; // and so on...
}

/// specified with ``-fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while``
void while_post_decrement() {
unsigned char count = 16;
while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
}
Many existing projects have a large amount of these code patterns present.
This new flag should allow those projects to enable integer sanitizers with
less noise.

Python Binding Changes
----------------------
Expand Down
73 changes: 4 additions & 69 deletions clang/docs/StandardCPlusPlusModules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,9 @@ approach:
Reducing the duplication from textual includes is what improves compile-time
performance.

To help users to identify such issues, we add a warning ``-Wdecls-in-multiple-modules``.
This warning is disabled by default and it needs to be explicitly enabled or by ``-Weverything``.

Transitioning to modules
------------------------

Expand Down Expand Up @@ -1297,74 +1300,6 @@ A high-level overview of support for standards features, including modules, can
be found on the `C++ Feature Status <https://clang.llvm.org/cxx_status.html>`_
page.

Missing VTables for classes attached to modules
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now the compiler may miss emitting the definition of vtables
for classes attached to modules, if the definition of the class
doesn't contain any key function in that module units
(The key function is the first non-pure virtual function that is
not inline at the point of class definition.)

(Note: technically, the key function is not a thing for modules.
We use the concept here for convinient.)

For example,

.. code-block:: c++

// layer1.cppm
export module foo:layer1;
struct Fruit {
virtual ~Fruit() = default;
virtual void eval() = 0;
};
struct Banana : public Fruit {
Banana() {}
void eval() override;
};

// layer2.cppm
export module foo:layer2;
import :layer1;
export void layer2_fun() {
Banana *b = new Banana();
b->eval();
}
void Banana::eval() {
}
For the above example, we can't find the definition for the vtable of
class ``Banana`` in any object files.

The expected behavior is, for dynamic classes attached to named modules,
the vtable should always be emitted to the module units the class attaches
to.

To workaround the problem, users can add the key function manually in the
corresponding module units. e.g.,

.. code-block:: c++

// layer1.cppm
export module foo:layer1;
struct Fruit {
virtual ~Fruit() = default;
virtual void eval() = 0;
};
struct Banana : public Fruit {
// Hack a key function to hint the compiler to emit the virtual table.
virtual void anchor();

Banana() {}
void eval() override;
};

void Banana::anchor() {}

This is tracked by
`#70585 <https://github.com/llvm/llvm-project/issues/70585>`_.

Including headers after import is not well-supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -1436,7 +1371,7 @@ non-module unit depending on the definition of some macros. However, this usage
is forbidden by P1857R3 which is not yet implemented in Clang. This means that
is possible to write invalid modules which will no longer be accepted once
P1857R3 is implemented. This is tracked by
`#56917 <https://github.com/llvm/llvm-project/issues/56917>`_.
`#54047 <https://github.com/llvm/llvm-project/issues/54047>`_.

Until then, it is recommended not to mix macros with module declarations.

Expand Down
65 changes: 65 additions & 0 deletions clang/docs/UndefinedBehaviorSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,71 @@ To silence reports from unsigned integer overflow, you can set
``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for
providing fuzzing signal without blowing up logs.

Disabling instrumentation for common overflow patterns
------------------------------------------------------

There are certain overflow-dependent or overflow-prone code patterns which
produce a lot of noise for integer overflow/truncation sanitizers. Negated
unsigned constants, post-decrements in a while loop condition and simple
overflow checks are accepted and pervasive code patterns. However, the signal
received from sanitizers instrumenting these code patterns may be too noisy for
some projects. To disable instrumentation for these common patterns one should
use ``-fsanitize-undefined-ignore-overflow-pattern=``.

Currently, this option supports three overflow-dependent code idioms:

``negated-unsigned-const``

.. code-block:: c++

/// -fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const
unsigned long foo = -1UL; // No longer causes a negation overflow warning
unsigned long bar = -2UL; // and so on...

``unsigned-post-decr-while``

.. code-block:: c++

/// -fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while
unsigned char count = 16;
while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
``add-signed-overflow-test,add-unsigned-overflow-test``

.. code-block:: c++

/// -fsanitize-undefined-ignore-overflow-pattern=add-(signed|unsigned)-overflow-test
if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and other re-orderings,
// won't be instrumented (signed or unsigned types)
.. list-table:: Overflow Pattern Types
:widths: 30 50
:header-rows: 1

* - Pattern
- Sanitizer
* - negated-unsigned-const
- unsigned-integer-overflow
* - unsigned-post-decr-while
- unsigned-integer-overflow
* - add-unsigned-overflow-test
- unsigned-integer-overflow
* - add-signed-overflow-test
- signed-integer-overflow



Note: ``add-signed-overflow-test`` suppresses only the check for Undefined
Behavior. Eager Undefined Behavior optimizations are still possible. One may
remedy this with ``-fwrapv`` or ``-fno-strict-overflow``.

You can enable all exclusions with
``-fsanitize-undefined-ignore-overflow-pattern=all`` or disable all exclusions
with ``-fsanitize-undefined-ignore-overflow-pattern=none``. If
``-fsanitize-undefined-ignore-overflow-pattern`` is not specified ``none`` is
implied. Specifying ``none`` alongside other values also implies ``none`` as
``none`` has precedence over other values -- including ``all``.

Issue Suppression
=================

Expand Down
2 changes: 2 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,8 @@ are listed below.
integrity.
- ``-fsanitize=safe-stack``: :doc:`safe stack <SafeStack>`
protection against stack-based memory corruption errors.
- ``-fsanitize=realtime``: :doc:`RealtimeSanitizer`,
a real-time safety checker.

There are more fine-grained checks available: see
the :ref:`list <ubsan-checks>` of specific kinds of
Expand Down
1 change: 1 addition & 0 deletions clang/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Using Clang as a Compiler
UndefinedBehaviorSanitizer
DataFlowSanitizer
LeakSanitizer
RealtimeSanitizer
SanitizerCoverage
SanitizerStats
SanitizerSpecialCaseList
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3888,6 +3888,7 @@ class BinaryOperator : public Expr {
/// Construct an empty binary operator.
explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) {
BinaryOperatorBits.Opc = BO_Comma;
BinaryOperatorBits.ExcludedOverflowPattern = false;
}

public:
Expand Down Expand Up @@ -4043,6 +4044,15 @@ class BinaryOperator : public Expr {
void setHasStoredFPFeatures(bool B) { BinaryOperatorBits.HasFPFeatures = B; }
bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; }

/// Set and get the bit that informs arithmetic overflow sanitizers whether
/// or not they should exclude certain BinaryOperators from instrumentation
void setExcludedOverflowPattern(bool B) {
BinaryOperatorBits.ExcludedOverflowPattern = B;
}
bool hasExcludedOverflowPattern() const {
return BinaryOperatorBits.ExcludedOverflowPattern;
}

/// Get FPFeatures from trailing storage
FPOptionsOverride getStoredFPFeatures() const {
assert(hasStoredFPFeatures());
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -2176,8 +2176,9 @@ class LambdaExpr final : public Expr,
const_child_range children() const;
};

/// An expression "T()" which creates a value-initialized rvalue of type
/// T, which is a non-class type. See (C++98 [5.2.3p2]).
/// An expression "T()" which creates an rvalue of a non-class type T.
/// For non-void T, the rvalue is value-initialized.
/// See (C++98 [5.2.3p2]).
class CXXScalarValueInitExpr : public Expr {
friend class ASTStmtReader;

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,11 @@ class alignas(void *) Stmt {
LLVM_PREFERRED_TYPE(bool)
unsigned HasFPFeatures : 1;

/// Whether or not this BinaryOperator should be excluded from integer
/// overflow sanitization.
LLVM_PREFERRED_TYPE(bool)
unsigned ExcludedOverflowPattern : 1;

SourceLocation OpLoc;
};

Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
unsigned Kind : NumOfBuiltinTypeBits;
};

public:
static constexpr int FunctionTypeNumParamsWidth = 16;
static constexpr int FunctionTypeNumParamsLimit = (1 << 16) - 1;

protected:
/// FunctionTypeBitfields store various bits belonging to FunctionProtoType.
/// Only common bits are stored here. Additional uncommon bits are stored
/// in a trailing object after FunctionProtoType.
Expand Down Expand Up @@ -1966,7 +1971,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
/// According to [implimits] 8 bits should be enough here but this is
/// somewhat easy to exceed with metaprogramming and so we would like to
/// keep NumParams as wide as reasonably possible.
unsigned NumParams : 16;
unsigned NumParams : FunctionTypeNumParamsWidth;

/// The type of exception specification this function has.
LLVM_PREFERRED_TYPE(ExceptionSpecificationType)
Expand Down
13 changes: 11 additions & 2 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,15 @@ def BTFTypeTag : TypeAttr {
let LangOpts = [COnly];
}

def BPFFastCall : InheritableAttr,
TargetSpecificAttr<TargetBPF> {
let Spellings = [Clang<"bpf_fastcall">];
let Subjects = SubjectList<[FunctionLike]>;
let Documentation = [BPFFastCallDocs];
let LangOpts = [COnly];
let SimpleHandler = 1;
}

def WebAssemblyExportName : InheritableAttr,
TargetSpecificAttr<TargetWebAssembly> {
let Spellings = [Clang<"export_name">];
Expand Down Expand Up @@ -4529,7 +4538,7 @@ def HLSLSV_GroupIndex: HLSLAnnotationAttr {

def HLSLResourceBinding: InheritableAttr {
let Spellings = [HLSLAnnotation<"register">];
let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar]>;
let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar], ErrorDiag>;
let LangOpts = [HLSL];
let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>];
let Documentation = [HLSLResourceBindingDocs];
Expand Down Expand Up @@ -4613,7 +4622,7 @@ def HLSLROV : InheritableAttr {

def HLSLResourceClass : InheritableAttr {
let Spellings = [CXX11<"hlsl", "resource_class">];
let Subjects = SubjectList<[Struct]>;
let Subjects = SubjectList<[Field]>;
let LangOpts = [HLSL];
let Args = [
EnumArgument<"ResourceClass", "llvm::hlsl::ResourceClass",
Expand Down
105 changes: 75 additions & 30 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,12 @@ succeeds but Clang emits a warning specifying that the function is deprecated.
Finally, if Clang is instructed to compile code for macOS 10.7, the call
fails because ``f()`` is no longer available.

Clang is instructed to compile code for a minimum deployment version using
the ``-target`` or ``-mtargetos`` command line arguments. For example,
macOS 10.7 would be specified as ``-target x86_64-apple-macos10.7`` or
``-mtargetos=macos10.7``. Variants like Mac Catalyst are specified as
``-target arm64-apple-ios15.0-macabi`` or ``-mtargetos=ios15.0-macabi``

The availability attribute is a comma-separated list starting with the
platform name and then including clauses specifying important milestones in the
declaration's lifetime (in any order) along with additional information. Those
Expand Down Expand Up @@ -1636,41 +1642,61 @@ the implicitly inferred availability attributes. If no availability attribute
specifies availability for the current target platform, the availability
attributes are ignored. Supported platforms are:

``ios``
Apple's iOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-ios*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=ios*version*``
command-line argument.
``iOS``
``macOS``
``tvOS``
``watchOS``
``iOSApplicationExtension``
``macOSApplicationExtension``
``tvOSApplicationExtension``
``watchOSApplicationExtension``
``macCatalyst``
``macCatalystApplicationExtension``
``visionOS``
``visionOSApplicationExtension``
``driverkit``
``swift``
``android``
``fuchsia``
``ohos``
``zos``
``ShaderModel``

``macos``
Apple's macOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-macos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=macos*version*``
command-line argument. ``macosx`` is supported for
backward-compatibility reasons, but it is deprecated.
Some platforms have alias names:

``ios``
``macos``
``macosx (deprecated)``
``tvos``
Apple's tvOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-tvos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=tvos*version*``
command-line argument.

``watchos``
Apple's watchOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-watchos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=watchos*version*``
command-line argument.

``ios_app_extension``
``macos_app_extension``
``macosx_app_extension (deprecated)``
``tvos_app_extension``
``watchos_app_extension``
``maccatalyst``
``maccatalyst_app_extension``
``visionos``
Apple's visionOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-visionos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=visionos*version*``
command-line argument.

``driverkit``
Apple's DriverKit userspace kernel extensions. The minimum deployment target
is specified as part of the ``-target *arch*-apple-driverkit*version*``
command line argument.
``visionos_app_extension``
``shadermodel``

Supported environment names for the ShaderModel platform:

``pixel``
``vertex``
``geometry``
``hull``
``domain``
``compute``
``raygeneration``
``intersection``
``anyhit``
``closesthit``
``miss``
``callable``
``mesh``
``amplification``
``library``

A declaration can typically be used even when deploying back to a platform
version prior to when the declaration was introduced. When this happens, the
Expand Down Expand Up @@ -2345,6 +2371,25 @@ section.
}];
}

def BPFFastCallDocs : Documentation {
let Category = DocCatType;
let Content = [{
Functions annotated with this attribute are likely to be inlined by BPF JIT.
It is assumed that inlined implementation uses less caller saved registers,
than a regular function.
Specifically, the following registers are likely to be preserved:
- ``R0`` if function return value is ``void``;
- ``R2-R5` if function takes 1 argument;
- ``R3-R5` if function takes 2 arguments;
- ``R4-R5` if function takes 3 arguments;
- ``R5`` if function takes 4 arguments;

For such functions Clang generates code pattern that allows BPF JIT
to recognize and remove unnecessary spills and fills of the preserved
registers.
}];
}

def MipsInterruptDocs : Documentation {
let Category = DocCatFunction;
let Heading = "interrupt (MIPS)";
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4745,6 +4745,12 @@ def HLSLRSqrt : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLSaturate : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_saturate"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
Expand Down
22 changes: 11 additions & 11 deletions clang/include/clang/Basic/BuiltinsWebAssembly.def
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_pmin_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_pmax_f64x2, "V2dV2dV2d", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_min_f16x8, "V8hV8hV8h", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_max_f16x8, "V8hV8hV8h", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_pmin_f16x8, "V8hV8hV8h", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_pmax_f16x8, "V8hV8hV8h", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_min_f16x8, "V8hV8hV8h", "nc", "fp16")
TARGET_BUILTIN(__builtin_wasm_max_f16x8, "V8hV8hV8h", "nc", "fp16")
TARGET_BUILTIN(__builtin_wasm_pmin_f16x8, "V8hV8hV8h", "nc", "fp16")
TARGET_BUILTIN(__builtin_wasm_pmax_f16x8, "V8hV8hV8h", "nc", "fp16")

TARGET_BUILTIN(__builtin_wasm_ceil_f32x4, "V4fV4f", "nc", "simd128")
TARGET_BUILTIN(__builtin_wasm_floor_f32x4, "V4fV4f", "nc", "simd128")
Expand Down Expand Up @@ -170,8 +170,8 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_madd_f32x4, "V4fV4fV4fV4f", "nc", "relaxed
TARGET_BUILTIN(__builtin_wasm_relaxed_nmadd_f32x4, "V4fV4fV4fV4f", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_madd_f64x2, "V2dV2dV2dV2d", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_nmadd_f64x2, "V2dV2dV2dV2d", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_madd_f16x8, "V8hV8hV8hV8h", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_relaxed_nmadd_f16x8, "V8hV8hV8hV8h", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_relaxed_madd_f16x8, "V8hV8hV8hV8h", "nc", "fp16")
TARGET_BUILTIN(__builtin_wasm_relaxed_nmadd_f16x8, "V8hV8hV8hV8h", "nc", "fp16")

TARGET_BUILTIN(__builtin_wasm_relaxed_laneselect_i8x16, "V16ScV16ScV16ScV16Sc", "nc", "relaxed-simd")
TARGET_BUILTIN(__builtin_wasm_relaxed_laneselect_i16x8, "V8sV8sV8sV8s", "nc", "relaxed-simd")
Expand All @@ -197,11 +197,11 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_dot_i8x16_i7x16_add_s_i32x4, "V4iV16ScV16S
TARGET_BUILTIN(__builtin_wasm_relaxed_dot_bf16x8_add_f32_f32x4, "V4fV8UsV8UsV4f", "nc", "relaxed-simd")

// Half-Precision (fp16)
TARGET_BUILTIN(__builtin_wasm_loadf16_f32, "fh*", "nU", "half-precision")
TARGET_BUILTIN(__builtin_wasm_storef16_f32, "vfh*", "n", "half-precision")
TARGET_BUILTIN(__builtin_wasm_splat_f16x8, "V8hf", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_extract_lane_f16x8, "fV8hi", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_replace_lane_f16x8, "V8hV8hif", "nc", "half-precision")
TARGET_BUILTIN(__builtin_wasm_loadf16_f32, "fh*", "nU", "fp16")
TARGET_BUILTIN(__builtin_wasm_storef16_f32, "vfh*", "n", "fp16")
TARGET_BUILTIN(__builtin_wasm_splat_f16x8, "V8hf", "nc", "fp16")
TARGET_BUILTIN(__builtin_wasm_extract_lane_f16x8, "fV8hi", "nc", "fp16")
TARGET_BUILTIN(__builtin_wasm_replace_lane_f16x8, "V8hV8hif", "nc", "fp16")

// Reference Types builtins
// Some builtins are custom type-checked - see 't' as part of the third argument,
Expand Down
44 changes: 44 additions & 0 deletions clang/include/clang/Basic/BuiltinsX86.def
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,50 @@ TARGET_BUILTIN(__builtin_ia32_vcvttps2ibs512_mask, "V16UiV16fV16UiUsIi", "nV:512
TARGET_BUILTIN(__builtin_ia32_vcvttps2iubs128_mask, "V4UiV4fV4UiUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvttps2iubs256_mask, "V8UiV8fV8UiUcIi", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvttps2iubs512_mask, "V16UiV16fV16UiUsIi", "nV:512:", "avx10.2-512")

// AVX10.2 CONVERT
TARGET_BUILTIN(__builtin_ia32_vcvt2ps2phx128_mask, "V8xV4fV4fV8xUc", "ncV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvt2ps2phx256_mask, "V16xV8fV8fV16xUsIi", "ncV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvt2ps2phx512_mask, "V32xV16fV16fV32xUiIi", "ncV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2bf8_128_mask, "V16cV16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2bf8_256_mask, "V16cV32cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2bf8_512_mask, "V32cV64cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2bf8s_128_mask, "V16cV16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2bf8s_256_mask, "V16cV32cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2bf8s_512_mask, "V32cV64cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2hf8_128_mask, "V16cV16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2hf8_256_mask, "V16cV32cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2hf8_512_mask, "V32cV64cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2hf8s_128_mask, "V16cV16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2hf8s_256_mask, "V16cV32cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtbiasph2hf8s_512_mask, "V32cV64cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2bf8_128, "V16cV8xV8x", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2bf8_256, "V32cV16xV16x", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2bf8_512, "V64cV32xV32x", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2bf8s_128, "V16cV8xV8x", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2bf8s_256, "V32cV16xV16x", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2bf8s_512, "V64cV32xV32x", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2hf8_128, "V16cV8xV8x", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2hf8_256, "V32cV16xV16x", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2hf8_512, "V64cV32xV32x", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2hf8s_128, "V16cV8xV8x", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2hf8s_256, "V32cV16xV16x", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtne2ph2hf8s_512, "V64cV32xV32x", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvthf8_2ph128_mask, "V8xV16cV8xUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvthf8_2ph256_mask, "V16xV16cV16xUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvthf8_2ph512_mask, "V32xV32cV32xUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2bf8_128_mask, "V16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2bf8_256_mask, "V16cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2bf8_512_mask, "V32cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2bf8s_128_mask, "V16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2bf8s_256_mask, "V16cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2bf8s_512_mask, "V32cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2hf8_128_mask, "V16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2hf8_256_mask, "V16cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2hf8_512_mask, "V32cV32xV32cUi", "nV:512:", "avx10.2-512")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2hf8s_128_mask, "V16cV8xV16cUc", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2hf8s_256_mask, "V16cV16xV16cUs", "nV:256:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vcvtneph2hf8s_512_mask, "V32cV32xV32cUi", "nV:512:", "avx10.2-512")
#undef BUILTIN
#undef TARGET_BUILTIN
#undef TARGET_HEADER_BUILTIN
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ VALUE_CODEGENOPT(Name, Bits, Default)

CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
CODEGENOPT(Crel, 1, 0) ///< -Wa,--crel
CODEGENOPT(ImplicitMapSyms, 1, 0) ///< -Wa,-mmapsyms=implicit
CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm.
CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments.
CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new
Expand Down Expand Up @@ -176,6 +177,7 @@ CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled.
CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled.
CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled.
CODEGENOPT(MipsMsa , 1, 0) ///< Set when -Wa,-mmsa is enabled.
CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is
///< enabled.
CODEGENOPT(NoWarn , 1, 0) ///< Set when -Wa,--no-warn is enabled.
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticASTKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ def note_constexpr_new : Note<
def note_constexpr_new_non_replaceable : Note<
"call to %select{placement|class-specific}0 %1">;
def note_constexpr_new_placement : Note<
"this placement new expression is not yet supported in constant expressions">;
"this placement new expression is not supported in constant expressions "
"%select{|before C++2c}0">;
def note_constexpr_placement_new_wrong_type : Note<
"placement new would change type of storage from %0 to %1">;
def note_constexpr_new_negative : Note<
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,9 @@ def DXILValidation : DiagGroup<"dxil-validation">;
// Warning for HLSL API availability
def HLSLAvailability : DiagGroup<"hlsl-availability">;

// Warnings for legacy binding behavior
def LegacyConstantRegisterBinding : DiagGroup<"legacy-constant-register-binding">;

// Warnings and notes related to const_var_decl_type attribute checks
def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">;

Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,9 @@ def ext_decomp_decl_empty : ExtWarn<
"ISO C++17 does not allow a decomposition group to be empty">,
InGroup<DiagGroup<"empty-decomposition">>;

def err_function_parameter_limit_exceeded : Error<
"too many function parameters; subsequent parameters will be ignored">;

// C++26 structured bindings
def ext_decl_attrs_on_binding : ExtWarn<
"an attribute specifier sequence attached to a structured binding declaration "
Expand Down Expand Up @@ -971,6 +974,9 @@ def warn_cxx23_variadic_friends : Warning<
"variadic 'friend' declarations are incompatible with C++ standards before C++2c">,
DefaultIgnore, InGroup<CXXPre26Compat>;

def err_friend_concept : Error<
"friend declaration cannot be a concept">;

// C++11 default member initialization
def ext_nonstatic_member_init : ExtWarn<
"default member initializer for non-static data member is a C++11 "
Expand Down
16 changes: 9 additions & 7 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -9365,9 +9365,6 @@ let CategoryName = "Inline Assembly Issue" in {
"invalid input size for constraint '%0'">;
def err_asm_invalid_output_size : Error<
"invalid output size for constraint '%0'">;
def err_invalid_asm_cast_lvalue : Error<
"invalid use of a cast in a inline asm context requiring an lvalue: "
"remove the cast or build with -fheinous-gnu-extensions">;
def err_invalid_asm_value_for_constraint
: Error <"value '%0' out of range for constraint '%1'">;
def err_asm_non_addr_value_in_memory_constraint : Error <
Expand All @@ -9381,9 +9378,8 @@ let CategoryName = "Inline Assembly Issue" in {
def warn_asm_label_on_auto_decl : Warning<
"ignored asm label '%0' on automatic variable">;
def warn_invalid_asm_cast_lvalue : Warning<
"invalid use of a cast in an inline asm context requiring an lvalue: "
"accepted due to -fheinous-gnu-extensions, but clang may remove support "
"for this in the future">;
"invalid use of a cast in an inline asm context requiring an lvalue">,
InGroup<DiagGroup<"invalid-gnu-asm-cast">>, DefaultError;
def warn_asm_mismatched_size_modifier : Warning<
"value size does not match register size specified by the constraint "
"and modifier">,
Expand Down Expand Up @@ -12352,7 +12348,13 @@ def err_hlsl_missing_semantic_annotation : Error<
def err_hlsl_init_priority_unsupported : Error<
"initializer priorities are not supported in HLSL">;

def err_hlsl_unsupported_register_type : Error<"invalid resource class specifier '%0' used; expected 'b', 's', 't', or 'u'">;
def warn_hlsl_user_defined_type_missing_member: Warning<"binding type '%select{t|u|b|s|c}0' only applies to types containing %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric types}0">, InGroup<LegacyConstantRegisterBinding>;
def err_hlsl_binding_type_mismatch: Error<"binding type '%select{t|u|b|s|c}0' only applies to %select{SRV resources|UAV resources|constant buffer resources|sampler state|numeric variables in the global scope}0">;
def err_hlsl_binding_type_invalid: Error<"binding type '%0' is invalid">;
def err_hlsl_duplicate_register_annotation: Error<"binding type '%select{t|u|b|s|c|i}0' cannot be applied more than once">;
def warn_hlsl_register_type_c_packoffset: Warning<"binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?">, InGroup<LegacyConstantRegisterBinding>, DefaultError;
def warn_hlsl_deprecated_register_type_b: Warning<"binding type 'b' only applies to constant buffers. The 'bool constant' binding type is no longer supported">, InGroup<LegacyConstantRegisterBinding>, DefaultError;
def warn_hlsl_deprecated_register_type_i: Warning<"binding type 'i' ignored. The 'integer constant' binding type is no longer supported">, InGroup<LegacyConstantRegisterBinding>, DefaultError;
def err_hlsl_unsupported_register_number : Error<"register number should be an integer">;
def err_hlsl_expected_space : Error<"invalid space specifier '%0' used; expected 'space' followed by an integer, like space1">;
def warn_hlsl_packoffset_mix : Warning<"cannot mix packoffset elements with nonpackoffset elements in a cbuffer">,
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/DiagnosticSerializationKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ def warn_module_system_bit_conflict : Warning<
"as a non-system module; any difference in diagnostic options will be ignored">,
InGroup<ModuleConflict>;

def warn_decls_in_multiple_modules : Warning<
"declaration %0 is detected to be defined in multiple module units, first is from '%1' and second is from '%2'; "
"the compiler may not be good at merging the definitions. ">,
InGroup<DiagGroup<"decls-in-multiple-modules">>,
DefaultIgnore;

def err_failed_to_find_module_file : Error<
"failed to find module file for module '%0'">;
} // let CategoryName
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
LANGOPT(Blocks , 1, 0, "blocks extension to C")
BENIGN_LANGOPT(EmitAllDecls , 1, 0, "emitting all declarations")
LANGOPT(MathErrno , 1, 1, "errno in math functions")
BENIGN_LANGOPT(HeinousExtensions , 1, 0, "extensions that we really don't like and may be ripped out at any time")
LANGOPT(Modules , 1, 0, "modules semantics")
COMPATIBLE_LANGOPT(CPlusPlusModules, 1, 0, "C++ modules syntax")
LANGOPT(SkipODRCheckInGMF, 1, 0, "Skip ODR checks for decls in the global module fragment")
Expand Down Expand Up @@ -465,7 +464,9 @@ LANGOPT(FixedPoint, 1, 0, "fixed point types")
LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0,
"unsigned fixed point types having one extra padding bit")

LANGOPT(RegisterStaticDestructors, 1, 1, "Register C++ static destructors")
ENUM_LANGOPT(RegisterStaticDestructors, RegisterStaticDestructorsKind, 2,
RegisterStaticDestructorsKind::All,
"Register C++ static destructors")

LANGOPT(RegCall4, 1, 0, "Set __regcall4 as a default calling convention to respect __regcall ABI v.4")

Expand Down
40 changes: 40 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,23 @@ class LangOptionsBase {
PerThread,
};

/// Exclude certain code patterns from being instrumented by arithmetic
/// overflow sanitizers
enum OverflowPatternExclusionKind {
/// Don't exclude any overflow patterns from sanitizers
None = 1 << 0,
/// Exclude all overflow patterns (below)
All = 1 << 1,
/// if (a + b < a)
AddSignedOverflowTest = 1 << 2,
/// if (a + b < a)
AddUnsignedOverflowTest = 1 << 3,
/// -1UL
NegUnsignedConst = 1 << 4,
/// while (count--)
PostDecrInWhile = 1 << 5,
};

enum class DefaultVisiblityExportMapping {
None,
/// map only explicit default visibilities to exported
Expand Down Expand Up @@ -441,6 +458,16 @@ class LangOptionsBase {
CX_None
};

/// Controls which variables have static destructors registered.
enum class RegisterStaticDestructorsKind {
/// Register static destructors for all variables.
All,
/// Register static destructors only for thread-local variables.
ThreadLocal,
/// Don't register static destructors for any variables.
None,
};

// Define simple language options (with no accessors).
#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
Expand Down Expand Up @@ -555,6 +582,11 @@ class LangOptions : public LangOptionsBase {
/// The default stream kind used for HIP kernel launching.
GPUDefaultStreamKind GPUDefaultStream;

/// Which overflow patterns should be excluded from sanitizer instrumentation
unsigned OverflowPatternExclusionMask = 0;

std::vector<std::string> OverflowPatternExclusionValues;

/// The seed used by the randomize structure layout feature.
std::string RandstructSeed;

Expand Down Expand Up @@ -630,6 +662,14 @@ class LangOptions : public LangOptionsBase {
return MSCompatibilityVersion >= MajorVersion * 100000U;
}

bool isOverflowPatternExcluded(OverflowPatternExclusionKind Kind) const {
if (OverflowPatternExclusionMask & OverflowPatternExclusionKind::None)
return false;
if (OverflowPatternExclusionMask & OverflowPatternExclusionKind::All)
return true;
return OverflowPatternExclusionMask & Kind;
}

/// Reset all of the options that are not considered when building a
/// module.
void resetNonModularOptions();
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/Sanitizers.def
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ SANITIZER("thread", Thread)
// Numerical stability sanitizer.
SANITIZER("numerical", NumericalStability)

// RealtimeSanitizer
SANITIZER("realtime", Realtime)

// LeakSanitizer
SANITIZER("leak", Leak)

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,9 @@ KEYWORD(out , KEYHLSL)
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL)
#include "clang/Basic/HLSLIntangibleTypes.def"

// HLSL Type traits.
TYPE_TRAIT_2(__builtin_hlsl_is_scalarized_layout_compatible, IsScalarizedLayoutCompatible, KEYHLSL)

// OpenMP Type Traits
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)

Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,7 @@ class Driver {

/// Takes the path to a binary that's either in bin/ or lib/ and returns
/// the path to clang's resource directory.
static std::string GetResourcesPath(StringRef BinaryPath,
StringRef CustomResourceDir = "");
static std::string GetResourcesPath(StringRef BinaryPath);

Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler",
Expand Down
52 changes: 41 additions & 11 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,8 @@ def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>,
Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>;
def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>,
Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>;
def Winvalid_gnu_asm_cast : Flag<["-"], "Winvalid-gnu-asm-cast">, Group<W_Group>,
Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>;
def W_Joined : Joined<["-"], "W">, Group<W_Group>,
Visibility<[ClangOption, CC1Option, CLOption, DXCOption, FC1Option, FlangOption]>,
MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
Expand Down Expand Up @@ -2300,11 +2302,18 @@ defm fixed_point : BoolFOption<"fixed-point",
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
BothFlags<[], [ClangOption], " fixed point types">>;
defm cxx_static_destructors : BoolFOption<"c++-static-destructors",
LangOpts<"RegisterStaticDestructors">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option],
"Disable C++ static destructor registration">,
PosFlag<SetTrue>>;
def cxx_static_destructors_EQ : Joined<["-"], "fc++-static-destructors=">, Group<f_Group>,
HelpText<"Controls which variables C++ static destructors are registered for">,
Values<"all,thread-local,none">,
NormalizedValues<["All", "ThreadLocal", "None"]>,
NormalizedValuesScope<"LangOptions::RegisterStaticDestructorsKind">,
MarshallingInfoEnum<LangOpts<"RegisterStaticDestructors">, "All">,
Visibility<[ClangOption, CC1Option]>;
def cxx_static_destructors : Flag<["-"], "fc++-static-destructors">, Group<f_Group>,
Alias<cxx_static_destructors_EQ>, AliasArgs<["all"]>;
def no_cxx_static_destructors : Flag<["-"], "fno-c++-static-destructors">, Group<f_Group>,
Alias<cxx_static_destructors_EQ>, AliasArgs<["none"]>,
HelpText<"Disable C++ static destructor registration">;
def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<CodeGenOpts<"SymbolPartition">>;
Expand Down Expand Up @@ -2565,6 +2574,11 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
"Disable">,
BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
Group<f_clang_Group>;
def fsanitize_undefined_ignore_overflow_pattern_EQ : CommaJoined<["-"], "fsanitize-undefined-ignore-overflow-pattern=">,
HelpText<"Specify the overflow patterns to exclude from artihmetic sanitizer instrumentation">,
Visibility<[ClangOption, CC1Option]>,
Values<"none,all,add-unsigned-overflow-test,add-signed-overflow-test,negated-unsigned-const,unsigned-post-decr-while">,
MarshallingInfoStringVector<LangOpts<"OverflowPatternExclusionValues">>;
def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access">,
Group<f_clang_Group>,
HelpText<"Enable memory access instrumentation in ThreadSanitizer (default)">;
Expand Down Expand Up @@ -2756,9 +2770,13 @@ defm gnu89_inline : BoolFOption<"gnu89-inline",
NegFlag<SetFalse>>, ShouldParseIf<!strconcat("!", cplusplus.KeyPath)>;
def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group<f_Group>,
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
// This used to be a standalone flag but is now mapped to
// -Wno-error=invalid-gnu-asm-cast, which is the only thing the flag used to
// control.
def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoFlag<LangOpts<"HeinousExtensions">>;
Alias<W_Joined>, AliasArgs<["no-error=invalid-gnu-asm-cast"]>,
HelpText<"(Deprecated) Controls whether '-Winvalid-gnu-asm-cast' defaults to "
"an error or a warning">;
def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>,
Group<Link_Group>;
def : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
Expand Down Expand Up @@ -5028,8 +5046,8 @@ def mexception_handing : Flag<["-"], "mexception-handling">, Group<m_wasm_Featur
def mno_exception_handing : Flag<["-"], "mno-exception-handling">, Group<m_wasm_Features_Group>;
def mextended_const : Flag<["-"], "mextended-const">, Group<m_wasm_Features_Group>;
def mno_extended_const : Flag<["-"], "mno-extended-const">, Group<m_wasm_Features_Group>;
def mhalf_precision : Flag<["-"], "mhalf-precision">, Group<m_wasm_Features_Group>;
def mno_half_precision : Flag<["-"], "mno-half-precision">, Group<m_wasm_Features_Group>;
def mfp16 : Flag<["-"], "mfp16">, Group<m_wasm_Features_Group>;
def mno_fp16 : Flag<["-"], "mno-fp16">, Group<m_wasm_Features_Group>;
def mmultimemory : Flag<["-"], "mmultimemory">, Group<m_wasm_Features_Group>;
def mno_multimemory : Flag<["-"], "mno-multimemory">, Group<m_wasm_Features_Group>;
def mmultivalue : Flag<["-"], "mmultivalue">, Group<m_wasm_Features_Group>;
Expand Down Expand Up @@ -5383,7 +5401,9 @@ def mmadd4 : Flag<["-"], "mmadd4">, Group<m_mips_Features_Group>,
def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_mips_Features_Group>,
HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">;
def mmsa : Flag<["-"], "mmsa">, Group<m_mips_Features_Group>,
HelpText<"Enable MSA ASE (MIPS only)">;
Visibility<[ClangOption, CC1Option, CC1AsOption]>,
HelpText<"Enable MSA ASE (MIPS only)">,
MarshallingInfoFlag<CodeGenOpts<"MipsMsa">>;
def mno_msa : Flag<["-"], "mno-msa">, Group<m_mips_Features_Group>,
HelpText<"Disable MSA ASE (MIPS only)">;
def mmt : Flag<["-"], "mmt">, Group<m_mips_Features_Group>,
Expand Down Expand Up @@ -6148,6 +6168,10 @@ def mv8plus : Flag<["-"], "mv8plus">, Group<m_sparc_Features_Group>,
HelpText<"Enable V8+ mode, allowing use of 64-bit V9 instructions in 32-bit code">;
def mno_v8plus : Flag<["-"], "mno-v8plus">, Group<m_sparc_Features_Group>,
HelpText<"Disable V8+ mode">;
def mfix_gr712rc : Flag<["-"], "mfix-gr712rc">, Group<m_sparc_Features_Group>,
HelpText<"Enable workarounds for GR712RC errata">;
def mfix_ut700 : Flag<["-"], "mfix-ut700">, Group<m_sparc_Features_Group>,
HelpText<"Enable workarounds for UT700 errata">;
foreach i = 1 ... 7 in
def ffixed_g#i : Flag<["-"], "ffixed-g"#i>, Group<m_sparc_Features_Group>,
HelpText<"Reserve the G"#i#" register (SPARC only)">;
Expand Down Expand Up @@ -7131,6 +7155,12 @@ def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">,
def crel : Flag<["--"], "crel">,
HelpText<"Enable CREL relocation format (ELF only)">,
MarshallingInfoFlag<CodeGenOpts<"Crel">>;
def mmapsyms_implicit : Flag<["-"], "mmapsyms=implicit">,
HelpText<"Allow mapping symbol at section beginning to be implicit, "
"lowering number of mapping symbols at the expense of some "
"portability. Recommended for projects that can build all their "
"object files using this option">,
MarshallingInfoFlag<CodeGenOpts<"ImplicitMapSyms">>;
def mrelax_relocations_no : Flag<["-"], "mrelax-relocations=no">,
HelpText<"Disable x86 relax relocations">,
MarshallingInfoNegativeFlag<CodeGenOpts<"X86RelaxRelocations">>;
Expand Down Expand Up @@ -7959,7 +7989,7 @@ def fapply_global_visibility_to_externs : Flag<["-"], "fapply-global-visibility-
MarshallingInfoFlag<LangOpts<"SetVisibilityForExternDecls">>;
def fbracket_depth : Separate<["-"], "fbracket-depth">,
HelpText<"Maximum nesting level for parentheses, brackets, and braces">,
MarshallingInfoInt<LangOpts<"BracketDepth">, "2048">;
MarshallingInfoInt<LangOpts<"BracketDepth">, "256">;
defm const_strings : BoolOption<"f", "const-strings",
LangOpts<"ConstStrings">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use">,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/SanitizerArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SanitizerArgs {
std::vector<std::string> BinaryMetadataIgnorelistFiles;
int CoverageFeatures = 0;
int BinaryMetadataFeatures = 0;
int OverflowPatternExclusions = 0;
int MsanTrackOrigins = 0;
bool MsanUseAfterDtor = true;
bool MsanParamRetval = true;
Expand Down Expand Up @@ -106,6 +107,7 @@ class SanitizerArgs {
bool needsNsanRt() const {
return Sanitizers.has(SanitizerKind::NumericalStability);
}
bool needsRtsanRt() const { return Sanitizers.has(SanitizerKind::Realtime); }

bool hasMemTag() const {
return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals();
Expand Down
50 changes: 33 additions & 17 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ struct FormatStyle {

/// If the function declaration doesn't fit on a line,
/// allow putting all parameters of a function declaration onto
/// the next line even if ``BinPackParameters`` is ``false``.
/// the next line even if ``BinPackParameters`` is ``OnePerLine``.
/// \code
/// true:
/// void myFunction(
Expand Down Expand Up @@ -1192,20 +1192,36 @@ struct FormatStyle {
/// \version 3.7
bool BinPackArguments;

/// If ``false``, a function declaration's or function definition's
/// parameters will either all be on the same line or will have one line each.
/// \code
/// true:
/// void f(int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaa,
/// int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
///
/// false:
/// void f(int aaaaaaaaaaaaaaaaaaaa,
/// int aaaaaaaaaaaaaaaaaaaa,
/// int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
/// \endcode
/// Different way to try to fit all parameters on a line.
enum BinPackParametersStyle : int8_t {
/// Bin-pack parameters.
/// \code
/// void f(int a, int bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
/// int ccccccccccccccccccccccccccccccccccccccccccc);
/// \endcode
BPPS_BinPack,
/// Put all parameters on the current line if they fit.
/// Otherwise, put each one on its own line.
/// \code
/// void f(int a, int b, int c);
///
/// void f(int a,
/// int b,
/// int ccccccccccccccccccccccccccccccccccccc);
/// \endcode
BPPS_OnePerLine,
/// Always put each parameter on its own line.
/// \code
/// void f(int a,
/// int b,
/// int c);
/// \endcode
BPPS_AlwaysOnePerLine,
};

/// The bin pack parameters style to use.
/// \version 3.7
bool BinPackParameters;
BinPackParametersStyle BinPackParameters;

/// Styles for adding spacing around ``:`` in bitfield definitions.
enum BitFieldColonSpacingStyle : int8_t {
Expand Down Expand Up @@ -3414,7 +3430,7 @@ struct FormatStyle {
/// items into as few lines as possible when they go over ``ColumnLimit``.
///
/// If ``Auto`` (the default), delegates to the value in
/// ``BinPackParameters``. If that is ``true``, bin-packs Objective-C
/// ``BinPackParameters``. If that is ``BinPack``, bin-packs Objective-C
/// protocol conformance list items into as few lines as possible
/// whenever they go over ``ColumnLimit``.
///
Expand All @@ -3426,13 +3442,13 @@ struct FormatStyle {
/// onto individual lines whenever they go over ``ColumnLimit``.
///
/// \code{.objc}
/// Always (or Auto, if BinPackParameters=true):
/// Always (or Auto, if BinPackParameters==BinPack):
/// @interface ccccccccccccc () <
/// ccccccccccccc, ccccccccccccc,
/// ccccccccccccc, ccccccccccccc> {
/// }
///
/// Never (or Auto, if BinPackParameters=false):
/// Never (or Auto, if BinPackParameters!=BinPack):
/// @interface ddddddddddddd () <
/// ddddddddddddd,
/// ddddddddddddd,
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3021,15 +3021,17 @@ class Parser : public CodeCompletionHandler {
SemaCodeCompletion::AttributeCompletion::None,
const IdentifierInfo *EnclosingScope = nullptr);

void MaybeParseHLSLAnnotations(Declarator &D,
bool MaybeParseHLSLAnnotations(Declarator &D,
SourceLocation *EndLoc = nullptr,
bool CouldBeBitField = false) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (Tok.is(tok::colon)) {
ParsedAttributes Attrs(AttrFactory);
ParseHLSLAnnotations(Attrs, EndLoc, CouldBeBitField);
D.takeAttributes(Attrs);
return true;
}
return false;
}

void MaybeParseHLSLAnnotations(ParsedAttributes &Attrs,
Expand Down
9 changes: 8 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -13071,12 +13071,19 @@ class Sema final : public SemaBase {
/// ForConstraintInstantiation indicates we should continue looking when
/// encountering a lambda generic call operator, and continue looking for
/// arguments on an enclosing class template.
///
/// \param SkipForSpecialization when specified, any template specializations
/// in a traversal would be ignored.
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
/// when encountering a specialized member function template, rather than
/// returning immediately.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
bool ForConstraintInstantiation = false,
bool SkipForSpecialization = false);
bool SkipForSpecialization = false,
bool ForDefaultArgumentSubstitution = false);

/// RAII object to handle the state changes required to synthesize
/// a function body.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class SemaHLSL : public SemaBase {
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);

bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);

// HLSL Type trait implementations
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
};

} // namespace clang
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,12 @@ class ASTReader
/// performed deduplication.
llvm::SetVector<NamedDecl *> PendingMergedDefinitionsToDeduplicate;

/// The duplicated definitions in module units which are pending to be warned.
/// We need to delay it to wait for the loading of definitions since we don't
/// want to warn for forward declarations.
llvm::SmallVector<std::pair<Decl *, Decl *>>
PendingWarningForDuplicatedDefsInModuleUnits;

/// Read the record that describes the lexical contents of a DC.
bool ReadLexicalDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor,
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,11 @@ ANALYZER_OPTION(
ANALYZER_OPTION(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
"The maximum complexity of symbolic constraint.", 35)

// HACK:https://discourse.llvm.org/t/rfc-make-istainted-and-complex-symbols-friends/79570
// Ideally, we should get rid of this option soon.
ANALYZER_OPTION(unsigned, MaxTaintedSymbolComplexity, "max-tainted-symbol-complexity",
"[DEPRECATED] The maximum complexity of a symbol to carry taint", 9)

ANALYZER_OPTION(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
"The maximum times a large function could be inlined.", 32)

Expand Down
75 changes: 51 additions & 24 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,34 +885,60 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
if (!LT || !RT)
return false;

// Visit the given pointer expression and optionally convert to a PT_Ptr.
auto visitAsPointer = [&](const Expr *E, PrimType T) -> bool {
if (!this->visit(E))
return false;
if (T != PT_Ptr)
return this->emitDecayPtr(T, PT_Ptr, E);
return true;
};

if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
if (Op != BO_Sub)
return false;

assert(E->getType()->isIntegerType());
if (!visit(RHS) || !visit(LHS))
if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))
return false;

return this->emitSubPtr(classifyPrim(E->getType()), E);
}

PrimType OffsetType;
if (LHS->getType()->isIntegerType()) {
if (!visit(RHS) || !visit(LHS))
if (!visitAsPointer(RHS, *RT))
return false;
if (!this->visit(LHS))
return false;
OffsetType = *LT;
} else if (RHS->getType()->isIntegerType()) {
if (!visit(LHS) || !visit(RHS))
if (!visitAsPointer(LHS, *LT))
return false;
if (!this->visit(RHS))
return false;
OffsetType = *RT;
} else {
return false;
}

if (Op == BO_Add)
return this->emitAddOffset(OffsetType, E);
else if (Op == BO_Sub)
return this->emitSubOffset(OffsetType, E);
// Do the operation and optionally transform to
// result pointer type.
if (Op == BO_Add) {
if (!this->emitAddOffset(OffsetType, E))
return false;

if (classifyPrim(E) != PT_Ptr)
return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
return true;
} else if (Op == BO_Sub) {
if (!this->emitSubOffset(OffsetType, E))
return false;

if (classifyPrim(E) != PT_Ptr)
return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
return true;
}

return false;
}
Expand Down Expand Up @@ -1318,14 +1344,15 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
const Expr *ArrayFiller, const Expr *E) {

QualType QT = E->getType();

if (const auto *AT = QT->getAs<AtomicType>())
QT = AT->getValueType();

if (QT->isVoidType())
if (QT->isVoidType()) {
if (Inits.size() == 0)
return true;
return this->emitInvalid(E);
}

// Handle discarding first.
if (DiscardResult) {
Expand Down Expand Up @@ -2556,7 +2583,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {

if (DiscardResult)
return this->emitPopPtr(E);
return true;
return this->emitFinishInit(E);
}

if (T->isArrayType()) {
Expand Down Expand Up @@ -3238,9 +3265,6 @@ template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
}

template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
if (E->containsErrors())
return this->emitError(E);

// We're basically doing:
// OptionScope<Emitter> Scope(this, DicardResult, Initializing);
// but that's unnecessary of course.
Expand Down Expand Up @@ -3277,9 +3301,6 @@ template <class Emitter>
bool Compiler<Emitter>::visitInitializer(const Expr *E) {
assert(!classify(E->getType()));

if (E->containsErrors())
return this->emitError(E);

if (!this->checkLiteralType(E))
return false;

Expand Down Expand Up @@ -4364,11 +4385,6 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
}

template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
if (IS->isNonNegatedConsteval())
return visitStmt(IS->getThen());
if (IS->isNegatedConsteval())
return IS->getElse() ? visitStmt(IS->getElse()) : true;

if (auto *CondInit = IS->getInit())
if (!visitStmt(CondInit))
return false;
Expand All @@ -4377,8 +4393,19 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
if (!visitDeclStmt(CondDecl))
return false;

if (!this->visitBool(IS->getCond()))
return false;
// Compile condition.
if (IS->isNonNegatedConsteval()) {
if (!this->emitIsConstantContext(IS))
return false;
} else if (IS->isNegatedConsteval()) {
if (!this->emitIsConstantContext(IS))
return false;
if (!this->emitInv(IS))
return false;
} else {
if (!this->visitBool(IS->getCond()))
return false;
}

if (const Stmt *Else = IS->getElse()) {
LabelTy LabelElse = this->getLabel();
Expand Down
23 changes: 10 additions & 13 deletions clang/lib/AST/ByteCode/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) {
}

template <typename T>
static void moveTy(Block *, const std::byte *Src, std::byte *Dst,
static void moveTy(Block *, std::byte *Src, std::byte *Dst,
const Descriptor *) {
// FIXME: Get rid of the const_cast.
auto *SrcPtr = reinterpret_cast<T *>(const_cast<std::byte *>(Src));
auto *SrcPtr = reinterpret_cast<T *>(Src);
auto *DstPtr = reinterpret_cast<T *>(Dst);
new (DstPtr) T(std::move(*SrcPtr));
}
Expand Down Expand Up @@ -63,11 +62,9 @@ static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) {
}

template <typename T>
static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst,
static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst,
const Descriptor *D) {
// FIXME: Get rid of the const_cast.
InitMapPtr &SrcIMP =
*reinterpret_cast<InitMapPtr *>(const_cast<std::byte *>(Src));
InitMapPtr &SrcIMP = *reinterpret_cast<InitMapPtr *>(Src);
if (SrcIMP) {
// We only ever invoke the moveFunc when moving block contents to a
// DeadBlock. DeadBlocks don't need InitMaps, so we destroy them here.
Expand All @@ -76,7 +73,7 @@ static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst,
Src += sizeof(InitMapPtr);
Dst += sizeof(InitMapPtr);
for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
auto *SrcPtr = &reinterpret_cast<T *>(const_cast<std::byte *>(Src))[I];
auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];
auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
new (DstPtr) T(std::move(*SrcPtr));
}
Expand Down Expand Up @@ -126,19 +123,19 @@ static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) {
}
}

static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst,
static void moveArrayDesc(Block *B, std::byte *Src, std::byte *Dst,
const Descriptor *D) {
const unsigned NumElems = D->getNumElems();
const unsigned ElemSize =
D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);

unsigned ElemOffset = 0;
for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
const auto *SrcPtr = Src + ElemOffset;
auto *SrcPtr = Src + ElemOffset;
auto *DstPtr = Dst + ElemOffset;

const auto *SrcDesc = reinterpret_cast<const InlineDescriptor *>(SrcPtr);
const auto *SrcElemLoc = reinterpret_cast<const std::byte *>(SrcDesc + 1);
auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr);
auto *SrcElemLoc = reinterpret_cast<std::byte *>(SrcDesc + 1);
auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr);
auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1);

Expand Down Expand Up @@ -233,7 +230,7 @@ static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
destroyBase(B, Ptr, F.Desc, F.Offset);
}

static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst,
static void moveRecord(Block *B, std::byte *Src, std::byte *Dst,
const Descriptor *D) {
assert(D);
assert(D->ElemRecord);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ using BlockDtorFn = void (*)(Block *Storage, std::byte *FieldPtr,
/// blocks are persisted: the move function copies all inline descriptors and
/// non-trivial fields, as existing pointers might need to reference those
/// descriptors. Data is not copied since it cannot be legally read.
using BlockMoveFn = void (*)(Block *Storage, const std::byte *SrcFieldPtr,
using BlockMoveFn = void (*)(Block *Storage, std::byte *SrcFieldPtr,
std::byte *DstFieldPtr,
const Descriptor *FieldDesc);

Expand Down
13 changes: 9 additions & 4 deletions clang/lib/AST/ByteCode/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,16 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
if (ConvertResultToRValue) {
if (!Ptr.isZero() && !Ptr.isDereferencable())
return false;

if (S.getLangOpts().CPlusPlus11 && Ptr.isBlockPointer() &&
!CheckFinalLoad(S, OpPC, Ptr)) {
return false;
}

// Never allow reading from a non-const pointer, unless the memory
// has been created in this evaluation.
if (!Ptr.isZero() && Ptr.isBlockPointer() &&
Ptr.block()->getEvalID() != Ctx.getEvalID() &&
(!CheckLoad(S, OpPC, Ptr, AK_Read) || !Ptr.isConst()))
if (!Ptr.isZero() && !Ptr.isConst() && Ptr.isBlockPointer() &&
Ptr.block()->getEvalID() != Ctx.getEvalID())
return false;

if (std::optional<APValue> V =
Expand Down Expand Up @@ -214,7 +219,7 @@ bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
return false;

if (std::optional<APValue> APV =
Ptr.toRValue(S.getCtx(), EvalResult.getSourceType())) {
Ptr.toRValue(S.getASTContext(), EvalResult.getSourceType())) {
EvalResult.setValue(*APV);
return true;
}
Expand Down
43 changes: 43 additions & 0 deletions clang/lib/AST/ByteCode/FunctionPointer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===----------------------- FunctionPointer.cpp ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "FunctionPointer.h"

namespace clang {
namespace interp {

APValue FunctionPointer::toAPValue(const ASTContext &) const {
if (!Func)
return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/true);

if (!Valid)
return APValue(static_cast<Expr *>(nullptr),
CharUnits::fromQuantity(getIntegerRepresentation()), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);

if (Func->getDecl())
return APValue(Func->getDecl(), CharUnits::fromQuantity(Offset), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
return APValue(Func->getExpr(), CharUnits::fromQuantity(Offset), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
}

void FunctionPointer::print(llvm::raw_ostream &OS) const {
OS << "FnPtr(";
if (Func && Valid)
OS << Func->getName();
else if (Func)
OS << reinterpret_cast<uintptr_t>(Func);
else
OS << "nullptr";
OS << ") + " << Offset;
}

} // namespace interp
} // namespace clang
41 changes: 10 additions & 31 deletions clang/lib/AST/ByteCode/FunctionPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,29 @@

#include "Function.h"
#include "Primitives.h"
#include "clang/AST/APValue.h"

namespace clang {
class ASTContext;
class APValue;
namespace interp {

class FunctionPointer final {
private:
const Function *Func;
uint64_t Offset;
bool Valid;

public:
FunctionPointer() = default;
FunctionPointer(const Function *Func) : Func(Func), Valid(true) {}
FunctionPointer(const Function *Func, uint64_t Offset = 0)
: Func(Func), Offset(Offset), Valid(true) {}

FunctionPointer(uintptr_t IntVal, const Descriptor *Desc = nullptr)
: Func(reinterpret_cast<const Function *>(IntVal)), Valid(false) {}
: Func(reinterpret_cast<const Function *>(IntVal)), Offset(0),
Valid(false) {}

const Function *getFunction() const { return Func; }
uint64_t getOffset() const { return Offset; }
bool isZero() const { return !Func; }
bool isValid() const { return Valid; }
bool isWeak() const {
Expand All @@ -39,33 +43,8 @@ class FunctionPointer final {
return Func->getDecl()->isWeak();
}

APValue toAPValue(const ASTContext &) const {
if (!Func)
return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/true);

if (!Valid)
return APValue(static_cast<Expr *>(nullptr),
CharUnits::fromQuantity(getIntegerRepresentation()), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);

if (Func->getDecl())
return APValue(Func->getDecl(), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
return APValue(Func->getExpr(), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
}

void print(llvm::raw_ostream &OS) const {
OS << "FnPtr(";
if (Func && Valid)
OS << Func->getName();
else if (Func)
OS << reinterpret_cast<uintptr_t>(Func);
else
OS << "nullptr";
OS << ")";
}
APValue toAPValue(const ASTContext &) const;
void print(llvm::raw_ostream &OS) const;

std::string toDiagnosticString(const ASTContext &Ctx) const {
if (!Func)
Expand All @@ -79,7 +58,7 @@ class FunctionPointer final {
}

ComparisonCategoryResult compare(const FunctionPointer &RHS) const {
if (Func == RHS.Func)
if (Func == RHS.Func && Offset == RHS.Offset)
return ComparisonCategoryResult::Equal;
return ComparisonCategoryResult::Unordered;
}
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/AST/ByteCode/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,24 @@ template <bool Signed> class IntegralAP final {
APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); }

bool isZero() const { return V.isZero(); }
bool isPositive() const { return V.isNonNegative(); }
bool isNegative() const { return !V.isNonNegative(); }
bool isPositive() const {
if constexpr (Signed)
return V.isNonNegative();
return true;
}
bool isNegative() const {
if constexpr (Signed)
return !V.isNonNegative();
return false;
}
bool isMin() const { return V.isMinValue(); }
bool isMax() const { return V.isMaxValue(); }
static constexpr bool isSigned() { return Signed; }
bool isMinusOne() const { return Signed && V == -1; }

unsigned countLeadingZeros() const { return V.countl_zero(); }

void print(llvm::raw_ostream &OS) const { OS << V; }
void print(llvm::raw_ostream &OS) const { V.print(OS, Signed);}
std::string toDiagnosticString(const ASTContext &Ctx) const {
std::string NameStr;
llvm::raw_string_ostream OS(NameStr);
Expand Down
35 changes: 30 additions & 5 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
auto IsConstType = [&S](const VarDecl *VD) -> bool {
QualType T = VD->getType();

if (T.isConstant(S.getCtx()))
if (T.isConstant(S.getASTContext()))
return true;

if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
Expand Down Expand Up @@ -523,9 +523,9 @@ bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
assert(S.getLangOpts().CPlusPlus);
const auto *VD = cast<VarDecl>(Ptr.getDeclDesc()->asValueDecl());
if ((!VD->hasConstantInitialization() &&
VD->mightBeUsableInConstantExpressions(S.getCtx())) ||
VD->mightBeUsableInConstantExpressions(S.getASTContext())) ||
(S.getLangOpts().OpenCL && !S.getLangOpts().CPlusPlus11 &&
!VD->hasICEInitializer(S.getCtx()))) {
!VD->hasICEInitializer(S.getASTContext()))) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at);
Expand Down Expand Up @@ -559,6 +559,31 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return true;
}

/// This is not used by any of the opcodes directly. It's used by
/// EvalEmitter to do the final lvalue-to-rvalue conversion.
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckConstant(S, OpPC, Ptr))
return false;

if (!CheckDummy(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckExtern(S, OpPC, Ptr))
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckActive(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckMutable(S, OpPC, Ptr))
return false;
return true;
}

bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
return false;
Expand Down Expand Up @@ -772,7 +797,7 @@ bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, bool NewWasArray,
// but we want to get the array size right.
if (D->isArray()) {
QualType ElemQT = D->getType()->getPointeeType();
TypeToDiagnose = S.getCtx().getConstantArrayType(
TypeToDiagnose = S.getASTContext().getConstantArrayType(
ElemQT, APInt(64, static_cast<uint64_t>(D->getNumElems()), false),
nullptr, ArraySizeModifier::Normal, 0);
} else
Expand All @@ -794,7 +819,7 @@ bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
// Whatever this is, we didn't heap allocate it.
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
<< Ptr.toDiagnosticString(S.getCtx());
<< Ptr.toDiagnosticString(S.getASTContext());

if (Ptr.isTemporary())
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
Expand Down
Loading