Compare commits

...

13 commits

Author SHA1 Message Date
Jonne Ransijn
b56c7fc8b9
Merge 33b9e7ac95 into 63a5717bc7 2024-11-20 16:09:04 -05:00
Jonne Ransijn
33b9e7ac95
AK: Allow NonnullRawPtr to be used in constant expressions 2024-11-19 16:53:31 +01:00
Jonne Ransijn
f555af68a1
AK: Restrict template parameter of JsonArray constructor
This constructor doesn't need to accept iterable containers of anything
other than `JsonValue`s.
2024-11-19 16:53:31 +01:00
Jonne Ransijn
365557ddd7
AK: Add IterableContainerOf concept
This concept not only checks that the given type is iterable, but it
also checks that the iterated value is of the expected type.
2024-11-19 16:53:31 +01:00
Jonne Ransijn
b09595e147
AK: Add IsTemplateBaseOf<Base, Derived> concept
This concept checks if any specialization of `Base<...>` is a base class
of `Derived`.
2024-11-19 16:53:31 +01:00
Jonne Ransijn
1a03a27c86
AK: Disallow creating NonnullRawPtrs from r-value references
This would always result in a use-after-free.
2024-11-19 16:53:30 +01:00
Jonne Ransijn
db0f019a70
Meta: Print failed pre-commit steps in bold
This makes them easier to find, especially for colorblind people.
2024-11-19 16:53:30 +01:00
Jonne Ransijn
db28ed8f51
AK: Use Noncopyable.h in NonnullRawPtr 2024-11-19 16:53:30 +01:00
Jonne Ransijn
b35fbe77c6
AK: Use Noncopyable.h in Badge 2024-11-19 16:53:30 +01:00
Jonne Ransijn
0be6603d5e
AK: Fix ASSERT_NOT_REACHED macro when NDEBUG is not defined
This is supposed to be a function-like macro just like
`VERIFY_NOT_REACHED()` and when `NDEBUG` is defined.
2024-11-19 16:53:30 +01:00
Jonne Ransijn
a8094f3333
AK+LibJS: Allow {TRY,MUST}{,_OR_THROW_OOM} on list-initializers
List initializers may contain commas without surrounding parenthesis,
causing them to be passed as multiple macro arguments.
2024-11-19 16:53:24 +01:00
Jonne Ransijn
079edffd47
AK: Allow calling ASSERT and VERIFY on list-initializers
List initializers may contain commas without surrounding parenthesis,
causing them to be passed as multiple macro arguments.
2024-11-19 16:18:54 +01:00
Jonne Ransijn
2d8eff9b52
AK: Remove clang-tidy warnings for ASSERT(a || b) lines
Lines like these were getting a warning to simplify the expanded
boolean expression from `!(a || b)` to `(a && b)`, but since the
`!(...)` is part of the macro, that is never going to happen.
2024-11-19 16:18:53 +01:00
9 changed files with 65 additions and 64 deletions

View file

@ -9,9 +9,9 @@
extern "C" __attribute__((noreturn)) void ak_verification_failed(char const*);
#define __stringify_helper(x) #x
#define __stringify(x) __stringify_helper(x)
#define VERIFY(expr) \
(__builtin_expect(/* NOLINT(readability-simplify-boolean-expr) */ !(expr), 0) \
? ak_verification_failed(#expr " at " __FILE__ ":" __stringify(__LINE__)) \
#define VERIFY(...) \
(__builtin_expect(/* NOLINT(readability-simplify-boolean-expr) */ !(__VA_ARGS__), 0) \
? ak_verification_failed(#__VA_ARGS__ " at " __FILE__ ":" __stringify(__LINE__)) \
: (void)0)
#define VERIFY_NOT_REACHED() VERIFY(false) /* NOLINT(cert-dcl03-c,misc-static-assert) No, this can't be static_assert, it's a runtime check */
static constexpr bool TODO = false;
@ -23,12 +23,12 @@ static constexpr bool TODO = false;
extern "C" __attribute__((noreturn)) void ak_assertion_failed(char const*);
#ifndef NDEBUG
# define ASSERT(expr) \
(__builtin_expect(!(expr), 0) \
? ak_assertion_failed(#expr " at " __FILE__ ":" __stringify(__LINE__)) \
# define ASSERT(...) \
(__builtin_expect(/* NOLINT(readability-simplify-boolean-expr) */ !(__VA_ARGS__), 0) \
? ak_assertion_failed(#__VA_ARGS__ " at " __FILE__ ":" __stringify(__LINE__)) \
: (void)0)
# define ASSERT_NOT_REACHED ASSERT(false) /* NOLINT(cert-dcl03-c,misc-static-assert) No, this can't be static_assert, it's a runtime check */
# define ASSERT_NOT_REACHED() ASSERT(false) /* NOLINT(cert-dcl03-c,misc-static-assert) No, this can't be static_assert, it's a runtime check */
#else
# define ASSERT(expr)
# define ASSERT(...)
# define ASSERT_NOT_REACHED() __builtin_unreachable()
#endif

View file

@ -6,24 +6,22 @@
#pragma once
#include <AK/Noncopyable.h>
#include <AK/Platform.h>
namespace AK {
template<typename T>
class Badge {
AK_MAKE_NONCOPYABLE(Badge);
AK_MAKE_NONMOVABLE(Badge);
public:
using Type = T;
private:
friend T;
constexpr Badge() = default;
Badge(Badge const&) = delete;
Badge& operator=(Badge const&) = delete;
Badge(Badge&&) = delete;
Badge& operator=(Badge&&) = delete;
};
}

View file

@ -122,6 +122,13 @@ concept IterableContainer = requires {
} -> IteratorPairWith<decltype(declval<T>().end())>;
};
template<typename T, typename ValueT>
concept IterableContainerOf = IterableContainer<T> && requires {
{
*declval<T>().begin()
} -> SameAs<ValueT>;
};
template<typename Func, typename... Args>
concept FallibleFunction = requires(Func&& func, Args&&... args) {
func(forward<Args>(args)...).is_error();
@ -173,6 +180,7 @@ using AK::Concepts::Fundamental;
using AK::Concepts::Indexable;
using AK::Concepts::Integral;
using AK::Concepts::IterableContainer;
using AK::Concepts::IterableContainerOf;
using AK::Concepts::IteratorFunction;
using AK::Concepts::IteratorPairWith;
using AK::Concepts::OneOf;

View file

@ -37,7 +37,7 @@ public:
{
}
template<IterableContainer ContainerT>
template<IterableContainerOf<JsonValue> ContainerT>
JsonArray(ContainerT const& source)
{
for (auto& value : source)

View file

@ -7,60 +7,41 @@
#pragma once
#include <AK/Forward.h>
#include <AK/Noncopyable.h>
#include <AK/Traits.h>
namespace AK {
template<typename T>
requires(!IsLvalueReference<T> && !IsRvalueReference<T>) class [[nodiscard]] NonnullRawPtr {
AK_MAKE_DEFAULT_COPYABLE(NonnullRawPtr);
AK_MAKE_DEFAULT_MOVABLE(NonnullRawPtr);
public:
using ValueType = T;
NonnullRawPtr() = delete;
constexpr NonnullRawPtr() = delete;
constexpr NonnullRawPtr(T const&&) = delete;
NonnullRawPtr(T& other)
constexpr NonnullRawPtr(T& other)
: m_ptr(&other)
{
}
NonnullRawPtr(NonnullRawPtr const& other)
: m_ptr(other.m_ptr)
{
}
constexpr operator bool() const = delete;
constexpr bool operator!() const = delete;
NonnullRawPtr(NonnullRawPtr&& other)
: m_ptr(other.m_ptr)
{
}
constexpr operator T&() { return *m_ptr; }
constexpr operator T const&() const { return *m_ptr; }
NonnullRawPtr& operator=(NonnullRawPtr const& other)
{
m_ptr = other.m_ptr;
[[nodiscard]] ALWAYS_INLINE constexpr T& value() { return *m_ptr; }
[[nodiscard]] ALWAYS_INLINE constexpr T const& value() const { return *m_ptr; }
return *this;
}
[[nodiscard]] ALWAYS_INLINE constexpr T& operator*() { return value(); }
[[nodiscard]] ALWAYS_INLINE constexpr T const& operator*() const { return value(); }
NonnullRawPtr& operator=(NonnullRawPtr&& other)
{
m_ptr = other.m_ptr;
return *this;
}
operator bool() const = delete;
bool operator!() const = delete;
operator T&() { return *m_ptr; }
operator T const&() const { return *m_ptr; }
[[nodiscard]] ALWAYS_INLINE T& value() { return *m_ptr; }
[[nodiscard]] ALWAYS_INLINE T const& value() const { return *m_ptr; }
[[nodiscard]] ALWAYS_INLINE T& operator*() { return value(); }
[[nodiscard]] ALWAYS_INLINE T const& operator*() const { return value(); }
ALWAYS_INLINE RETURNS_NONNULL T* operator->() { return &value(); }
ALWAYS_INLINE RETURNS_NONNULL T const* operator->() const { return &value(); }
ALWAYS_INLINE RETURNS_NONNULL constexpr T* operator->() { return &value(); }
ALWAYS_INLINE RETURNS_NONNULL constexpr T const* operator->() const { return &value(); }
private:
T* m_ptr;

View file

@ -456,6 +456,19 @@ using AssertSize = __AssertSize<T, ExpectedSize, sizeof(T)>;
template<typename T>
inline constexpr bool IsPOD = __is_pod(T);
template<template<typename...> class Base, typename Derived>
struct __IsTemplateBaseOf {
template<typename... Args>
static TrueType test(Base<Args...> const*);
static FalseType test(...);
using type = decltype(test(declval<Derived*>()));
};
template<template<typename...> class Base, typename Derived>
inline constexpr bool IsTemplateBaseOf = __IsTemplateBaseOf<Base, Derived>::type::value;
template<typename T>
inline constexpr bool IsTrivial = __is_trivial(T);
@ -654,6 +667,7 @@ using AK::Detail::IsSame;
using AK::Detail::IsSameIgnoringCV;
using AK::Detail::IsSigned;
using AK::Detail::IsSpecializationOf;
using AK::Detail::IsTemplateBaseOf;
using AK::Detail::IsTrivial;
using AK::Detail::IsTriviallyAssignable;
using AK::Detail::IsTriviallyConstructible;

View file

@ -21,11 +21,11 @@
// from a fallible expression. This will not do what you want; the statement expression
// will create a copy regardless, so it is explicitly disallowed.
#define TRY(expression) \
#define TRY(...) \
({ \
/* Ignore -Wshadow to allow nesting the macro. */ \
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
auto&& _temporary_result = (expression)); \
auto&& _temporary_result = (__VA_ARGS__)); \
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
if (_temporary_result.is_error()) [[unlikely]] \
@ -33,11 +33,11 @@
_temporary_result.release_value(); \
})
#define MUST(expression) \
#define MUST(...) \
({ \
/* Ignore -Wshadow to allow nesting the macro. */ \
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
auto&& _temporary_result = (expression)); \
auto&& _temporary_result = (__VA_ARGS__)); \
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
VERIFY(!_temporary_result.is_error()); \

View file

@ -17,11 +17,11 @@
namespace JS {
#define TRY_OR_THROW_OOM(vm, expression) \
#define TRY_OR_THROW_OOM(vm, ...) \
({ \
/* Ignore -Wshadow to allow nesting the macro. */ \
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
auto&& _temporary_result = (expression)); \
auto&& _temporary_result = (__VA_ARGS__)); \
if (_temporary_result.is_error()) { \
VERIFY(_temporary_result.error().code() == ENOMEM); \
return (vm).throw_completion<JS::InternalError>((vm).error_message(::JS::VM::ErrorMessage::OutOfMemory)); \
@ -31,11 +31,11 @@ namespace JS {
_temporary_result.release_value(); \
})
#define MUST_OR_THROW_OOM(expression) \
#define MUST_OR_THROW_OOM(...) \
({ \
/* Ignore -Wshadow to allow nesting the macro. */ \
AK_IGNORE_DIAGNOSTIC("-Wshadow", \
auto&& _temporary_result = (expression)); \
auto&& _temporary_result = (__VA_ARGS__)); \
if (_temporary_result.is_error()) { \
auto _completion = _temporary_result.release_error(); \
\

View file

@ -5,7 +5,7 @@ set -e
script_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
cd "${script_path}/.." || exit 1
RED='\033[0;31m'
BOLD_RED='\033[0;1;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
@ -27,7 +27,7 @@ for cmd in \
if "${cmd}" "$@"; then
echo -e "[${GREEN}OK${NC}]: ${cmd}"
else
echo -e "[${RED}FAIL${NC}]: ${cmd}"
echo -e "[${BOLD_RED}FAIL${NC}]: ${cmd}"
((FAILURES+=1))
fi
done
@ -36,7 +36,7 @@ if [ -x ./Build/lagom/bin/IPCMagicLinter ]; then
if { git ls-files '*.ipc' | xargs ./Build/lagom/bin/IPCMagicLinter; }; then
echo -e "[${GREEN}OK${NC}]: IPCMagicLinter (in Meta/lint-ci.sh)"
else
echo -e "[${RED}FAIL${NC}]: IPCMagicLinter (in Meta/lint-ci.sh)"
echo -e "[${BOLD_RED}FAIL${NC}]: IPCMagicLinter (in Meta/lint-ci.sh)"
((FAILURES+=1))
fi
else
@ -46,14 +46,14 @@ fi
if Meta/lint-clang-format.sh --overwrite-inplace "$@" && git diff --exit-code -- ':*.cpp' ':*.h' ':*.mm'; then
echo -e "[${GREEN}OK${NC}]: Meta/lint-clang-format.sh"
else
echo -e "[${RED}FAIL${NC}]: Meta/lint-clang-format.sh"
echo -e "[${BOLD_RED}FAIL${NC}]: Meta/lint-clang-format.sh"
((FAILURES+=1))
fi
if Meta/lint-swift.sh "$@" && git diff --exit-code -- ':*.swift'; then
echo -e "[${GREEN}OK${NC}]: Meta/lint-swift.sh"
else
echo -e "[${RED}FAIL${NC}]: Meta/lint-swift.sh"
echo -e "[${BOLD_RED}FAIL${NC}]: Meta/lint-swift.sh"
((FAILURES+=1))
fi