65 changes: 65 additions & 0 deletions bolt/test/AArch64/internal-call.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## Test that llvm-bolt detects internal calls and marks the containing function
## as non-simple.

# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -static
# RUN: llvm-bolt %t.exe -o %t.null --print-all 2>&1 | FileCheck %s

# CHECK: Binary Function "_start" after building cfg
# CHECK: internal call detected in function _start
# CHECK-NOT: Binary Function "_start" after validate-internal-calls

.text
.globl _start
.type _start, %function
_start:
.cfi_startproc
.LBB00:
mov x11, #0x1fff
cmp x1, x11
b.hi .Ltmp1

.entry1:
movi v4.16b, #0x0
movi v5.16b, #0x0
subs x1, x1, #0x8
b.lo .Ltmp2

.entry2:
ld1 { v2.2d, v3.2d }, [x0], #32
ld1 { v0.2d, v1.2d }, [x0], #32

.Ltmp2:
uaddlp v4.4s, v4.8h
uaddlp v4.2d, v4.4s
mov x0, v4.d[0]
mov x1, v4.d[1]
add x0, x0, x1
ret x30

.Ltmp1:
mov x8, x30

.Lloop:
add x5, x0, x9
mov x1, #0xface
movi v4.16b, #0x0
movi v5.16b, #0x0
bl .entry2
add x4, x4, x0
mov x0, x5
sub x7, x7, x10
cmp x7, x11
b.hi .Lloop

mov x1, x7
bl .entry1
add x0, x4, x0
mov x30, x8
ret x30

.cfi_endproc
.size _start, .-_start

## Force relocation mode.
.reloc 0, R_AARCH64_NONE
6 changes: 4 additions & 2 deletions bolt/test/X86/end-symbol.test
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# RUN: yaml2obj %p/Inputs/plt-sec.yaml &> %t.exe
# RUN: llvm-bolt %t.exe -o %t.out
# RUN: (llvm-readelf --program-headers %t.out | grep LOAD | tail -n 1 ; llvm-nm %t.out) \
# RUN: | FileCheck %s

# RUN: llvm-readelf --program-headers %t.out | grep LOAD | tail -n 1 > %t.load
# RUN: llvm-nm %t.out >> %t.load
# RUN: FileCheck %s < %t.load

## Check that llvm-bolt correctly updates _end symbol to match the end of the
## last loadable segment.
Expand Down
5 changes: 3 additions & 2 deletions bolt/test/X86/instrumentation-eh_frame_hdr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
// RUN: %clangxx %cxxflags -static -Wl,-q %s -o %t.exe -Wl,--entry=_start
// RUN: llvm-bolt %t.exe -o %t.instr -instrument \
// RUN: --instrumentation-file=%t.fdata -instrumentation-sleep-time=1
// RUN: (llvm-readelf -SW %t.instr | grep -v bolt; llvm-readelf -lW %t.instr | \
// RUN: grep LOAD | tail -n 1) | FileCheck %s
// RUN: llvm-readelf -SW %t.instr | grep -v bolt > %t.sections
// RUN: llvm-readelf -lW %t.instr | grep LOAD | tail -n 1 >> %t.sections
// RUN: FileCheck %s < %t.sections

// CHECK: {{.*}} .eh_frame_hdr PROGBITS [[#%x, EH_ADDR:]]
// CHECK: LOAD 0x[[#%x, LD_OFFSET:]] 0x[[#%x, LD_VADDR:]] 0x[[#%x, LD_FSIZE:]]
Expand Down
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
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
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>)
83 changes: 61 additions & 22 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 Down Expand Up @@ -174,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 @@ -212,6 +220,11 @@ Attribute Changes in Clang
- ``[[clang::lifetimebound]]`` is now explicitly disallowed on explicit object member functions
where they were previously silently ignored.

- Clang now automatically adds ``[[clang::lifetimebound]]`` to the parameters of
``std::span, std::string_view`` constructors, this enables Clang to capture
more cases where the returned reference outlives the object.
(#GH100567)

Improvements to Clang's diagnostics
-----------------------------------

Expand Down Expand Up @@ -241,6 +254,18 @@ Improvements to Clang's diagnostics

- 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 @@ -296,6 +321,9 @@ Bug Fixes to C++ Support
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)
- Clang now correctly handles direct-list-initialization of a structured bindings from an array. (#GH31813)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -452,31 +480,42 @@ 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-overflow-test``, ``negated-unsigned-const``, and
``post-decr-while``. The sanitizer instrumentation can be toggled off for all
available patterns by specifying ``all``. Conversely, you can disable all
exclusions with ``none``.
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-overflow-test``
/// 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=post-decr-while``
/// 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
while (count--) { /* ... */ } // No longer causes unsigned-integer-overflow sanitizer to trip
}
Many existing projects have a large amount of these code patterns present.
Expand Down
3 changes: 3 additions & 0 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
37 changes: 30 additions & 7 deletions clang/docs/UndefinedBehaviorSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -314,26 +314,49 @@ Currently, this option supports three overflow-dependent code idioms:
unsigned long foo = -1UL; // No longer causes a negation overflow warning
unsigned long bar = -2UL; // and so on...

``post-decr-while``
``unsigned-post-decr-while``

.. code-block:: c++

/// -fsanitize-undefined-ignore-overflow-pattern=post-decr-while
/// -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-overflow-test``
``add-signed-overflow-test,add-unsigned-overflow-test``

.. code-block:: c++

/// -fsanitize-undefined-ignore-overflow-pattern=add-overflow-test
/// -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 (same for signed types)
// 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``. Specifying ``none``
has precedence over other values.
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
13 changes: 9 additions & 4 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -950,10 +950,13 @@ treated as a file name and is searched for sequentially in the directories:
- system directory,
- the directory where Clang executable resides.

Both user and system directories for configuration files are specified during
clang build using CMake parameters, ``CLANG_CONFIG_FILE_USER_DIR`` and
``CLANG_CONFIG_FILE_SYSTEM_DIR`` respectively. The first file found is used.
It is an error if the required file cannot be found.
Both user and system directories for configuration files can be specified
either during build or during runtime. At build time, use
``CLANG_CONFIG_FILE_USER_DIR`` and ``CLANG_CONFIG_FILE_SYSTEM_DIR``. At run
time use the ``--config-user-dir=`` and ``--config-system-dir=`` command line
options. Specifying config directories at runtime overrides the config
directories set at build time The first file found is used. It is an error if
the required file cannot be found.

The default configuration files are searched for in the same directories
following the rules described in the next paragraphs. Loading default
Expand Down Expand Up @@ -2068,6 +2071,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
22 changes: 19 additions & 3 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ if ((y = make_int())) {
nullability
^^^^^^^^^^^
Objective C checkers that warn for null pointer passing and dereferencing errors.
Checkers (mostly Objective C) that warn for null pointer passing and dereferencing errors.
.. _nullability-NullPassedToNonnull:
Expand All @@ -588,8 +588,8 @@ Warns when a null pointer is passed to a pointer which has a _Nonnull type.
.. _nullability-NullReturnedFromNonnull:
nullability.NullReturnedFromNonnull (ObjC)
""""""""""""""""""""""""""""""""""""""""""
nullability.NullReturnedFromNonnull (C, C++, ObjC)
""""""""""""""""""""""""""""""""""""""""""""""""""
Warns when a null pointer is returned from a function that has _Nonnull return type.
.. code-block:: objc
Expand All @@ -604,6 +604,22 @@ Warns when a null pointer is returned from a function that has _Nonnull return t
return result;
}
Warns when a null pointer is returned from a function annotated with ``__attribute__((returns_nonnull))``
.. code-block:: cpp
int global;
__attribute__((returns_nonnull)) void* getPtr(void* p);
void* getPtr(void* p) {
if (p) { // forgot to negate the condition
return &global;
}
// Warning: nullptr returned from a function that is expected
// to return a non-null value
return p;
}
.. _nullability-NullableDereferenced:
nullability.NullableDereferenced (ObjC)
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
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4538,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 @@ -4622,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
86 changes: 56 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
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
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -974,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
18 changes: 15 additions & 3 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,13 @@ class LangOptionsBase {
/// Exclude all overflow patterns (below)
All = 1 << 1,
/// if (a + b < a)
AddOverflowTest = 1 << 2,
AddSignedOverflowTest = 1 << 2,
/// if (a + b < a)
AddUnsignedOverflowTest = 1 << 3,
/// -1UL
NegUnsignedConst = 1 << 3,
NegUnsignedConst = 1 << 4,
/// while (count--)
PostDecrInWhile = 1 << 4,
PostDecrInWhile = 1 << 5,
};

enum class DefaultVisiblityExportMapping {
Expand Down Expand Up @@ -456,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
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
31 changes: 22 additions & 9 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 @@ -2568,7 +2577,7 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
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-overflow-test,negated-unsigned-const,post-decr-while">,
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>,
Expand Down Expand Up @@ -2761,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 @@ -7976,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
1 change: 1 addition & 0 deletions clang/include/clang/Driver/SanitizerArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,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
4 changes: 2 additions & 2 deletions clang/include/clang/ExtractAPI/DeclarationFragments.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,9 @@ class DeclarationFragmentsBuilder {
/// Build DeclarationFragments for a macro.
///
/// \param Name name of the macro.
/// \param MD the associated MacroDirective.
/// \param MI the associated MacroInfo.
static DeclarationFragments getFragmentsForMacro(StringRef Name,
const MacroDirective *MD);
const MacroInfo *MI);

/// Build DeclarationFragments for a typedef \p TypedefNameDecl.
static DeclarationFragments
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {

StringRef getOwningModuleName(const Decl &D) {
if (auto *OwningModule = D.getImportedOwningModule())
return OwningModule->Name;
return OwningModule->getTopLevelModule()->Name;

return {};
}
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
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/Initialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,11 @@ class InitializationSequence {

void AddParenthesizedListInitStep(QualType T);

/// Only used when initializing structured bindings from an array with
/// direct-list-initialization. Unwrap the initializer list to get the array
/// for array copy.
void AddUnwrapInitListInitStep(InitListExpr *Syntactic);

/// Add steps to unwrap a initializer list for a reference around a
/// single element and rewrap it at the end.
void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,9 @@ class Sema final : public SemaBase {
/// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);

/// Add [[clang:::lifetimebound]] attr for std:: functions and methods.
void inferLifetimeBoundAttribute(FunctionDecl *FD);

/// Add [[gsl::Pointer]] attributes for std:: types.
void inferGslPointerAttribute(TypedefNameDecl *TD);

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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines CheckerVisitor.
// This file defines various utilities used by checkers.
//
//===----------------------------------------------------------------------===//

Expand Down Expand Up @@ -114,6 +114,10 @@ OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,

std::optional<SVal> getPointeeVal(SVal PtrSVal, ProgramStateRef State);

/// Returns true if declaration \p D is in std namespace or any nested namespace
/// or class scope.
bool isWithinStdNamespace(const Decl *D);

} // namespace ento

} // namespace clang
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ class ExprEngine {
const Stmt *DiagnosticStmt = nullptr,
ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);

/// A tag to track convenience transitions, which can be removed at cleanup.
/// This tag applies to a node created after removeDead.
static const ProgramPointTag *cleanupNodeTag();

/// processCFGElement - Called by CoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a CFG element.
void processCFGElement(const CFGElement E, ExplodedNode *Pred,
Expand Down
32 changes: 16 additions & 16 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,16 @@ 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 (Inits.size() == 0)
return true;
return this->emitInvalid(E);
}

// Handle discarding first.
if (DiscardResult) {
for (const Expr *Init : Inits) {
Expand All @@ -1353,13 +1363,6 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
return true;
}

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

if (QT->isVoidType())
return this->emitInvalid(E);

// Primitive values.
if (std::optional<PrimType> T = classify(QT)) {
assert(!DiscardResult);
Expand Down Expand Up @@ -3262,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 All @@ -3275,9 +3275,12 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
if (E->getType().isNull())
return false;

if (E->getType()->isVoidType())
return this->discard(E);

// Create local variable to hold the return value.
if (!E->getType()->isVoidType() && !E->isGLValue() &&
!E->getType()->isAnyComplexType() && !classify(E->getType())) {
if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
!classify(E->getType())) {
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
Expand All @@ -3298,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 @@ -5177,7 +5177,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
// We should already have a pointer when we get here.
return this->delegate(SubExpr);
case UO_Deref: // *x
if (DiscardResult || E->getType()->isVoidType())
if (DiscardResult)
return this->discard(SubExpr);
return this->visit(SubExpr);
case UO_Not: // ~x
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
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,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
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
10 changes: 5 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 @@ -797,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 @@ -819,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
71 changes: 41 additions & 30 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ using APSInt = llvm::APSInt;
/// Convert a value to an APValue.
template <typename T>
bool ReturnValue(const InterpState &S, const T &V, APValue &R) {
R = V.toAPValue(S.getCtx());
R = V.toAPValue(S.getASTContext());
return true;
}

Expand Down Expand Up @@ -231,12 +231,12 @@ bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
// constructing the array, we catch this here.
SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
if (NumElements->toAPSInt().getActiveBits() >
ConstantArrayType::getMaxSizeBits(S.getCtx()) ||
ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
*NumElements > MaxElements) {
if (!IsNoThrow) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
<< NumElements->toDiagnosticString(S.getCtx());
<< NumElements->toDiagnosticString(S.getASTContext());
}
return false;
}
Expand Down Expand Up @@ -517,12 +517,19 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {

// Den = real(RHS)² + imag(RHS)²
T A, B;
if (T::mul(RHSR, RHSR, Bits, &A) || T::mul(RHSI, RHSI, Bits, &B))
return false;
if (T::mul(RHSR, RHSR, Bits, &A) || T::mul(RHSI, RHSI, Bits, &B)) {
// Ignore overflow here, because that's what the current interpeter does.
}
T Den;
if (T::add(A, B, Bits, &Den))
return false;

if (Compare(Den, Zero) == ComparisonCategoryResult::Equal) {
const SourceInfo &E = S.Current->getSource(OpPC);
S.FFDiag(E, diag::note_expr_divide_by_zero);
return false;
}

// real(Result) = ((real(LHS) * real(RHS)) + (imag(LHS) * imag(RHS))) / Den
T &ResultR = Result.atIndex(0).deref<T>();
T &ResultI = Result.atIndex(1).deref<T>();
Expand Down Expand Up @@ -911,8 +918,8 @@ inline bool CmpHelper<FunctionPointer>(InterpState &S, CodePtr OpPC,

const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
<< LHS.toDiagnosticString(S.getCtx())
<< RHS.toDiagnosticString(S.getCtx());
<< LHS.toDiagnosticString(S.getASTContext())
<< RHS.toDiagnosticString(S.getASTContext());
return false;
}

Expand All @@ -927,7 +934,7 @@ inline bool CmpHelperEQ<FunctionPointer>(InterpState &S, CodePtr OpPC,
if (FP.isWeak()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
<< FP.toDiagnosticString(S.getCtx());
<< FP.toDiagnosticString(S.getASTContext());
return false;
}
}
Expand All @@ -945,8 +952,8 @@ inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
if (!Pointer::hasSameBase(LHS, RHS)) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
<< LHS.toDiagnosticString(S.getCtx())
<< RHS.toDiagnosticString(S.getCtx());
<< LHS.toDiagnosticString(S.getASTContext())
<< RHS.toDiagnosticString(S.getASTContext());
return false;
} else {
unsigned VL = LHS.getByteOffset();
Expand Down Expand Up @@ -974,7 +981,7 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
if (P.isWeak()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
<< P.toDiagnosticString(S.getCtx());
<< P.toDiagnosticString(S.getASTContext());
return false;
}
}
Expand All @@ -984,13 +991,13 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
RHS.getOffset() == 0) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
<< LHS.toDiagnosticString(S.getCtx());
<< LHS.toDiagnosticString(S.getASTContext());
return false;
} else if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
LHS.getOffset() == 0) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
<< RHS.toDiagnosticString(S.getCtx());
<< RHS.toDiagnosticString(S.getASTContext());
return false;
}

Expand Down Expand Up @@ -1073,8 +1080,8 @@ bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) {
// This should only happen with pointers.
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
<< LHS.toDiagnosticString(S.getCtx())
<< RHS.toDiagnosticString(S.getCtx());
<< LHS.toDiagnosticString(S.getASTContext())
<< RHS.toDiagnosticString(S.getASTContext());
return false;
}

Expand Down Expand Up @@ -1342,7 +1349,7 @@ bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
const Pointer &Ptr = S.P.getGlobal(I);

const T Value = S.Stk.peek<T>();
APValue APV = Value.toAPValue(S.getCtx());
APValue APV = Value.toAPValue(S.getASTContext());
APValue *Cached = Temp->getOrCreateValue(true);
*Cached = APV;

Expand All @@ -1369,7 +1376,7 @@ inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
std::make_pair(P.getDeclDesc()->asExpr(), Temp));

if (std::optional<APValue> APV =
P.toRValue(S.getCtx(), Temp->getTemporaryExpr()->getType())) {
P.toRValue(S.getASTContext(), Temp->getTemporaryExpr()->getType())) {
*Cached = *APV;
return true;
}
Expand Down Expand Up @@ -1404,7 +1411,8 @@ bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
return false;
const Pointer &Field = This.atField(FieldOffset);
const auto &Value = S.Stk.pop<T>();
Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
Field.deref<T>() =
Value.truncate(F->Decl->getBitWidthValue(S.getASTContext()));
Field.initialize();
return true;
}
Expand All @@ -1427,7 +1435,8 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
Field.deref<T>() =
Value.truncate(F->Decl->getBitWidthValue(S.getASTContext()));
Field.activate();
Field.initialize();
return true;
Expand Down Expand Up @@ -1477,7 +1486,7 @@ inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
return false;

if (Ptr.isIntegralPointer()) {
S.Stk.push<Pointer>(Ptr.asIntPointer().atOffset(S.getCtx(), Off));
S.Stk.push<Pointer>(Ptr.asIntPointer().atOffset(S.getASTContext(), Off));
return true;
}

Expand Down Expand Up @@ -1505,7 +1514,7 @@ inline bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
return false;

if (Ptr.isIntegralPointer()) {
S.Stk.push<Pointer>(Ptr.asIntPointer().atOffset(S.getCtx(), Off));
S.Stk.push<Pointer>(Ptr.asIntPointer().atOffset(S.getASTContext(), Off));
return true;
}

Expand Down Expand Up @@ -1721,7 +1730,7 @@ bool StoreBitField(InterpState &S, CodePtr OpPC) {
if (Ptr.canBeInitialized())
Ptr.initialize();
if (const auto *FD = Ptr.getField())
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getASTContext()));
else
Ptr.deref<T>() = Value;
return true;
Expand All @@ -1736,7 +1745,7 @@ bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
if (Ptr.canBeInitialized())
Ptr.initialize();
if (const auto *FD = Ptr.getField())
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getASTContext()));
else
Ptr.deref<T>() = Value;
return true;
Expand Down Expand Up @@ -2014,7 +2023,7 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
while (auto *AT = dyn_cast<ArrayType>(PtrT))
PtrT = AT->getElementType();

QualType ArrayTy = S.getCtx().getConstantArrayType(
QualType ArrayTy = S.getASTContext().getConstantArrayType(
PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_pointer_subtraction_zero_size)
Expand Down Expand Up @@ -2535,7 +2544,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
return false;

if (Ptr.isRoot() || !Ptr.isUnknownSizeArray() || Ptr.isDummy()) {
if (Ptr.isRoot() || !Ptr.isUnknownSizeArray()) {
S.Stk.push<Pointer>(Ptr.atIndex(0));
return true;
}
Expand Down Expand Up @@ -2608,9 +2617,11 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
// the function we're about to call is a lambda call operator,
// skip the CheckInvoke, since the ThisPtr is a null pointer
// anyway.
if (!(S.Current->getFunction() &&
S.Current->getFunction()->isLambdaStaticInvoker() &&
Func->isLambdaCallOperator())) {
if (S.Current->getFunction() &&
S.Current->getFunction()->isLambdaStaticInvoker() &&
Func->isLambdaCallOperator()) {
assert(ThisPtr.isZero());
} else {
if (!CheckInvoke(S, OpPC, ThisPtr))
return false;
}
Expand Down Expand Up @@ -2951,7 +2962,7 @@ inline bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD) {
if (VD == S.EvaluatingDecl)
return true;

if (!VD->isUsableInConstantExpressions(S.getCtx())) {
if (!VD->isUsableInConstantExpressions(S.getASTContext())) {
S.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local)
<< (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD;
return false;
Expand Down Expand Up @@ -3045,7 +3056,7 @@ static inline bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm) {
if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
<< Ptr.toDiagnosticString(S.getCtx()) << Ptr.isOnePastEnd();
<< Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();
return false;
}

Expand Down
41 changes: 21 additions & 20 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static T getParam(const InterpFrame *Frame, unsigned Index) {
}

PrimType getIntPrimType(const InterpState &S) {
const TargetInfo &TI = S.getCtx().getTargetInfo();
const TargetInfo &TI = S.getASTContext().getTargetInfo();
unsigned IntWidth = TI.getIntWidth();

if (IntWidth == 32)
Expand All @@ -49,7 +49,7 @@ PrimType getIntPrimType(const InterpState &S) {
}

PrimType getLongPrimType(const InterpState &S) {
const TargetInfo &TI = S.getCtx().getTargetInfo();
const TargetInfo &TI = S.getASTContext().getTargetInfo();
unsigned LongWidth = TI.getLongWidth();

if (LongWidth == 64)
Expand Down Expand Up @@ -272,10 +272,10 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
return false;

const llvm::fltSemantics &TargetSemantics =
S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());
S.getASTContext().getFloatTypeSemantics(F->getDecl()->getReturnType());

Floating Result;
if (S.getCtx().getTargetInfo().isNan2008()) {
if (S.getASTContext().getTargetInfo().isNan2008()) {
if (Signaling)
Result = Floating(
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
Expand Down Expand Up @@ -303,7 +303,7 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const Function *F) {
const llvm::fltSemantics &TargetSemantics =
S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());
S.getASTContext().getFloatTypeSemantics(F->getDecl()->getReturnType());

S.Stk.push<Floating>(Floating::getInf(TargetSemantics));
return true;
Expand Down Expand Up @@ -689,8 +689,8 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Arg = peekToAPSInt(S.Stk, ArgT);

int Result =
S.getCtx().getTargetInfo().getEHDataRegisterNumber(Arg.getZExtValue());
int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber(
Arg.getZExtValue());
pushInteger(S, Result, Call->getType());
return true;
}
Expand Down Expand Up @@ -734,7 +734,7 @@ static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
ResultType->isSignedIntegerOrEnumerationType();
uint64_t LHSSize = LHS.getBitWidth();
uint64_t RHSSize = RHS.getBitWidth();
uint64_t ResultSize = S.getCtx().getTypeSize(ResultType);
uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType);
uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);

// Add an additional bit if the signedness isn't uniformly agreed to. We
Expand Down Expand Up @@ -794,7 +794,7 @@ static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
// since it will give us the behavior of a TruncOrSelf in the case where
// its parameter <= its size. We previously set Result to be at least the
// type-size of the result, so getTypeSize(ResultType) <= Resu
APSInt Temp = Result.extOrTrunc(S.getCtx().getTypeSize(ResultType));
APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType));
Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());

if (!APSInt::isSameValue(Temp, Result))
Expand Down Expand Up @@ -974,8 +974,8 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
if (Size.isPowerOfTwo()) {
// Check against inlining width.
unsigned InlineWidthBits =
S.getCtx().getTargetInfo().getMaxAtomicInlineWidth();
if (Size <= S.getCtx().toCharUnitsFromBits(InlineWidthBits)) {
S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();
if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {

// OK, we will inline appropriately-aligned operations of this size,
// and _Atomic(T) is appropriately-aligned.
Expand Down Expand Up @@ -1007,7 +1007,7 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {
QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isIncompleteType() &&
S.getCtx().getTypeAlignInChars(PointeeType) >= Size) {
S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
// OK, we will inline operations on this object.
return returnBool(true);
}
Expand Down Expand Up @@ -1059,7 +1059,7 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
return false;
}
unsigned SrcWidth = S.getCtx().getIntWidth(Call->getArg(0)->getType());
unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());
APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
if (APSInt::compareValues(Alignment, MaxValue) > 0) {
S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
Expand Down Expand Up @@ -1094,7 +1094,7 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
unsigned PtrOffset = Ptr.getByteOffset();
PtrOffset = Ptr.getIndex();
CharUnits BaseAlignment =
S.getCtx().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());
S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());
CharUnits PtrAlign =
BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));

Expand Down Expand Up @@ -1157,7 +1157,7 @@ static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
const Function *Func,
const CallExpr *Call) {
analyze_os_log::OSLogBufferLayout Layout;
analyze_os_log::computeOSLogBufferLayout(S.getCtx(), Call, Layout);
analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout);
pushInteger(S, Layout.size().getQuantity(), Call->getType());
return true;
}
Expand Down Expand Up @@ -1624,22 +1624,23 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
const RecordDecl *RD = RT->getDecl();
if (RD->isInvalidDecl())
return false;
const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
unsigned FieldIndex = MemberDecl->getFieldIndex();
assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
Result += S.getCtx().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
Result +=
S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
CurrentType = MemberDecl->getType().getNonReferenceType();
break;
}
case OffsetOfNode::Array: {
// When generating bytecode, we put all the index expressions as Sint64 on
// the stack.
int64_t Index = ArrayIndices[ArrayIndex];
const ArrayType *AT = S.getCtx().getAsArrayType(CurrentType);
const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
if (!AT)
return false;
CurrentType = AT->getElementType();
CharUnits ElementSize = S.getCtx().getTypeSizeInChars(CurrentType);
CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
Result += Index * ElementSize;
++ArrayIndex;
break;
Expand All @@ -1656,7 +1657,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
const RecordDecl *RD = RT->getDecl();
if (RD->isInvalidDecl())
return false;
const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);

// Find the base class itself.
CurrentType = BaseSpec->getType();
Expand Down
14 changes: 7 additions & 7 deletions clang/lib/AST/ByteCode/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
if (const auto *MCE = dyn_cast_if_present<CXXMemberCallExpr>(CallExpr)) {
const Expr *Object = MCE->getImplicitObjectArgument();
Object->printPretty(OS, /*Helper=*/nullptr,
S.getCtx().getPrintingPolicy(),
S.getASTContext().getPrintingPolicy(),
/*Indentation=*/0);
if (Object->getType()->isPointerType())
OS << "->";
Expand All @@ -188,18 +188,18 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
} else if (const auto *OCE =
dyn_cast_if_present<CXXOperatorCallExpr>(CallExpr)) {
OCE->getArg(0)->printPretty(OS, /*Helper=*/nullptr,
S.getCtx().getPrintingPolicy(),
S.getASTContext().getPrintingPolicy(),
/*Indentation=*/0);
OS << ".";
} else if (const auto *M = dyn_cast<CXXMethodDecl>(F)) {
print(OS, This, S.getCtx(),
S.getCtx().getLValueReferenceType(
S.getCtx().getRecordType(M->getParent())));
print(OS, This, S.getASTContext(),
S.getASTContext().getLValueReferenceType(
S.getASTContext().getRecordType(M->getParent())));
OS << ".";
}
}

F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(),
F->getNameForDiagnostic(OS, S.getASTContext().getPrintingPolicy(),
/*Qualified=*/false);
OS << '(';
unsigned Off = 0;
Expand All @@ -212,7 +212,7 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {

PrimType PrimTy = S.Ctx.classify(Ty).value_or(PT_Ptr);

TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getCtx(), Ty));
TYPE_SWITCH(PrimTy, print(OS, stackRef<T>(Off), S.getASTContext(), Ty));
Off += align(primSize(PrimTy));
if (I + 1 != N)
OS << ", ";
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/InterpState.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class InterpState final : public State, public SourceMapper {
Expr::EvalStatus &getEvalStatus() const override {
return Parent.getEvalStatus();
}
ASTContext &getCtx() const override { return Parent.getCtx(); }
ASTContext &getASTContext() const override { return Parent.getASTContext(); }

// Forward status checks and updates to the walker.
bool checkingForUndefinedBehavior() const override {
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/AST/ByteCode/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ void State::addNotes(ArrayRef<PartialDiagnosticAt> Diags) {
}

DiagnosticBuilder State::report(SourceLocation Loc, diag::kind DiagId) {
return getCtx().getDiagnostics().Report(Loc, DiagId);
return getASTContext().getDiagnostics().Report(Loc, DiagId);
}

/// Add a diagnostic to the diagnostics list.
PartialDiagnostic &State::addDiag(SourceLocation Loc, diag::kind DiagId) {
PartialDiagnostic PD(DiagId, getCtx().getDiagAllocator());
PartialDiagnostic PD(DiagId, getASTContext().getDiagAllocator());
getEvalStatus().Diag->push_back(std::make_pair(Loc, PD));
return getEvalStatus().Diag->back().second;
}
Expand All @@ -93,7 +93,8 @@ OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId,
}

unsigned CallStackNotes = getCallStackDepth() - 1;
unsigned Limit = getCtx().getDiagnostics().getConstexprBacktraceLimit();
unsigned Limit =
getASTContext().getDiagnostics().getConstexprBacktraceLimit();
if (Limit)
CallStackNotes = std::min(CallStackNotes, Limit + 1);
if (checkingPotentialConstantExpression())
Expand All @@ -113,7 +114,9 @@ OptionalDiagnostic State::diag(SourceLocation Loc, diag::kind DiagId,
return OptionalDiagnostic();
}

const LangOptions &State::getLangOpts() const { return getCtx().getLangOpts(); }
const LangOptions &State::getLangOpts() const {
return getASTContext().getLangOpts();
}

void State::addCallStack(unsigned Limit) {
// Determine which calls to skip, if any.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class State {
virtual void setActiveDiagnostic(bool Flag) = 0;
virtual void setFoldFailureDiagnostic(bool Flag) = 0;
virtual Expr::EvalStatus &getEvalStatus() const = 0;
virtual ASTContext &getCtx() const = 0;
virtual ASTContext &getASTContext() const = 0;
virtual bool hasPriorDiagnostic() = 0;
virtual unsigned getCallStackDepth() = 0;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ ExprDependence clang::computeDependence(BinaryOperator *E) {
ExprDependence clang::computeDependence(ConditionalOperator *E) {
// The type of the conditional operator depends on the type of the conditional
// to support the GCC vector conditional extension. Additionally,
// [temp.dep.expr] does specify state that this should be dependent on ALL sub
// [temp.dep.expr] does specify that this should be dependent on ALL sub
// expressions.
return E->getCond()->getDependence() | E->getLHS()->getDependence() |
E->getRHS()->getDependence();
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2799,9 +2799,17 @@ bool VarDecl::isKnownToBeDefined() const {
}

bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
(!Ctx.getLangOpts().RegisterStaticDestructors &&
!hasAttr<AlwaysDestroyAttr>()));
if (!hasGlobalStorage())
return false;
if (hasAttr<NoDestroyAttr>())
return true;
if (hasAttr<AlwaysDestroyAttr>())
return false;

using RSDKind = LangOptions::RegisterStaticDestructorsKind;
RSDKind K = Ctx.getLangOpts().getRegisterStaticDestructors();
return K == RSDKind::None ||
(K == RSDKind::ThreadLocal && getTLSKind() == TLS_None);
}

QualType::DestructionKind
Expand Down
27 changes: 21 additions & 6 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4806,6 +4806,26 @@ getOverflowPatternBinOp(const BinaryOperator *E) {
return {};
}

/// Compute and set the OverflowPatternExclusion bit based on whether the
/// BinaryOperator expression matches an overflow pattern being ignored by
/// -fsanitize-undefined-ignore-overflow-pattern=add-signed-overflow-test or
/// -fsanitize-undefined-ignore-overflow-pattern=add-unsigned-overflow-test
static void computeOverflowPatternExclusion(const ASTContext &Ctx,
const BinaryOperator *E) {
std::optional<BinaryOperator *> Result = getOverflowPatternBinOp(E);
if (!Result.has_value())
return;
QualType AdditionResultType = Result.value()->getType();

if ((AdditionResultType->isSignedIntegerType() &&
Ctx.getLangOpts().isOverflowPatternExcluded(
LangOptions::OverflowPatternExclusionKind::AddSignedOverflowTest)) ||
(AdditionResultType->isUnsignedIntegerType() &&
Ctx.getLangOpts().isOverflowPatternExcluded(
LangOptions::OverflowPatternExclusionKind::AddUnsignedOverflowTest)))
Result.value()->setExcludedOverflowPattern(true);
}

BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
Opcode opc, QualType ResTy, ExprValueKind VK,
ExprObjectKind OK, SourceLocation opLoc,
Expand All @@ -4818,12 +4838,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
BinaryOperatorBits.ExcludedOverflowPattern = false;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
if (Ctx.getLangOpts().isOverflowPatternExcluded(
LangOptions::OverflowPatternExclusionKind::AddOverflowTest)) {
std::optional<BinaryOperator *> Result = getOverflowPatternBinOp(this);
if (Result.has_value())
Result.value()->BinaryOperatorBits.ExcludedOverflowPattern = true;
}
computeOverflowPatternExclusion(Ctx, this);
BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
if (hasStoredFPFeatures())
setStoredFPFeatures(FPFeatures);
Expand Down
Loading