Skip to content

Commit 4f2174c

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merge llvm/main into amd-debug
2 parents 1727a19 + 6a5cb5a commit 4f2174c

File tree

20 files changed

+529
-294
lines changed

20 files changed

+529
-294
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ Bug Fixes in This Version
253253
-------------------------
254254
- Fix a crash when marco name is empty in ``#pragma push_macro("")`` or
255255
``#pragma pop_macro("")``. (#GH149762).
256+
- Fix a crash in variable length array (e.g. ``int a[*]``) function parameter type
257+
being used in ``_Countof`` expression. (#GH152826).
256258
- `-Wunreachable-code`` now diagnoses tautological or contradictory
257259
comparisons such as ``x != 0 || x != 1.0`` and ``x == 0 && x == 1.0`` on
258260
targets that treat ``_Float16``/``__fp16`` as native scalar types. Previously

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2248,7 +2248,9 @@ bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
22482248
assert(VAT);
22492249
if (VAT->getElementType()->isArrayType()) {
22502250
std::optional<APSInt> Res =
2251-
VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx);
2251+
VAT->getSizeExpr()
2252+
? VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx)
2253+
: std::nullopt;
22522254
if (Res) {
22532255
if (DiscardResult)
22542256
return true;

clang/lib/AST/ExprConstant.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15353,6 +15353,13 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
1535315353
const auto *VAT = Info.Ctx.getAsVariableArrayType(Ty);
1535415354
assert(VAT);
1535515355
if (VAT->getElementType()->isArrayType()) {
15356+
// Variable array size expression could be missing (e.g. int a[*][10]) In
15357+
// that case, it can't be a constant expression.
15358+
if (!VAT->getSizeExpr()) {
15359+
Info.FFDiag(E->getBeginLoc());
15360+
return false;
15361+
}
15362+
1535615363
std::optional<APSInt> Res =
1535715364
VAT->getSizeExpr()->getIntegerConstantExpr(Info.Ctx);
1535815365
if (Res) {
@@ -17890,7 +17897,10 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
1789017897
// it is an ICE or not.
1789117898
const auto *VAT = Ctx.getAsVariableArrayType(ArgTy);
1789217899
if (VAT->getElementType()->isArrayType())
17893-
return CheckICE(VAT->getSizeExpr(), Ctx);
17900+
// Variable array size expression could be missing (e.g. int a[*][10])
17901+
// In that case, it can't be a constant expression.
17902+
return VAT->getSizeExpr() ? CheckICE(VAT->getSizeExpr(), Ctx)
17903+
: ICEDiag(IK_NotICE, E->getBeginLoc());
1789417904

1789517905
// Otherwise, this is a regular VLA, which is definitely not an ICE.
1789617906
return ICEDiag(IK_NotICE, E->getBeginLoc());

clang/test/Sema/gh152826.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -std=c2y -verify %s
2+
// RUN: %clang_cc1 -std=c2y -verify -fexperimental-new-constant-interpreter %s
3+
// expected-no-diagnostics
4+
5+
void gh152826(char (*a)[*][5], int (*x)[_Countof(*a)]);
6+
void more_likely_in_practice(unsigned long size_one, int (*a)[*][5], int b[_Countof(*a)]);
7+
void f(int (*x)[*][1][*][2][*][*][3][*], int q[_Countof(*x)]);

libcxx/docs/ReleaseNotes/22.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Improvements and New Features
5454
- The performance of the ``(iterator, iterator)`` constructors of ``multimap`` and ``multiset``
5555
has been improved by up to 3x
5656
- The performance of ``insert(iterator, iterator)`` of ``multimap`` and ``multiset`` has been improved by up to 2.5x
57+
- The performance of ``erase(iterator, iterator)`` in the unordered containers has been improved by up to 1.9x
5758

5859
Deprecations and Removals
5960
-------------------------

libcxx/include/__hash_table

Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,21 @@ private:
10241024
}
10251025
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
10261026

1027-
_LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT;
1027+
_LIBCPP_HIDE_FROM_ABI void __deallocate_node(__node_pointer __nd) _NOEXCEPT {
1028+
auto& __alloc = __node_alloc();
1029+
__node_traits::destroy(__alloc, std::addressof(__nd->__get_value()));
1030+
std::__destroy_at(std::__to_address(__nd));
1031+
__node_traits::deallocate(__alloc, __nd, 1);
1032+
}
1033+
1034+
_LIBCPP_HIDE_FROM_ABI void __deallocate_node_list(__next_pointer __np) _NOEXCEPT {
1035+
while (__np != nullptr) {
1036+
__next_pointer __next = __np->__next_;
1037+
__deallocate_node(__np->__upcast());
1038+
__np = __next;
1039+
}
1040+
}
1041+
10281042
_LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT;
10291043

10301044
template <class _From, class _ValueT = _Tp, __enable_if_t<__is_hash_value_type<_ValueT>::value, int> = 0>
@@ -1162,7 +1176,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() {
11621176
static_assert(is_copy_constructible<hasher>::value, "Hasher must be copy-constructible.");
11631177
#endif
11641178

1165-
__deallocate_node(__first_node_.__next_);
1179+
__deallocate_node_list(__first_node_.__next_);
11661180
}
11671181

11681182
template <class _Tp, class _Hash, class _Equal, class _Alloc>
@@ -1238,7 +1252,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __other)
12381252
// At this point we either have consumed the whole incoming hash table, or we don't have any more nodes to reuse in
12391253
// the destination. Either continue with constructing new nodes, or deallocate the left over nodes.
12401254
if (__own_iter->__next_) {
1241-
__deallocate_node(__own_iter->__next_);
1255+
__deallocate_node_list(__own_iter->__next_);
12421256
__own_iter->__next_ = nullptr;
12431257
} else {
12441258
__copy_construct(__other_iter, __own_iter, __current_chash);
@@ -1249,19 +1263,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __other)
12491263
return *this;
12501264
}
12511265

1252-
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1253-
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) _NOEXCEPT {
1254-
__node_allocator& __na = __node_alloc();
1255-
while (__np != nullptr) {
1256-
__next_pointer __next = __np->__next_;
1257-
__node_pointer __real_np = __np->__upcast();
1258-
__node_traits::destroy(__na, std::addressof(__real_np->__get_value()));
1259-
std::__destroy_at(std::addressof(*__real_np));
1260-
__node_traits::deallocate(__na, __real_np, 1);
1261-
__np = __next;
1262-
}
1263-
}
1264-
12651266
template <class _Tp, class _Hash, class _Equal, class _Alloc>
12661267
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
12671268
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
@@ -1317,11 +1318,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u,
13171318
}
13181319
#if _LIBCPP_HAS_EXCEPTIONS
13191320
} catch (...) {
1320-
__deallocate_node(__cache);
1321+
__deallocate_node_list(__cache);
13211322
throw;
13221323
}
13231324
#endif // _LIBCPP_HAS_EXCEPTIONS
1324-
__deallocate_node(__cache);
1325+
__deallocate_node_list(__cache);
13251326
}
13261327
const_iterator __i = __u.begin();
13271328
while (__u.size() != 0)
@@ -1360,11 +1361,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __
13601361
}
13611362
#if _LIBCPP_HAS_EXCEPTIONS
13621363
} catch (...) {
1363-
__deallocate_node(__cache);
1364+
__deallocate_node_list(__cache);
13641365
throw;
13651366
}
13661367
#endif // _LIBCPP_HAS_EXCEPTIONS
1367-
__deallocate_node(__cache);
1368+
__deallocate_node_list(__cache);
13681369
}
13691370
for (; __first != __last; ++__first)
13701371
__emplace_unique(*__first);
@@ -1390,11 +1391,11 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __f
13901391
}
13911392
#if _LIBCPP_HAS_EXCEPTIONS
13921393
} catch (...) {
1393-
__deallocate_node(__cache);
1394+
__deallocate_node_list(__cache);
13941395
throw;
13951396
}
13961397
#endif // _LIBCPP_HAS_EXCEPTIONS
1397-
__deallocate_node(__cache);
1398+
__deallocate_node_list(__cache);
13981399
}
13991400
for (; __first != __last; ++__first)
14001401
__emplace_multi(*__first);
@@ -1427,7 +1428,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
14271428
template <class _Tp, class _Hash, class _Equal, class _Alloc>
14281429
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT {
14291430
if (size() > 0) {
1430-
__deallocate_node(__first_node_.__next_);
1431+
__deallocate_node_list(__first_node_.__next_);
14311432
__first_node_.__next_ = nullptr;
14321433
size_type __bc = bucket_count();
14331434
for (size_type __i = 0; __i < __bc; ++__i)
@@ -1955,12 +1956,57 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) {
19551956
template <class _Tp, class _Hash, class _Equal, class _Alloc>
19561957
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
19571958
__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) {
1958-
for (const_iterator __p = __first; __first != __last; __p = __first) {
1959-
++__first;
1960-
erase(__p);
1959+
if (__first == __last)
1960+
return iterator(__last.__node_);
1961+
1962+
// current node
1963+
__next_pointer __current = __first.__node_;
1964+
size_type __bucket_count = bucket_count();
1965+
size_t __chash = std::__constrain_hash(__current->__hash(), __bucket_count);
1966+
// find previous node
1967+
__next_pointer __before_first = __bucket_list_[__chash];
1968+
for (; __before_first->__next_ != __current; __before_first = __before_first->__next_)
1969+
;
1970+
1971+
__next_pointer __last_node = __last.__node_;
1972+
1973+
// If __before_first is in the same bucket (i.e. the first element we erase is not the first in the bucket), clear
1974+
// this bucket first without re-linking it
1975+
if (__before_first != __first_node_.__ptr() &&
1976+
std::__constrain_hash(__before_first->__hash(), __bucket_count) == __chash) {
1977+
while (__current != __last_node) {
1978+
if (auto __next_chash = std::__constrain_hash(__current->__hash(), __bucket_count); __next_chash != __chash) {
1979+
__chash = __next_chash;
1980+
break;
1981+
}
1982+
auto __next = __current->__next_;
1983+
__deallocate_node(__current->__upcast());
1984+
__current = __next;
1985+
--__size_;
1986+
}
19611987
}
1962-
__next_pointer __np = __last.__node_;
1963-
return iterator(__np);
1988+
1989+
while (__current != __last_node) {
1990+
auto __next = __current->__next_;
1991+
__deallocate_node(__current->__upcast());
1992+
__current = __next;
1993+
--__size_;
1994+
1995+
// When switching buckets, set the old bucket to be empty and update the next bucket to have __before_first as its
1996+
// before-first element
1997+
if (__next) {
1998+
if (auto __next_chash = std::__constrain_hash(__next->__hash(), __bucket_count); __next_chash != __chash) {
1999+
__bucket_list_[__chash] = nullptr;
2000+
__chash = __next_chash;
2001+
__bucket_list_[__chash] = __before_first;
2002+
}
2003+
}
2004+
}
2005+
2006+
// re-link __before_first with __last
2007+
__before_first->__next_ = __current;
2008+
2009+
return iterator(__last.__node_);
19642010
}
19652011

19662012
template <class _Tp, class _Hash, class _Equal, class _Alloc>

libcxx/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/erase_range.pass.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,20 @@ int main(int, char**) {
9191
assert(c.size() == 0);
9292
assert(k == c.end());
9393
}
94+
{ // Make sure we're properly destroying the elements when erasing
95+
{ // When erasing part of a bucket
96+
std::unordered_multimap<int, std::string> map;
97+
map.insert(std::make_pair(1, "This is a long string to make sure ASan can detect a memory leak"));
98+
map.insert(std::make_pair(1, "This is another long string to make sure ASan can detect a memory leak"));
99+
map.erase(++map.begin(), map.end());
100+
}
101+
{ // When erasing the whole bucket
102+
std::unordered_multimap<int, std::string> map;
103+
map.insert(std::make_pair(1, "This is a long string to make sure ASan can detect a memory leak"));
104+
map.insert(std::make_pair(1, "This is another long string to make sure ASan can detect a memory leak"));
105+
map.erase(map.begin(), map.end());
106+
}
107+
}
94108
#if TEST_STD_VER >= 11
95109
{
96110
typedef std::unordered_multimap<int,

lldb/include/lldb/Protocol/MCP/Server.h

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#ifndef LLDB_PROTOCOL_MCP_SERVER_H
1010
#define LLDB_PROTOCOL_MCP_SERVER_H
1111

12-
#include "lldb/Host/JSONTransport.h"
13-
#include "lldb/Host/MainLoop.h"
1412
#include "lldb/Protocol/MCP/Protocol.h"
1513
#include "lldb/Protocol/MCP/Resource.h"
1614
#include "lldb/Protocol/MCP/Tool.h"
@@ -20,52 +18,26 @@
2018

2119
namespace lldb_protocol::mcp {
2220

23-
class MCPTransport final
24-
: public lldb_private::JSONRPCTransport<Request, Response, Notification> {
21+
class Server {
2522
public:
26-
using LogCallback = std::function<void(llvm::StringRef message)>;
27-
28-
MCPTransport(lldb::IOObjectSP in, lldb::IOObjectSP out,
29-
std::string client_name, LogCallback log_callback = {})
30-
: JSONRPCTransport(in, out), m_client_name(std::move(client_name)),
31-
m_log_callback(log_callback) {}
32-
virtual ~MCPTransport() = default;
33-
34-
void Log(llvm::StringRef message) override {
35-
if (m_log_callback)
36-
m_log_callback(llvm::formatv("{0}: {1}", m_client_name, message).str());
37-
}
38-
39-
private:
40-
std::string m_client_name;
41-
LogCallback m_log_callback;
42-
};
43-
44-
class Server : public MCPTransport::MessageHandler {
45-
public:
46-
Server(std::string name, std::string version,
47-
std::unique_ptr<MCPTransport> transport_up,
48-
lldb_private::MainLoop &loop);
49-
~Server() = default;
50-
51-
using NotificationHandler = std::function<void(const Notification &)>;
23+
Server(std::string name, std::string version);
24+
virtual ~Server() = default;
5225

5326
void AddTool(std::unique_ptr<Tool> tool);
5427
void AddResourceProvider(std::unique_ptr<ResourceProvider> resource_provider);
55-
void AddNotificationHandler(llvm::StringRef method,
56-
NotificationHandler handler);
57-
58-
llvm::Error Run();
5928

6029
protected:
61-
Capabilities GetCapabilities();
30+
virtual Capabilities GetCapabilities() = 0;
6231

6332
using RequestHandler =
6433
std::function<llvm::Expected<Response>(const Request &)>;
34+
using NotificationHandler = std::function<void(const Notification &)>;
6535

6636
void AddRequestHandlers();
6737

6838
void AddRequestHandler(llvm::StringRef method, RequestHandler handler);
39+
void AddNotificationHandler(llvm::StringRef method,
40+
NotificationHandler handler);
6941

7042
llvm::Expected<std::optional<Message>> HandleData(llvm::StringRef data);
7143

@@ -80,23 +52,12 @@ class Server : public MCPTransport::MessageHandler {
8052
llvm::Expected<Response> ResourcesListHandler(const Request &);
8153
llvm::Expected<Response> ResourcesReadHandler(const Request &);
8254

83-
void Received(const Request &) override;
84-
void Received(const Response &) override;
85-
void Received(const Notification &) override;
86-
void OnError(llvm::Error) override;
87-
void OnClosed() override;
88-
89-
void TerminateLoop();
90-
9155
std::mutex m_mutex;
9256

9357
private:
9458
const std::string m_name;
9559
const std::string m_version;
9660

97-
std::unique_ptr<MCPTransport> m_transport_up;
98-
lldb_private::MainLoop &m_loop;
99-
10061
llvm::StringMap<std::unique_ptr<Tool>> m_tools;
10162
std::vector<std::unique_ptr<ResourceProvider>> m_resource_providers;
10263

0 commit comments

Comments
 (0)