Skip to content

Commit d2ddc3e

Browse files
author
Jenkins
committed
merge main into amd-staging
Change-Id: Ib5e932d2b4da80980a20013b4b728b1395f8b405
2 parents 0c4fe60 + 8eb5baf commit d2ddc3e

File tree

24 files changed

+324
-136
lines changed

24 files changed

+324
-136
lines changed

clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing
1+
// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26
22

33
typedef __INT64_TYPE__ I64;
44

clang/docs/RealtimeSanitizer.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ A **partial** list of flags RealtimeSanitizer respects:
187187
* - ``abort_on_error``
188188
- OS dependent
189189
- boolean
190-
- If true, the tool calls abort() instead of _exit() after printing the error report. On some OSes (OSX, for exmple) this is beneficial because a better stack trace is emitted on crash.
190+
- If true, the tool calls ``abort()`` instead of ``_exit()`` after printing the error report. On some OSes (MacOS, for exmple) this is beneficial because a better stack trace is emitted on crash.
191191
* - ``symbolize``
192192
- ``true``
193193
- boolean
194194
- If set, use the symbolizer to turn virtual addresses to file/line locations. If false, can greatly speed up the error reporting.
195195
* - ``suppressions``
196-
- ""
196+
- ``""``
197197
- path
198-
- If set to a valid suppressions file, will suppress issue reporting. See details in "Disabling", below.
198+
- If set to a valid suppressions file, will suppress issue reporting. See details in `Disabling and Suppressing`_.
199199

200200

201201
Some issues with flags can be debugged using the ``verbosity=$NUM`` flag:
@@ -244,6 +244,7 @@ To register a callback which will be invoked before a RTSan kills the process:
244244
...
245245
}
246246
247+
.. _disabling-and-suppressing:
247248

248249
Disabling and suppressing
249250
-------------------------

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ New Compiler Flags
436436
- The ``-Warray-compare`` warning has been added to warn about array comparison
437437
on versions older than C++20.
438438

439+
- The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison
440+
starting from C++26, this warning is enabled as an error by default.
441+
439442
Deprecated Compiler Flags
440443
-------------------------
441444

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10277,6 +10277,11 @@ def warn_array_comparison : Warning<
1027710277
"to compare array addresses, use unary '+' to decay operands to pointers">,
1027810278
InGroup<DiagGroup<"array-compare">>;
1027910279

10280+
def warn_array_comparison_cxx26 : Warning<
10281+
"comparison between two arrays is ill-formed in C++26; "
10282+
"to compare array addresses, use unary '+' to decay operands to pointers">,
10283+
InGroup<DiagGroup<"array-compare-cxx26">>, DefaultError;
10284+
1028010285
def warn_stringcompare : Warning<
1028110286
"result of comparison against %select{a string literal|@encode}0 is "
1028210287
"unspecified (use an explicit string comparison function instead)">,

clang/lib/AST/ByteCode/BitcastBuffer.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,7 @@ BitcastBuffer::copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth,
6262
}
6363

6464
bool BitcastBuffer::allInitialized() const {
65-
Bits Sum;
66-
for (BitRange BR : InitializedBits)
67-
Sum += BR.size();
68-
69-
return Sum == FinalBitSize;
65+
return rangeInitialized(Bits::zero(), FinalBitSize);
7066
}
7167

7268
void BitcastBuffer::markInitialized(Bits Offset, Bits Length) {
@@ -111,6 +107,34 @@ void BitcastBuffer::markInitialized(Bits Offset, Bits Length) {
111107
#endif
112108
}
113109

110+
bool BitcastBuffer::rangeInitialized(Bits Offset, Bits Length) const {
111+
if (Length.isZero())
112+
return true;
113+
114+
BitRange Range(Offset, Offset + Length - Bits(1));
115+
Bits Sum;
116+
bool FoundStart = false;
117+
for (BitRange BR : InitializedBits) {
118+
if (FoundStart) {
119+
if (BR.contains(Range.End)) {
120+
Sum += (Range.End - BR.Start + Bits(1));
121+
break;
122+
}
123+
124+
// Else, BR is completely inside Range.
125+
Sum += BR.size();
126+
}
127+
if (BR.contains(Range.Start)) {
128+
Sum += (BR.End - Range.Start + Bits(1));
129+
FoundStart = true;
130+
}
131+
}
132+
133+
// Note that Sum can be larger than Range, e.g. when Range is fully
134+
// contained in one range.
135+
return Sum >= Range.size();
136+
}
137+
114138
#if 0
115139
template<typename T>
116140
static std::string hex(T t) {

clang/lib/AST/ByteCode/BitcastBuffer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,16 @@ struct Bytes {
5555
Bits toBits() const { return Bits(N * 8); }
5656
};
5757

58+
/// A bit range. Both Start and End are inclusive.
5859
struct BitRange {
5960
Bits Start;
6061
Bits End;
6162

6263
BitRange(Bits Start, Bits End) : Start(Start), End(End) {}
6364
Bits size() const { return End - Start + Bits(1); }
6465
bool operator<(BitRange Other) const { return Start.N < Other.Start.N; }
66+
67+
bool contains(Bits B) { return Start <= B && End >= B; }
6568
};
6669

6770
/// Track what bits have been initialized to known values and which ones
@@ -85,6 +88,7 @@ struct BitcastBuffer {
8588
/// Marks the bits in the given range as initialized.
8689
/// FIXME: Can we do this automatically in pushData()?
8790
void markInitialized(Bits Start, Bits Length);
91+
bool rangeInitialized(Bits Offset, Bits Length) const;
8892

8993
/// Push \p BitWidth bits at \p BitOffset from \p In into the buffer.
9094
/// \p TargetEndianness is the endianness of the target we're compiling for.

clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,10 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
248248
if (BitWidth.isZero())
249249
return true;
250250

251-
if (!P.isInitialized()) {
252-
assert(false && "Implement uninitialized value tracking");
253-
return ReturnOnUninit;
254-
}
251+
// Bits will be left uninitialized and diagnosed when reading.
252+
if (!P.isInitialized())
253+
return true;
255254

256-
assert(P.isInitialized());
257255
if (T == PT_Ptr) {
258256
assert(P.getType()->isNullPtrType());
259257
// Clang treats nullptr_t has having NO bits in its value
@@ -262,6 +260,7 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
262260
return true;
263261
}
264262

263+
assert(P.isInitialized());
265264
auto Buff =
266265
std::make_unique<std::byte[]>(ObjectReprChars.getQuantity());
267266
// Work around floating point types that contain unused padding bytes.
@@ -355,10 +354,11 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
355354
ToPtr, S.getContext(), Buffer.size(),
356355
[&](const Pointer &P, PrimType T, Bits BitOffset,
357356
bool PackedBools) -> bool {
358-
CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
357+
QualType PtrType = P.getType();
358+
CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(PtrType);
359359
Bits FullBitWidth = Bits(ASTCtx.toBits(ObjectReprChars));
360360
if (T == PT_Float) {
361-
const auto &Semantics = ASTCtx.getFloatTypeSemantics(P.getType());
361+
const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType);
362362
Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics));
363363
assert(NumBits.isFullByte());
364364
assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
@@ -382,6 +382,23 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
382382
else
383383
BitWidth = FullBitWidth;
384384

385+
// If any of the bits are uninitialized, we need to abort unless the
386+
// target type is std::byte or unsigned char.
387+
bool Initialized = Buffer.rangeInitialized(BitOffset, BitWidth);
388+
if (!Initialized) {
389+
if (!PtrType->isStdByteType() &&
390+
!PtrType->isSpecificBuiltinType(BuiltinType::UChar) &&
391+
!PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) {
392+
const Expr *E = S.Current->getExpr(OpPC);
393+
S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
394+
<< PtrType << S.getLangOpts().CharIsSigned
395+
<< E->getSourceRange();
396+
397+
return false;
398+
}
399+
return true;
400+
}
401+
385402
auto Memory = Buffer.copyBits(BitOffset, BitWidth, FullBitWidth,
386403
TargetEndianness);
387404
if (llvm::sys::IsBigEndianHost)

clang/lib/Sema/SemaExpr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11843,7 +11843,9 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
1184311843
RHSStripped->getType()->isArrayType()) {
1184411844
auto IsDeprArrayComparionIgnored =
1184511845
S.getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc);
11846-
auto DiagID = !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored
11846+
auto DiagID = S.getLangOpts().CPlusPlus26
11847+
? diag::warn_array_comparison_cxx26
11848+
: !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored
1184711849
? diag::warn_array_comparison
1184811850
: diag::warn_depr_array_comparison;
1184911851
S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange()

clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct bytes {
6363

6464
constexpr unsigned char operator[](size_t index) {
6565
if (index < N)
66-
return d[index];
66+
return d[index]; // expected-note {{read of uninitialized object}}
6767
return -1;
6868
}
6969
};
@@ -141,11 +141,11 @@ namespace BitFields {
141141
// expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'byte' is invalid}}
142142

143143
struct M {
144-
// ref-note@+1 {{subobject declared here}}
144+
// expected-note@+1 {{subobject declared here}}
145145
unsigned char mem[sizeof(BF)];
146146
};
147-
// ref-error@+2 {{initialized by a constant expression}}
148-
// ref-note@+1 {{not initialized}}
147+
// expected-error@+2 {{initialized by a constant expression}}
148+
// expected-note@+1 {{not initialized}}
149149
constexpr M m = bit_cast<M>(bf);
150150

151151
constexpr auto f = []() constexpr {
@@ -156,8 +156,8 @@ namespace BitFields {
156156

157157
static_assert(f()[0] + f()[1] + f()[2] == 0xc0 + 0xff + 0xee);
158158
{
159-
// ref-error@+2 {{initialized by a constant expression}}
160-
// ref-note@+1 {{read of uninitialized object is not allowed in a constant expression}}
159+
// expected-error@+2 {{initialized by a constant expression}}
160+
// expected-note@+1 {{in call to}}
161161
constexpr auto _bad = f()[3];
162162
}
163163

@@ -173,8 +173,8 @@ namespace BitFields {
173173
};
174174
static_assert(g().s0 + g().s1 + g().b0 + g().b1 == 0xc0 + 0xff + 0xe + 0xe);
175175
{
176-
// ref-error@+2 {{initialized by a constant expression}}
177-
// ref-note@+1 {{read of uninitialized object is not allowed in a constant expression}}
176+
// expected-error@+2 {{initialized by a constant expression}}
177+
// expected-note@+1 {{read of uninitialized object is not allowed in a constant expression}}
178178
constexpr auto _bad = g().b2;
179179
}
180180
}
@@ -457,4 +457,19 @@ namespace IndeterminateBits {
457457
};
458458
constexpr unsigned char B = __builtin_bit_cast(unsigned char, S2{3});
459459
static_assert(B == (LITTLE_END ? 3 : 192));
460+
461+
462+
463+
struct S3 {
464+
unsigned a : 13;
465+
unsigned : 17;
466+
unsigned b : 2;
467+
};
468+
469+
struct D {
470+
unsigned a;
471+
};
472+
constexpr D s = __builtin_bit_cast(D, S3{12, 3}); // expected-error {{must be initialized by a constant expression}} \
473+
// expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}}
474+
460475
}

clang/test/Sema/warn-stringcompare.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
22
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cxx %s
3+
// RUN: %clang_cc1 -x c++ -std=c++26 -fsyntax-only -verify=expected,cxx26 %s
34

45
#define DELIM "/"
56
#define DOT "."
@@ -15,15 +16,15 @@ void test(const char *d) {
1516
if (NULL == "/")
1617
return;
1718
if ("/" != DELIM) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
18-
return; // cxx-warning@-1 {{comparison between two arrays}}
19+
return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
1920
if (DELIM == "/") // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
20-
return; // cxx-warning@-1 {{comparison between two arrays}}
21+
return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
2122
if (DELIM != NULL)
2223
return;
2324
if (NULL == DELIM)
2425
return;
2526
if (DOT != DELIM) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
26-
return; // cxx-warning@-1 {{comparison between two arrays}}
27+
return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
2728
if (DELIM == DOT) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
28-
return; // cxx-warning@-1 {{comparison between two arrays}}
29+
return; // cxx-warning@-1 {{comparison between two arrays}} cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
2930
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -verify=expected,not-cxx20
22
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wno-deprecated-array-compare -verify %s -verify=expected,not-cxx20
33
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx20
4+
// RUN: %clang_cc1 -std=c++26 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx26
45

56
typedef struct {
67
char str[16];
@@ -9,13 +10,14 @@ typedef struct {
910

1011
bool object_equal(const Object &obj1, const Object &obj2) {
1112
if (obj1.str != obj2.str) // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
12-
return false;
13+
return false; // cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
1314
if (obj1.id != obj2.id) // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
14-
return false;
15+
return false; // cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
1516
return true;
1617
}
1718

1819

1920
void foo(int (&array1)[2], int (&array2)[2]) {
2021
if (array1 == array2) { } // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
22+
// cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
2123
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -verify=expected,not-cxx20
22
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx20
3+
// RUN: %clang_cc1 -std=c++26 -fsyntax-only -Wdeprecated -verify %s -verify=expected,cxx26
34

45
void f(int (&array1)[2], int (&array2)[2]) {
56
if (array1 == array2) { } // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
7+
// cxx26-error@-1 {{comparison between two arrays is ill-formed in C++26}}
68
}

clang/www/cxx_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
239239
<tr>
240240
<td>Remove Deprecated Array Comparisons from C++26</td>
241241
<td><a href="https://wg21.link/P2865R6">P2865R6</a></td>
242-
<td class="none" align="center">No</td>
242+
<td class="unreleased" align="center">Clang 20</td>
243243
</tr>
244244
<tr>
245245
<td>Structured Bindings can introduce a Pack</td>

compiler-rt/lib/rtsan/rtsan.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() {
8383

8484
SanitizerToolName = "RealtimeSanitizer";
8585
InitializeFlags();
86+
87+
InitializePlatformEarly();
88+
8689
InitializeInterceptors();
8790

8891
InitializeSuppressions();

compiler-rt/lib/rtsan/tests/rtsan_test_main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ extern "C" const char *__rtsan_default_options() {
1919
// and make sure we do not overwhelm the syslog while testing. Also, let's
2020
// turn symbolization off to speed up testing, especially when not running
2121
// with llvm-symbolizer but with atos.
22-
return "symbolize=false:abort_on_error=0:log_to_syslog=0";
22+
return "symbolize=false:"
23+
"abort_on_error=0:"
24+
"log_to_syslog=0:"
25+
"verify_interceptors=0:"; // some of our tests don't need interceptors
2326
#else
2427
// Let's turn symbolization off to speed up testing (more than 3 times speedup
2528
// observed).

compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -972,8 +972,9 @@ static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
972972
LowLevelAllocator allocator_for_env;
973973

974974
static bool ShouldCheckInterceptors() {
975-
// Restrict "interceptors working?" check to ASan and TSan.
976-
const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer"};
975+
// Restrict "interceptors working?" check
976+
const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer",
977+
"RealtimeSanitizer"};
977978
size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]);
978979
for (size_t i = 0; i < count; i++) {
979980
if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0)

0 commit comments

Comments
 (0)