[gjs/mozjs78: 30/50] maint: Use C++17 attributes




commit f092bf74a260200c3c118c843aacfa35d003c88c
Author: Philip Chimento <philip chimento gmail com>
Date:   Sat Aug 1 13:46:57 2020 -0700

    maint: Use C++17 attributes
    
    Now that we depend on C++17, we can use these attributes that are part
    of the language, instead of relying on macros to make them portable.
    (GJS_USE still needs to be defined for public header files, which may be
    compiled in C.)
    
    Attributes which are new in C++17 are [[maybe_unused]], [[nodiscard]],
    and [[fallthrough]].
    
    [skip cpplint] because cpplint doesn't deal with C++ attributes:
    https://github.com/google/styleguide/issues/165

 gi/arg-cache.cpp                  | 49 ++++++++++------------
 gi/arg-cache.h                    |  6 +--
 gi/arg-inl.h                      | 57 +++++++++++++-------------
 gi/arg.cpp                        | 71 +++++++++++---------------------
 gi/arg.h                          |  7 ++--
 gi/boxed.cpp                      | 16 +++-----
 gi/boxed.h                        | 23 +++++------
 gi/closure.h                      | 32 ++++++---------
 gi/foreign.cpp                    | 19 +++------
 gi/function.cpp                   | 11 ++---
 gi/fundamental.cpp                |  4 +-
 gi/fundamental.h                  | 11 ++---
 gi/gerror.cpp                     | 10 +----
 gi/gerror.h                       | 16 ++++----
 gi/gobject.cpp                    |  9 ++--
 gi/gtype.cpp                      |  2 +-
 gi/gtype.h                        |  6 +--
 gi/interface.h                    |  2 +-
 gi/ns.cpp                         |  2 +-
 gi/object.cpp                     | 36 ++++++----------
 gi/object.h                       | 66 +++++++++++++-----------------
 gi/param.h                        |  7 +---
 gi/repo.cpp                       | 11 ++---
 gi/repo.h                         |  7 +---
 gi/toggle.h                       | 22 ++++------
 gi/union.h                        |  4 +-
 gi/value.cpp                      | 12 ++----
 gi/value.h                        | 14 +++----
 gi/wrapperutils.h                 | 86 +++++++++++++++++----------------------
 gjs/atoms.h                       |  4 +-
 gjs/byteArray.cpp                 |  2 +-
 gjs/byteArray.h                   |  7 +---
 gjs/console.cpp                   | 17 ++------
 gjs/context-private.h             | 43 +++++++++++---------
 gjs/context.cpp                   |  8 ++--
 gjs/coverage.cpp                  | 47 ++++++---------------
 gjs/engine.cpp                    |  2 +-
 gjs/global.cpp                    | 25 ++++--------
 gjs/importer.cpp                  |  5 +--
 gjs/jsapi-class.h                 | 41 ++++++++-----------
 gjs/jsapi-dynamic-class.cpp       |  5 +--
 gjs/jsapi-util-args.h             |  6 +--
 gjs/jsapi-util-root.h             | 14 +++----
 gjs/jsapi-util-string.cpp         |  5 +--
 gjs/jsapi-util.cpp                | 12 ++----
 gjs/jsapi-util.h                  | 46 +++++++++++----------
 gjs/macros.h                      | 19 ++++-----
 gjs/module.cpp                    |  9 +---
 gjs/native.h                      |  3 +-
 gjs/profiler-private.h            |  3 +-
 gjs/profiler.cpp                  |  8 +---
 modules/cairo-context.cpp         | 17 +++-----
 modules/cairo-image-surface.cpp   |  3 +-
 modules/cairo-linear-gradient.cpp |  3 +-
 modules/cairo-path.cpp            |  4 +-
 modules/cairo-pdf-surface.cpp     |  3 +-
 modules/cairo-private.h           | 14 +++----
 modules/cairo-ps-surface.cpp      |  3 +-
 modules/cairo-radial-gradient.cpp |  3 +-
 modules/cairo-region.cpp          | 17 +++-----
 modules/cairo-solid-pattern.cpp   |  3 +-
 modules/cairo-surface-pattern.cpp |  3 +-
 modules/cairo-surface.cpp         | 14 ++-----
 modules/cairo-svg-surface.cpp     |  3 +-
 modules/console.cpp               | 15 +++----
 util/log.h                        | 12 +++---
 66 files changed, 423 insertions(+), 643 deletions(-)
---
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index 954378f7..a3ed782a 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -78,8 +78,8 @@ static void gjs_destroy_notify_callback(void* data) {
 
 // A helper function to retrieve array lengths from a GIArgument (letting the
 // compiler generate good instructions in case of big endian machines)
-GJS_USE
-static size_t gjs_g_argument_get_array_length(GITypeTag tag, GIArgument* arg) {
+[[nodiscard]] static size_t gjs_g_argument_get_array_length(GITypeTag tag,
+                                                            GIArgument* arg) {
     if (tag == GI_TYPE_TAG_INT8)
         return gjs_arg_get<int8_t>(arg);
     if (tag == GI_TYPE_TAG_UINT8)
@@ -384,8 +384,7 @@ static int32_t min_max_ints[5][2] = {{G_MININT8, G_MAXINT8},
                                      {0, G_MAXUINT16},
                                      {G_MININT32, G_MAXINT32}};
 
-GJS_USE
-static inline bool value_in_range(int32_t number, GITypeTag tag) {
+[[nodiscard]] static inline bool value_in_range(int32_t number, GITypeTag tag) {
     return (number >= min_max_ints[tag - GI_TYPE_TAG_INT8][0] &&
             number <= min_max_ints[tag - GI_TYPE_TAG_INT8][1]);
 }
@@ -786,17 +785,15 @@ static bool gjs_marshal_explicit_array_out_out(JSContext* cx,
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_skipped_release(JSContext*, GjsArgumentCache*,
                                         GjsFunctionCallState*,
-                                        GIArgument* in_arg G_GNUC_UNUSED,
-                                        GIArgument* out_arg G_GNUC_UNUSED) {
+                                        GIArgument* in_arg [[maybe_unused]],
+                                        GIArgument* out_arg [[maybe_unused]]) {
     return true;
 }
 
 GJS_JSAPI_RETURN_CONVENTION
-static bool gjs_marshal_generic_in_release(JSContext* cx,
-                                           GjsArgumentCache* self,
-                                           GjsFunctionCallState* state,
-                                           GIArgument* in_arg,
-                                           GIArgument* out_arg G_GNUC_UNUSED) {
+static bool gjs_marshal_generic_in_release(
+    JSContext* cx, GjsArgumentCache* self, GjsFunctionCallState* state,
+    GIArgument* in_arg, GIArgument* out_arg [[maybe_unused]]) {
     GITransfer transfer =
         state->call_completed ? self->transfer : GI_TRANSFER_NOTHING;
     return gjs_g_argument_release_in_arg(cx, transfer, &self->type_info,
@@ -807,7 +804,7 @@ GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_generic_out_release(JSContext* cx,
                                             GjsArgumentCache* self,
                                             GjsFunctionCallState*,
-                                            GIArgument* in_arg G_GNUC_UNUSED,
+                                            GIArgument* in_arg [[maybe_unused]],
                                             GIArgument* out_arg) {
     return gjs_g_argument_release(cx, self->transfer, &self->type_info,
                                   out_arg);
@@ -835,7 +832,7 @@ static bool gjs_marshal_generic_inout_release(JSContext* cx,
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_explicit_array_out_release(
     JSContext* cx, GjsArgumentCache* self, GjsFunctionCallState* state,
-    GIArgument* in_arg G_GNUC_UNUSED, GIArgument* out_arg) {
+    GIArgument* in_arg [[maybe_unused]], GIArgument* out_arg) {
     uint8_t length_pos = self->contents.array.length_pos;
     GIArgument* length_arg = &(state->out_cvalues[length_pos]);
     GITypeTag length_tag = self->contents.array.length_tag;
@@ -848,7 +845,7 @@ static bool gjs_marshal_explicit_array_out_release(
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_explicit_array_in_release(
     JSContext* cx, GjsArgumentCache* self, GjsFunctionCallState* state,
-    GIArgument* in_arg, GIArgument* out_arg G_GNUC_UNUSED) {
+    GIArgument* in_arg, GIArgument* out_arg [[maybe_unused]]) {
     uint8_t length_pos = self->contents.array.length_pos;
     GIArgument* length_arg = &(state->in_cvalues[length_pos]);
     GITypeTag length_tag = self->contents.array.length_tag;
@@ -864,7 +861,7 @@ static bool gjs_marshal_explicit_array_in_release(
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_explicit_array_inout_release(
     JSContext* cx, GjsArgumentCache* self, GjsFunctionCallState* state,
-    GIArgument* in_arg G_GNUC_UNUSED, GIArgument* out_arg) {
+    GIArgument* in_arg [[maybe_unused]], GIArgument* out_arg) {
     uint8_t length_pos = self->contents.array.length_pos;
     GIArgument* length_arg = &(state->in_cvalues[length_pos]);
     GITypeTag length_tag = self->contents.array.length_tag;
@@ -889,7 +886,7 @@ static bool gjs_marshal_explicit_array_inout_release(
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_caller_allocates_release(
     JSContext*, GjsArgumentCache* self, GjsFunctionCallState*,
-    GIArgument* in_arg, GIArgument* out_arg G_GNUC_UNUSED) {
+    GIArgument* in_arg, GIArgument* out_arg [[maybe_unused]]) {
     g_slice_free1(self->contents.caller_allocates_size,
                   gjs_arg_get<void*>(in_arg));
     return true;
@@ -899,7 +896,7 @@ GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_callback_release(JSContext*, GjsArgumentCache*,
                                          GjsFunctionCallState*,
                                          GIArgument* in_arg,
-                                         GIArgument* out_arg G_GNUC_UNUSED) {
+                                         GIArgument* out_arg [[maybe_unused]]) {
     auto* closure = gjs_arg_get<ffi_closure*>(in_arg);
     if (!closure)
         return true;
@@ -917,17 +914,16 @@ GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_string_in_release(JSContext*, GjsArgumentCache*,
                                           GjsFunctionCallState*,
                                           GIArgument* in_arg,
-                                          GIArgument* out_arg G_GNUC_UNUSED) {
+                                          GIArgument* out_arg
+                                          [[maybe_unused]]) {
     g_free(gjs_arg_get<void*>(in_arg));
     return true;
 }
 
 GJS_JSAPI_RETURN_CONVENTION
-static bool gjs_marshal_foreign_in_release(JSContext* cx,
-                                           GjsArgumentCache* self,
-                                           GjsFunctionCallState* state,
-                                           GIArgument* in_arg,
-                                           GIArgument* out_arg G_GNUC_UNUSED) {
+static bool gjs_marshal_foreign_in_release(
+    JSContext* cx, GjsArgumentCache* self, GjsFunctionCallState* state,
+    GIArgument* in_arg, GIArgument* out_arg [[maybe_unused]]) {
     bool ok = true;
 
     GITransfer transfer =
@@ -945,7 +941,7 @@ GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_marshal_boxed_in_release(JSContext*, GjsArgumentCache* self,
                                          GjsFunctionCallState*,
                                          GIArgument* in_arg,
-                                         GIArgument* out_arg G_GNUC_UNUSED) {
+                                         GIArgument* out_arg [[maybe_unused]]) {
     GType gtype = g_registered_type_info_get_g_type(self->contents.info);
     g_assert(g_type_is_a(gtype, G_TYPE_BOXED));
 
@@ -1287,8 +1283,7 @@ static void gjs_arg_cache_build_flags_mask(GjsArgumentCache* self,
     self->contents.flags_mask = mask;
 }
 
-GJS_USE
-static inline bool is_gdk_atom(GIBaseInfo* info) {
+[[nodiscard]] static inline bool is_gdk_atom(GIBaseInfo* info) {
     return strcmp("Atom", g_base_info_get_name(info)) == 0 &&
            strcmp("Gdk", g_base_info_get_namespace(info)) == 0;
 }
@@ -1324,7 +1319,7 @@ static bool gjs_arg_cache_build_interface_in_arg(JSContext* cx,
                     self->marshallers = &foreign_struct_in_marshallers;
                 return true;
             }
-            // fall through
+            [[fallthrough]];
         case GI_INFO_TYPE_BOXED:
         case GI_INFO_TYPE_OBJECT:
         case GI_INFO_TYPE_INTERFACE:
diff --git a/gi/arg-cache.h b/gi/arg-cache.h
index 82e4c0d3..a7223920 100644
--- a/gi/arg-cache.h
+++ b/gi/arg-cache.h
@@ -125,14 +125,14 @@ struct GjsArgumentCache {
         g_assert(pos <= MAX_ARGS && "No more than 253 arguments allowed");
         contents.callback.destroy_pos = pos < 0 ? ABSENT : pos;
     }
-    GJS_USE bool has_callback_destroy() {
+    [[nodiscard]] bool has_callback_destroy() {
         return contents.callback.destroy_pos != ABSENT;
     }
     void set_callback_closure_pos(int pos) {
         g_assert(pos <= MAX_ARGS && "No more than 253 arguments allowed");
         contents.callback.closure_pos = pos < 0 ? ABSENT : pos;
     }
-    GJS_USE bool has_callback_closure() {
+    [[nodiscard]] bool has_callback_closure() {
         return contents.callback.closure_pos != ABSENT;
     }
 
@@ -150,7 +150,7 @@ struct GjsArgumentCache {
         arg_name = "return value";
         nullable = false;  // We don't really care for return values
     }
-    GJS_USE bool is_return_value() { return arg_pos == RETURN_VALUE; }
+    [[nodiscard]] bool is_return_value() { return arg_pos == RETURN_VALUE; }
 };
 
 // This is a trick to print out the sizes of the structs at compile time, in
diff --git a/gi/arg-inl.h b/gi/arg-inl.h
index 7f313769..bdc474fc 100644
--- a/gi/arg-inl.h
+++ b/gi/arg-inl.h
@@ -16,8 +16,6 @@
 #include <glib-object.h>  // for GType
 #include <glib.h>         // for gboolean
 
-#include "gjs/macros.h"
-
 // GIArgument accessor templates
 //
 // These are intended to make access to the GIArgument union more type-safe and
@@ -35,8 +33,8 @@
 //   appropriate union member for type T.
 
 template <typename T>
-GJS_USE inline decltype(auto) gjs_arg_member(GIArgument* arg,
-                                             T GIArgument::*member) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member(GIArgument* arg,
+                                                   T GIArgument::*member) {
     return (arg->*member);
 }
 
@@ -44,7 +42,7 @@ GJS_USE inline decltype(auto) gjs_arg_member(GIArgument* arg,
  * which are in fact typedef's of other generic types.
  * Setting a tag for a type allows to perform proper specialization. */
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-GJS_USE inline decltype(auto) gjs_arg_member(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member(GIArgument* arg) {
     static_assert(!std::is_arithmetic<T>(), "Missing declaration for type");
 
     using NonconstPtrT =
@@ -54,64 +52,64 @@ GJS_USE inline decltype(auto) gjs_arg_member(GIArgument* arg) {
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<bool>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<bool>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_boolean);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<gboolean, GI_TYPE_TAG_BOOLEAN>(
-    GIArgument* arg) {
+[[nodiscard]] inline decltype(auto)
+gjs_arg_member<gboolean, GI_TYPE_TAG_BOOLEAN>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_boolean);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<int8_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<int8_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_int8);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<uint8_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<uint8_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_uint8);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<int16_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<int16_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_int16);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<uint16_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<uint16_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_uint16);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<int32_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<int32_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_int32);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<uint32_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<uint32_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_uint32);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<int64_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<int64_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_int64);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<uint64_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<uint64_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_uint64);
 }
 
 // gunichar is stored in v_uint32
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<char32_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<char32_t>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_uint32);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<GType, GI_TYPE_TAG_GTYPE>(
+[[nodiscard]] inline decltype(auto) gjs_arg_member<GType, GI_TYPE_TAG_GTYPE>(
     GIArgument* arg) {
     // GType is defined differently on 32-bit vs. 64-bit architectures. From gtype.h:
     //
@@ -127,40 +125,41 @@ GJS_USE inline decltype(auto) gjs_arg_member<GType, GI_TYPE_TAG_GTYPE>(
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<float>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<float>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_float);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<double>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<double>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_double);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<char*>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<char*>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_string);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<void*>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<void*>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_pointer);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<std::nullptr_t>(GIArgument* arg) {
+[[nodiscard]] inline decltype(auto) gjs_arg_member<std::nullptr_t>(
+    GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_pointer);
 }
 
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<int, GI_TYPE_TAG_INTERFACE>(
+[[nodiscard]] inline decltype(auto) gjs_arg_member<int, GI_TYPE_TAG_INTERFACE>(
     GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_int);
 }
 
 // Unsigned enums
 template <>
-GJS_USE inline decltype(auto) gjs_arg_member<unsigned, GI_TYPE_TAG_INTERFACE>(
-    GIArgument* arg) {
+[[nodiscard]] inline decltype(auto)
+gjs_arg_member<unsigned, GI_TYPE_TAG_INTERFACE>(GIArgument* arg) {
     return gjs_arg_member(arg, &GIArgument::v_uint);
 }
 
@@ -197,17 +196,17 @@ inline void gjs_arg_set<gboolean, GI_TYPE_TAG_BOOLEAN>(GIArgument* arg,
 }
 
 template <typename T, GITypeTag TAG = GI_TYPE_TAG_VOID>
-GJS_USE inline T gjs_arg_get(GIArgument* arg) {
+[[nodiscard]] inline T gjs_arg_get(GIArgument* arg) {
     return gjs_arg_member<T, TAG>(arg);
 }
 
 template <>
-GJS_USE inline bool gjs_arg_get<bool>(GIArgument* arg) {
+[[nodiscard]] inline bool gjs_arg_get<bool>(GIArgument* arg) {
     return !!gjs_arg_member<bool>(arg);
 }
 
 template <>
-GJS_USE inline gboolean gjs_arg_get<gboolean, GI_TYPE_TAG_BOOLEAN>(
+[[nodiscard]] inline gboolean gjs_arg_get<gboolean, GI_TYPE_TAG_BOOLEAN>(
     GIArgument* arg) {
     return !!gjs_arg_member<bool>(arg);
 }
diff --git a/gi/arg.cpp b/gi/arg.cpp
index ccc6cc80..d02d37d0 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -132,10 +132,7 @@ static bool _gjs_enum_value_is_valid(JSContext* context, GIEnumInfo* enum_info,
     return found;
 }
 
-GJS_USE
-static bool
-_gjs_enum_uses_signed_type (GIEnumInfo *enum_info)
-{
+[[nodiscard]] static bool _gjs_enum_uses_signed_type(GIEnumInfo* enum_info) {
     GITypeTag storage = g_enum_info_get_storage_type(enum_info);
     return (storage == GI_TYPE_TAG_INT8 ||
         storage == GI_TYPE_TAG_INT16 ||
@@ -148,8 +145,7 @@ _gjs_enum_uses_signed_type (GIEnumInfo *enum_info)
 // enumerations being passed on the stack in a 32-bit field. See FIXME comment
 // in g_field_info_get_field(). The same assumption of enums cast to 32-bit
 // signed integers is found in g_value_set_enum()/g_value_set_flags().
-GJS_USE
-int64_t _gjs_enum_from_int(GIEnumInfo* enum_info, int int_value) {
+[[nodiscard]] int64_t _gjs_enum_from_int(GIEnumInfo* enum_info, int int_value) {
     if (_gjs_enum_uses_signed_type (enum_info))
         return int64_t(int_value);
     else
@@ -157,17 +153,15 @@ int64_t _gjs_enum_from_int(GIEnumInfo* enum_info, int int_value) {
 }
 
 /* Here for symmetry, but result is the same for the two cases */
-GJS_USE
-static int _gjs_enum_to_int(int64_t value) { return static_cast<int>(value); }
+[[nodiscard]] static int _gjs_enum_to_int(int64_t value) {
+    return static_cast<int>(value);
+}
 
 /* Check if an argument of the given needs to be released if we created it
  * from a JS value to pass it into a function and aren't transfering ownership.
  */
-GJS_USE
-static bool
-type_needs_release (GITypeInfo *type_info,
-                    GITypeTag   type_tag)
-{
+[[nodiscard]] static bool type_needs_release(GITypeInfo* type_info,
+                                             GITypeTag type_tag) {
     if (type_tag == GI_TYPE_TAG_UTF8 ||
         type_tag == GI_TYPE_TAG_FILENAME ||
         type_tag == GI_TYPE_TAG_ARRAY ||
@@ -225,11 +219,8 @@ type_needs_release (GITypeInfo *type_info,
 /* Check if an argument of the given needs to be released if we obtained it
  * from out argument (or the return value), and we're transferring ownership
  */
-GJS_USE
-static bool
-type_needs_out_release(GITypeInfo *type_info,
-                       GITypeTag   type_tag)
-{
+[[nodiscard]] static bool type_needs_out_release(GITypeInfo* type_info,
+                                                 GITypeTag type_tag) {
     if (type_tag == GI_TYPE_TAG_UTF8 ||
         type_tag == GI_TYPE_TAG_FILENAME ||
         type_tag == GI_TYPE_TAG_ARRAY ||
@@ -265,8 +256,7 @@ type_needs_out_release(GITypeInfo *type_info,
 }
 
 /* FIXME: This should be added to gobject-introspection */
-GJS_USE
-static GITypeTag _g_type_info_get_storage_type(GITypeInfo* info) {
+[[nodiscard]] static GITypeTag _g_type_info_get_storage_type(GITypeInfo* info) {
     GITypeTag type_tag = g_type_info_get_tag(info);
 
     if (type_tag == GI_TYPE_TAG_INTERFACE) {
@@ -337,9 +327,8 @@ static void _g_type_info_argument_from_hash_pointer(GITypeInfo* info,
 }
 
 /* FIXME: This should be added to gobject-introspection */
-GJS_USE
-static void* _g_type_info_hash_pointer_from_argument(GITypeInfo* info,
-                                                     GIArgument* arg) {
+[[nodiscard]] static void* _g_type_info_hash_pointer_from_argument(
+    GITypeInfo* info, GIArgument* arg) {
     GITypeTag type_tag = _g_type_info_get_storage_type(info);
 
     switch (type_tag) {
@@ -463,10 +452,8 @@ gjs_array_to_g_list(JSContext   *context,
     return true;
 }
 
-GJS_USE
-static GHashTable *
-create_hash_table_for_key_type(GITypeInfo  *key_param_info)
-{
+[[nodiscard]] static GHashTable* create_hash_table_for_key_type(
+    GITypeInfo* key_param_info) {
     /* Don't use key/value destructor functions here, because we can't
      * construct correct ones in general if the value type is complex.
      * Rely on the type-aware g_argument_release functions. */
@@ -675,7 +662,7 @@ value_to_ghashtable_key(JSContext      *cx,
 }
 
 template <typename T>
-GJS_USE static T* heap_value_new_from_arg(GIArgument* val_arg) {
+[[nodiscard]] static T* heap_value_new_from_arg(GIArgument* val_arg) {
     T* heap_val = g_new(T, 1);
     *heap_val = gjs_arg_get<T>(val_arg);
 
@@ -1245,11 +1232,7 @@ gjs_array_from_flat_gvalue_array(JSContext             *context,
     return result;
 }
 
-GJS_USE
-static bool
-is_gvalue(GIBaseInfo *info,
-          GIInfoType  info_type)
-{
+[[nodiscard]] static bool is_gvalue(GIBaseInfo* info, GIInfoType info_type) {
     if (info_type == GI_INFO_TYPE_VALUE)
         return true;
 
@@ -1264,11 +1247,8 @@ is_gvalue(GIBaseInfo *info,
     return false;
 }
 
-GJS_USE
-static bool
-is_gvalue_flat_array(GITypeInfo *param_info,
-                     GITypeTag   element_type)
-{
+[[nodiscard]] static bool is_gvalue_flat_array(GITypeInfo* param_info,
+                                               GITypeTag element_type) {
     GIBaseInfo *interface_info;
     GIInfoType info_type;
     bool result;
@@ -1356,7 +1336,7 @@ static bool gjs_array_to_array(JSContext* context, JS::HandleValue array_value,
                     info_type, arr_p);
             }
         }
-        /* fall through */
+        [[fallthrough]];
     case GI_TYPE_TAG_ARRAY:
     case GI_TYPE_TAG_GLIST:
     case GI_TYPE_TAG_GSLIST:
@@ -1458,10 +1438,8 @@ char* gjs_argument_display_name(const char* arg_name,
     }
 }
 
-GJS_USE
-static const char *
-type_tag_to_human_string(GITypeInfo *type_info)
-{
+[[nodiscard]] static const char* type_tag_to_human_string(
+    GITypeInfo* type_info) {
     GITypeTag tag;
 
     tag = g_type_info_get_tag(type_info);
@@ -1559,10 +1537,7 @@ bool gjs_array_to_explicit_array(JSContext* context, JS::HandleValue value,
     return true;
 }
 
-GJS_USE
-static bool
-is_gdk_atom(GIBaseInfo *info)
-{
+[[nodiscard]] static bool is_gdk_atom(GIBaseInfo* info) {
     return (strcmp("Atom", g_base_info_get_name(info)) == 0 &&
             strcmp("Gdk", g_base_info_get_namespace(info)) == 0);
 }
@@ -3566,7 +3541,7 @@ gjs_g_arg_release_internal(JSContext  *context,
                         break;
                     }
                 }
-                /* fall through */
+                [[fallthrough]];
             case GI_TYPE_TAG_GLIST:
             case GI_TYPE_TAG_GSLIST:
             case GI_TYPE_TAG_ARRAY:
diff --git a/gi/arg.h b/gi/arg.h
index 42693d3e..06ea76b5 100644
--- a/gi/arg.h
+++ b/gi/arg.h
@@ -47,8 +47,8 @@ typedef enum {
     GJS_ARGUMENT_ARRAY_ELEMENT
 } GjsArgumentType;
 
-GJS_USE
-char* gjs_argument_display_name(const char* arg_name, GjsArgumentType arg_type);
+[[nodiscard]] char* gjs_argument_display_name(const char* arg_name,
+                                              GjsArgumentType arg_type);
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_value_to_arg(JSContext      *context,
@@ -111,8 +111,7 @@ bool gjs_g_argument_release_in_arg (JSContext  *context,
 GJS_JSAPI_RETURN_CONVENTION
 bool _gjs_flags_value_is_valid(JSContext* cx, GType gtype, int64_t value);
 
-GJS_USE
-int64_t _gjs_enum_from_int(GIEnumInfo* enum_info, int int_value);
+[[nodiscard]] int64_t _gjs_enum_from_int(GIEnumInfo* enum_info, int int_value);
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_array_from_strv(JSContext             *context,
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 9401333b..2537159f 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -63,8 +63,7 @@ BoxedInstance::BoxedInstance(JSContext* cx, JS::HandleObject obj)
     GJS_INC_COUNTER(boxed_instance);
 }
 
-GJS_USE
-static bool struct_is_simple(GIStructInfo *info);
+[[nodiscard]] static bool struct_is_simple(GIStructInfo* info);
 
 // See GIWrapperBase::resolve().
 bool BoxedPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
@@ -100,7 +99,7 @@ bool BoxedPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
 // See GIWrapperBase::new_enumerate().
 bool BoxedPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
                                         JS::MutableHandleIdVector properties,
-                                        bool only_enumerable G_GNUC_UNUSED) {
+                                        bool only_enumerable [[maybe_unused]]) {
     int n_methods = g_struct_info_get_n_methods(info());
     for (int i = 0; i < n_methods; i++) {
         GjsAutoFunctionInfo meth_info = g_struct_info_get_method(info(), i);
@@ -772,10 +771,8 @@ const struct JSClass BoxedBase::klass = {
 };
 // clang-format on
 
-GJS_USE
-static bool
-type_can_be_allocated_directly(GITypeInfo *type_info)
-{
+[[nodiscard]] static bool type_can_be_allocated_directly(
+    GITypeInfo* type_info) {
     bool is_simple = true;
 
     if (g_type_info_is_pointer(type_info)) {
@@ -867,10 +864,7 @@ type_can_be_allocated_directly(GITypeInfo *type_info)
  * type that we know how to assign to. If so, then we can allocate and free
  * instances without needing a constructor.
  */
-GJS_USE
-static bool
-struct_is_simple(GIStructInfo *info)
-{
+[[nodiscard]] static bool struct_is_simple(GIStructInfo* info) {
     int n_fields = g_struct_info_get_n_fields(info);
     bool is_simple = true;
     int i;
diff --git a/gi/boxed.h b/gi/boxed.h
index 01660472..a683d8d5 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -86,14 +86,14 @@ class BoxedBase
 
     // Helper methods that work on either instances or prototypes
 
-    GJS_USE const char* to_string_kind(void) const { return "boxed"; }
+    [[nodiscard]] const char* to_string_kind() const { return "boxed"; }
 
     GJS_JSAPI_RETURN_CONVENTION
     GIFieldInfo* get_field_info(JSContext* cx, uint32_t id) const;
 
  public:
-    GJS_USE
-    BoxedBase* get_copy_source(JSContext* cx, JS::Value value) const;
+    [[nodiscard]] BoxedBase* get_copy_source(JSContext* cx,
+                                             JS::Value value) const;
 };
 
 class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
@@ -122,23 +122,20 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
     // Accessors
 
  public:
-    GJS_USE
-    bool can_allocate_directly(void) const { return m_can_allocate_directly; }
-    GJS_USE
-    bool has_zero_args_constructor(void) const {
+    [[nodiscard]] bool can_allocate_directly() const {
+        return m_can_allocate_directly;
+    }
+    [[nodiscard]] bool has_zero_args_constructor() const {
         return m_zero_args_constructor >= 0;
     }
-    GJS_USE
-    bool has_default_constructor(void) const {
+    [[nodiscard]] bool has_default_constructor() const {
         return m_default_constructor >= 0;
     }
-    GJS_USE
-    GIFunctionInfo* zero_args_constructor_info(void) const {
+    [[nodiscard]] GIFunctionInfo* zero_args_constructor_info() const {
         return g_struct_info_get_method(info(), m_zero_args_constructor);
     }
     // The ID is traced from the object, so it's OK to create a handle from it.
-    GJS_USE
-    JS::HandleId default_constructor_name(void) const {
+    [[nodiscard]] JS::HandleId default_constructor_name() const {
         return JS::HandleId::fromMarkedLocation(
             m_default_constructor_name.address());
     }
diff --git a/gi/closure.h b/gi/closure.h
index e1a2478f..38836b77 100644
--- a/gi/closure.h
+++ b/gi/closure.h
@@ -30,30 +30,24 @@
 
 #include <js/TypeDecls.h>
 
-#include "gjs/macros.h"
-
 class JSTracer;
 namespace JS {
 class HandleValueArray;
 }
 
-GJS_USE
-GClosure* gjs_closure_new(JSContext* cx, JSFunction* callable,
-                          const char* description, bool root_function);
-
-GJS_USE
-bool gjs_closure_invoke(GClosure                   *closure,
-                        JS::HandleObject            this_obj,
-                        const JS::HandleValueArray& args,
-                        JS::MutableHandleValue      retval,
-                        bool                        return_exception);
-
-GJS_USE
-JSContext* gjs_closure_get_context   (GClosure     *closure);
-GJS_USE
-bool       gjs_closure_is_valid      (GClosure     *closure);
-GJS_USE
-JSFunction* gjs_closure_get_callable(GClosure* closure);
+[[nodiscard]] GClosure* gjs_closure_new(JSContext* cx, JSFunction* callable,
+                                        const char* description,
+                                        bool root_function);
+
+[[nodiscard]] bool gjs_closure_invoke(GClosure* closure,
+                                      JS::HandleObject this_obj,
+                                      const JS::HandleValueArray& args,
+                                      JS::MutableHandleValue retval,
+                                      bool return_exception);
+
+[[nodiscard]] JSContext* gjs_closure_get_context(GClosure* closure);
+[[nodiscard]] bool gjs_closure_is_valid(GClosure* closure);
+[[nodiscard]] JSFunction* gjs_closure_get_callable(GClosure* closure);
 
 void       gjs_closure_trace         (GClosure     *closure,
                                       JSTracer     *tracer);
diff --git a/gi/foreign.cpp b/gi/foreign.cpp
index 2b7b8041..7692147f 100644
--- a/gi/foreign.cpp
+++ b/gi/foreign.cpp
@@ -46,10 +46,7 @@ static struct {
 
 static GHashTable* foreign_structs_table = NULL;
 
-GJS_USE
-static GHashTable*
-get_foreign_structs(void)
-{
+[[nodiscard]] static GHashTable* get_foreign_structs() {
     // FIXME: look into hasing on GITypeInfo instead.
     if (!foreign_structs_table) {
         foreign_structs_table = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -60,11 +57,8 @@ get_foreign_structs(void)
     return foreign_structs_table;
 }
 
-GJS_USE
-static bool
-gjs_foreign_load_foreign_module(JSContext *context,
-                                const gchar *gi_namespace)
-{
+[[nodiscard]] static bool gjs_foreign_load_foreign_module(
+    JSContext* context, const char* gi_namespace) {
     int i;
 
     for (i = 0; foreign_modules[i].gi_namespace; ++i) {
@@ -106,11 +100,8 @@ void gjs_struct_foreign_register(const char* gi_namespace,
     g_hash_table_insert(get_foreign_structs(), canonical_name, info);
 }
 
-GJS_USE
-static GjsForeignInfo *
-gjs_struct_foreign_lookup(JSContext  *context,
-                          GIBaseInfo *interface_info)
-{
+[[nodiscard]] static GjsForeignInfo* gjs_struct_foreign_lookup(
+    JSContext* context, GIBaseInfo* interface_info) {
     GjsForeignInfo *retval = NULL;
     GHashTable *hash_table;
     char *key;
diff --git a/gi/function.cpp b/gi/function.cpp
index aff052ef..e194b8ec 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -206,7 +206,7 @@ warn_about_illegal_js_callback(const GjsCallbackTrampoline *trampoline,
  * In other words, everything we need to call the JS function and
  * getting the return value back.
  */
-static void gjs_callback_closure(ffi_cif* cif G_GNUC_UNUSED, void* result,
+static void gjs_callback_closure(ffi_cif* cif [[maybe_unused]], void* result,
                                  void** ffi_args, void* data) {
     JSContext *context;
     GjsCallbackTrampoline *trampoline;
@@ -603,8 +603,7 @@ GjsCallbackTrampoline* gjs_callback_trampoline_new(
 }
 
 /* Intended for error messages. Return value must be freed */
-GJS_USE
-static char* format_function_name(Function* function) {
+[[nodiscard]] static char* format_function_name(Function* function) {
     if (g_callable_info_is_method(function->info))
         return g_strdup_printf(
             "method %s.%s.%s", g_base_info_get_namespace(function->info),
@@ -1263,10 +1262,8 @@ init_cached_function_data (JSContext      *context,
     return true;
 }
 
-GJS_USE
-static inline JSObject *
-gjs_builtin_function_get_proto(JSContext *cx)
-{
+[[nodiscard]] static inline JSObject* gjs_builtin_function_get_proto(
+    JSContext* cx) {
     return JS::GetRealmFunctionPrototype(cx);
 }
 
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index f3f64c3e..0f5c3551 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -84,8 +84,8 @@ bool FundamentalInstance::associate_js_instance(JSContext* cx, JSObject* object,
 /**/
 
 /* Find the first constructor */
-GJS_USE
-static GIFunctionInfo* find_fundamental_constructor(GIObjectInfo* info) {
+[[nodiscard]] static GIFunctionInfo* find_fundamental_constructor(
+    GIObjectInfo* info) {
     int i, n_methods;
 
     n_methods = g_object_info_get_n_methods(info);
diff --git a/gi/fundamental.h b/gi/fundamental.h
index a26461eb..69084f96 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -65,7 +65,7 @@ class FundamentalBase
 
     // Helper methods
 
-    GJS_USE const char* to_string_kind(void) const { return "fundamental"; }
+    [[nodiscard]] const char* to_string_kind() const { return "fundamental"; }
 
     // Public API
 
@@ -99,12 +99,13 @@ class FundamentalPrototype
 
     // Accessors
 
-    GJS_USE
-    GICallableInfo* constructor_info(void) const { return m_constructor_info; }
+    [[nodiscard]] GICallableInfo* constructor_info() const {
+        return m_constructor_info;
+    }
 
     void* call_ref_function(void* ptr) const { return m_ref_function(ptr); }
     void call_unref_function(void* ptr) const { m_unref_function(ptr); }
-    GJS_USE void* call_get_value_function(const GValue* value) const {
+    [[nodiscard]] void* call_get_value_function(const GValue* value) const {
         return m_get_value_function(value);
     }
     void call_set_value_function(GValue* value, void* object) const {
@@ -117,7 +118,7 @@ class FundamentalPrototype
     GJS_JSAPI_RETURN_CONVENTION
     bool get_parent_proto(JSContext* cx, JS::MutableHandleObject proto) const;
 
-    GJS_USE unsigned constructor_nargs(void) const;
+    [[nodiscard]] unsigned constructor_nargs() const;
 
     GJS_JSAPI_RETURN_CONVENTION
     bool resolve_interface(JSContext* cx, JS::HandleObject obj, bool* resolved,
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 75211148..851f9dec 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -256,10 +256,7 @@ bool ErrorPrototype::define_class(JSContext* context,
            gjs_define_enum_values(context, constructor, info);
 }
 
-GJS_USE
-static GIEnumInfo *
-find_error_domain_info(GQuark domain)
-{
+[[nodiscard]] static GIEnumInfo* find_error_domain_info(GQuark domain) {
     GIEnumInfo *info;
 
     /* first an attempt without loading extra libraries */
@@ -320,10 +317,7 @@ bool gjs_define_error_properties(JSContext* cx, JS::HandleObject obj) {
                                  JSPROP_ENUMERATE);
 }
 
-GJS_USE
-static JSProtoKey
-proto_key_from_error_enum(int val)
-{
+[[nodiscard]] static JSProtoKey proto_key_from_error_enum(int val) {
     switch (val) {
     case GJS_JS_ERROR_EVAL_ERROR:
         return JSProto_EvalError;
diff --git a/gi/gerror.h b/gi/gerror.h
index 4f616c5a..18bf593f 100644
--- a/gi/gerror.h
+++ b/gi/gerror.h
@@ -77,7 +77,7 @@ class ErrorBase
     // Accessors
 
  public:
-    GJS_USE GQuark domain(void) const;
+    [[nodiscard]] GQuark domain(void) const;
 
     // Property getters
 
@@ -111,9 +111,8 @@ class ErrorBase
 
     GJS_JSAPI_RETURN_CONVENTION
     static bool typecheck(JSContext* cx, JS::HandleObject obj);
-    GJS_USE
-    static bool typecheck(JSContext* cx, JS::HandleObject obj,
-                          GjsTypecheckNoThrow);
+    [[nodiscard]] static bool typecheck(JSContext* cx, JS::HandleObject obj,
+                                        GjsTypecheckNoThrow);
 };
 
 class ErrorPrototype : public GIWrapperPrototype<ErrorBase, ErrorPrototype,
@@ -133,7 +132,7 @@ class ErrorPrototype : public GIWrapperPrototype<ErrorBase, ErrorPrototype,
     bool get_parent_proto(JSContext* cx, JS::MutableHandleObject proto) const;
 
  public:
-    GJS_USE GQuark domain(void) const { return m_domain; }
+    [[nodiscard]] GQuark domain(void) const { return m_domain; }
 
     GJS_JSAPI_RETURN_CONVENTION
     static bool define_class(JSContext* cx, JS::HandleObject in_object,
@@ -152,15 +151,14 @@ class ErrorInstance : public GIWrapperInstance<ErrorBase, ErrorPrototype,
  public:
     void copy_gerror(GError* other) { m_ptr = g_error_copy(other); }
     GJS_JSAPI_RETURN_CONVENTION
-    static GError* copy_ptr(JSContext* cx G_GNUC_UNUSED,
-                            GType gtype G_GNUC_UNUSED, void* ptr) {
+    static GError* copy_ptr(JSContext*, GType, void* ptr) {
         return g_error_copy(static_cast<GError*>(ptr));
     }
 
     // Accessors
 
-    GJS_USE const char* message(void) const { return m_ptr->message; }
-    GJS_USE int code(void) const { return m_ptr->code; }
+    [[nodiscard]] const char* message(void) const { return m_ptr->message; }
+    [[nodiscard]] int code(void) const { return m_ptr->code; }
 
     // JS constructor
 
diff --git a/gi/gobject.cpp b/gi/gobject.cpp
index 5e16d77c..81902374 100644
--- a/gi/gobject.cpp
+++ b/gi/gobject.cpp
@@ -44,8 +44,7 @@
 
 static std::unordered_map<GType, AutoParamArray> class_init_properties;
 
-GJS_USE
-static JSContext* current_context(void) {
+[[nodiscard]] static JSContext* current_context() {
     GjsContext* gjs = gjs_context_get_current();
     return static_cast<JSContext*>(gjs_context_get_native_context(gjs));
 }
@@ -149,7 +148,7 @@ static GObject* gjs_object_constructor(
 }
 
 static void gjs_object_set_gproperty(GObject* object,
-                                     unsigned property_id G_GNUC_UNUSED,
+                                     unsigned property_id [[maybe_unused]],
                                      const GValue* value, GParamSpec* pspec) {
     auto* priv = ObjectInstance::for_gobject(object);
     JSContext *cx = current_context();
@@ -162,7 +161,7 @@ static void gjs_object_set_gproperty(GObject* object,
 }
 
 static void gjs_object_get_gproperty(GObject* object,
-                                     unsigned property_id G_GNUC_UNUSED,
+                                     unsigned property_id [[maybe_unused]],
                                      GValue* value, GParamSpec* pspec) {
     auto* priv = ObjectInstance::for_gobject(object);
     JSContext *cx = current_context();
@@ -201,7 +200,7 @@ static void gjs_object_class_init(void* class_pointer, void*) {
 }
 
 static void gjs_object_custom_init(GTypeInstance* instance,
-                                   void* g_class G_GNUC_UNUSED) {
+                                   void* g_class [[maybe_unused]]) {
     JSContext *cx = current_context();
     GjsContextPrivate* gjs = GjsContextPrivate::from_cx(cx);
 
diff --git a/gi/gtype.cpp b/gi/gtype.cpp
index b17d2419..4c56e2a7 100644
--- a/gi/gtype.cpp
+++ b/gi/gtype.cpp
@@ -46,7 +46,7 @@
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
 
-GJS_USE static JSObject* gjs_gtype_get_proto(JSContext* cx) G_GNUC_UNUSED;
+[[nodiscard]] [[maybe_unused]] static JSObject* gjs_gtype_get_proto(JSContext*);
 GJS_JSAPI_RETURN_CONVENTION
 static bool gjs_gtype_define_proto(JSContext *, JS::HandleObject,
                                    JS::MutableHandleObject);
diff --git a/gi/gtype.h b/gi/gtype.h
index ceb1b94b..09d6bfd9 100644
--- a/gi/gtype.h
+++ b/gi/gtype.h
@@ -41,9 +41,7 @@ GJS_JSAPI_RETURN_CONVENTION
 bool gjs_gtype_get_actual_gtype(JSContext* context, JS::HandleObject object,
                                 GType* gtype_out);
 
-GJS_USE
-bool        gjs_typecheck_gtype         (JSContext             *context,
-                                         JS::HandleObject       obj,
-                                         bool                   throw_error);
+[[nodiscard]] bool gjs_typecheck_gtype(JSContext* cx, JS::HandleObject obj,
+                                       bool throw_error);
 
 #endif  // GI_GTYPE_H_
diff --git a/gi/interface.h b/gi/interface.h
index 3440e110..8b3a9456 100644
--- a/gi/interface.h
+++ b/gi/interface.h
@@ -73,7 +73,7 @@ class InterfaceBase : public GIWrapperBase<InterfaceBase, InterfacePrototype,
     static const struct JSClass klass;
     static JSFunctionSpec static_methods[];
 
-    GJS_USE const char* to_string_kind(void) const { return "interface"; }
+    [[nodiscard]] const char* to_string_kind(void) const { return "interface"; }
 
     // JSNative methods
 
diff --git a/gi/ns.cpp b/gi/ns.cpp
index 79681f7e..7cba73d5 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -120,7 +120,7 @@ ns_resolve(JSContext       *context,
 GJS_JSAPI_RETURN_CONVENTION
 static bool ns_new_enumerate(JSContext* cx, JS::HandleObject obj,
                              JS::MutableHandleIdVector properties,
-                             bool only_enumerable G_GNUC_UNUSED) {
+                             bool only_enumerable [[maybe_unused]]) {
     Ns* priv = priv_from_js(cx, obj);
 
     if (!priv) {
diff --git a/gi/object.cpp b/gi/object.cpp
index d5c9ba96..d9a946cd 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -101,10 +101,7 @@ G_DEFINE_QUARK(gjs::custom-type, ObjectBase::custom_type)
 G_DEFINE_QUARK(gjs::custom-property, ObjectBase::custom_property)
 // clang-format on
 
-GJS_USE
-static GQuark
-gjs_object_priv_quark (void)
-{
+[[nodiscard]] static GQuark gjs_object_priv_quark() {
     static GQuark val = 0;
     if (G_UNLIKELY (!val))
         val = g_quark_from_static_string ("gjs::private");
@@ -379,9 +376,8 @@ bool ObjectInstance::prop_getter_impl(JSContext* cx, JS::HandleString name,
     return true;
 }
 
-GJS_USE
-static GjsAutoFieldInfo lookup_field_info(GIObjectInfo* info,
-                                          const char* name) {
+[[nodiscard]] static GjsAutoFieldInfo lookup_field_info(GIObjectInfo* info,
+                                                        const char* name) {
     int n_fields = g_object_info_get_n_fields(info);
     int ix;
     GjsAutoFieldInfo retval;
@@ -574,10 +570,8 @@ bool ObjectPrototype::is_vfunc_unchanged(GIVFuncInfo* info) {
     return addr1 == addr2;
 }
 
-GJS_USE
-static GjsAutoVFuncInfo find_vfunc_on_parents(GIObjectInfo* info,
-                                              const char* name,
-                                              bool* out_defined_by_parent) {
+[[nodiscard]] static GjsAutoVFuncInfo find_vfunc_on_parents(
+    GIObjectInfo* info, const char* name, bool* out_defined_by_parent) {
     bool defined_by_parent = false;
 
     /* ref the first info so that we don't destroy
@@ -615,9 +609,8 @@ static void canonicalize_key(const GjsAutoChar& key) {
 }
 
 /* @name must already be canonicalized */
-GJS_USE
-static bool is_ginterface_property_name(GIInterfaceInfo* info,
-                                        const char* name) {
+[[nodiscard]] static bool is_ginterface_property_name(GIInterfaceInfo* info,
+                                                      const char* name) {
     int n_props = g_interface_info_get_n_properties(info);
     GjsAutoPropertyInfo prop_info;
 
@@ -739,11 +732,8 @@ bool ObjectPrototype::resolve_no_info(JSContext* cx, JS::HandleObject obj,
     return true;
 }
 
-GJS_USE
-static bool
-is_gobject_property_name(GIObjectInfo *info,
-                         const char   *name)
-{
+[[nodiscard]] static bool is_gobject_property_name(GIObjectInfo* info,
+                                                   const char* name) {
     // Optimization: GObject property names must start with a letter
     if (!g_ascii_isalpha(name[0]))
         return false;
@@ -927,7 +917,8 @@ bool ObjectPrototype::uncached_resolve(JSContext* context, JS::HandleObject obj,
 
 bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
                                          JS::MutableHandleIdVector properties,
-                                         bool only_enumerable G_GNUC_UNUSED) {
+                                         bool only_enumerable
+                                         [[maybe_unused]]) {
     unsigned n_interfaces;
     GType* interfaces = g_type_interfaces(gtype(), &n_interfaces);
 
@@ -1017,7 +1008,6 @@ bool ObjectPrototype::new_enumerate_impl(JSContext* cx, JS::HandleObject,
     return true;
 }
 
-
 /* Set properties from args to constructor (args[0] is supposed to be
  * a hash) */
 bool ObjectPrototype::props_to_g_parameters(JSContext* context,
@@ -1120,8 +1110,8 @@ void ObjectInstance::remove_wrapped_gobjects_if(
  * Callback called when the #GjsContext is disposed. It just calls
  * handle_context_dispose() on every ObjectInstance.
  */
-void ObjectInstance::context_dispose_notify(
-    void*, GObject* where_the_object_was G_GNUC_UNUSED) {
+void ObjectInstance::context_dispose_notify(void*, GObject* where_the_object_was
+                                            [[maybe_unused]]) {
     ObjectInstance::iterate_wrapped_gobjects(
         std::mem_fn(&ObjectInstance::handle_context_dispose));
 }
diff --git a/gi/object.h b/gi/object.h
index b90b4221..81648ddd 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -69,12 +69,12 @@ class GjsListLink {
     ObjectInstance* m_next;
 
  public:
-    GJS_USE ObjectInstance* prev(void) const { return m_prev; }
-    GJS_USE ObjectInstance* next(void) const { return m_next; }
+    [[nodiscard]] ObjectInstance* prev() const { return m_prev; }
+    [[nodiscard]] ObjectInstance* next() const { return m_next; }
 
     void prepend(ObjectInstance* this_instance, ObjectInstance* head);
     void unlink(void);
-    GJS_USE size_t size(void) const;
+    [[nodiscard]] size_t size() const;
 };
 
 struct AutoGValueVector : public std::vector<GValue> {
@@ -126,7 +126,7 @@ class ObjectBase
 
  private:
     // This is used in debug methods only.
-    GJS_USE const void* jsobj_addr(void) const;
+    [[nodiscard]] const void* jsobj_addr() const;
 
     /* Helper methods */
 
@@ -135,8 +135,8 @@ class ObjectBase
         GIWrapperBase::debug_lifecycle(jsobj_addr(), message);
     }
 
-    GJS_USE bool id_is_never_lazy(jsid name, const GjsAtoms& atoms);
-    GJS_USE bool is_custom_js_class();
+    [[nodiscard]] bool id_is_never_lazy(jsid name, const GjsAtoms& atoms);
+    [[nodiscard]] bool is_custom_js_class();
 
  public:
     void type_query_dynamic_safe(GTypeQuery* query);
@@ -144,10 +144,10 @@ class ObjectBase
     GJS_JSAPI_RETURN_CONVENTION
     static bool typecheck(JSContext* cx, JS::HandleObject obj,
                           GIObjectInfo* expected_info, GType expected_gtype);
-    GJS_USE
-    static bool typecheck(JSContext* cx, JS::HandleObject obj,
-                          GIObjectInfo* expected_info, GType expected_gtype,
-                          GjsTypecheckNoThrow no_throw) {
+    [[nodiscard]] static bool typecheck(JSContext* cx, JS::HandleObject obj,
+                                        GIObjectInfo* expected_info,
+                                        GType expected_gtype,
+                                        GjsTypecheckNoThrow no_throw) {
         return GIWrapperBase::typecheck(cx, obj, expected_info, expected_gtype,
                                         no_throw);
     }
@@ -187,7 +187,7 @@ class ObjectBase
     static bool signals_disconnect(JSContext* cx, unsigned argc, JS::Value* vp);
     GJS_JSAPI_RETURN_CONVENTION
     static bool to_string(JSContext* cx, unsigned argc, JS::Value* vp);
-    GJS_USE const char* to_string_kind(void) const;
+    [[nodiscard]] const char* to_string_kind() const;
     GJS_JSAPI_RETURN_CONVENTION
     static bool init_gobject(JSContext* cx, unsigned argc, JS::Value* vp);
     GJS_JSAPI_RETURN_CONVENTION
@@ -195,8 +195,8 @@ class ObjectBase
 
     /* Quarks */
 
-    GJS_USE static GQuark custom_type_quark(void);
-    GJS_USE static GQuark custom_property_quark(void);
+    [[nodiscard]] static GQuark custom_type_quark();
+    [[nodiscard]] static GQuark custom_property_quark();
 };
 
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1614220
@@ -239,16 +239,14 @@ class ObjectPrototype
     static constexpr InfoType::Tag info_type_tag = InfoType::Object;
 
  public:
-    GJS_USE
-    static ObjectPrototype* for_gtype(GType gtype);
+    [[nodiscard]] static ObjectPrototype* for_gtype(GType gtype);
 
     /* Helper methods */
  private:
     GJS_JSAPI_RETURN_CONVENTION
     bool get_parent_proto(JSContext* cx, JS::MutableHandleObject proto) const;
 
-    GJS_USE
-    bool is_vfunc_unchanged(GIVFuncInfo* info);
+    [[nodiscard]] bool is_vfunc_unchanged(GIVFuncInfo* info);
     static void vfunc_invalidated_notify(void* data, GClosure* closure);
 
     GJS_JSAPI_RETURN_CONVENTION
@@ -346,18 +344,15 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
     // Extra method to get an existing ObjectInstance from qdata
 
  public:
-    GJS_USE
-    static ObjectInstance* for_gobject(GObject* gobj);
+    [[nodiscard]] static ObjectInstance* for_gobject(GObject* gobj);
 
     /* Accessors */
 
  private:
-    GJS_USE
-    bool has_wrapper(void) const { return !!m_wrapper; }
+    [[nodiscard]] bool has_wrapper() const { return !!m_wrapper; }
 
  public:
-    GJS_USE
-    JSObject* wrapper(void) const { return m_wrapper; }
+    [[nodiscard]] JSObject* wrapper() const { return m_wrapper; }
 
     /* Methods to manipulate the JS object wrapper */
 
@@ -365,16 +360,14 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
     void discard_wrapper(void) { m_wrapper.reset(); }
     void switch_to_rooted(JSContext* cx) { m_wrapper.switch_to_rooted(cx); }
     void switch_to_unrooted(JSContext* cx) { m_wrapper.switch_to_unrooted(cx); }
-    GJS_USE
-    bool update_after_gc(void) { return m_wrapper.update_after_gc(); }
-    GJS_USE
-    bool wrapper_is_rooted(void) const { return m_wrapper.rooted(); }
+    [[nodiscard]] bool update_after_gc() { return m_wrapper.update_after_gc(); }
+    [[nodiscard]] bool wrapper_is_rooted() const { return m_wrapper.rooted(); }
     void release_native_object(void);
     void associate_js_gobject(JSContext* cx, JS::HandleObject obj,
                               GObject* gobj);
     void disassociate_js_gobject(void);
     void handle_context_dispose(void);
-    GJS_USE bool weak_pointer_was_finalized(void);
+    [[nodiscard]] bool weak_pointer_was_finalized();
     static void ensure_weak_pointer_callback(JSContext* cx);
     static void update_heap_wrapper_weak_pointers(JSContext* cx,
                                                   JS::Compartment* compartment,
@@ -402,7 +395,7 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
     void unset_object_qdata(void);
     void check_js_object_finalized(void);
     void ensure_uses_toggle_ref(JSContext* cx);
-    GJS_USE bool check_gobject_disposed(const char* for_what) const;
+    [[nodiscard]] bool check_gobject_disposed(const char* for_what) const;
     GJS_JSAPI_RETURN_CONVENTION
     bool signal_match_arguments_from_object(JSContext* cx,
                                             JS::HandleObject props_obj,
@@ -412,8 +405,7 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
                                             JS::MutableHandleFunction func_out);
 
  public:
-    static GObject* copy_ptr(JSContext* G_GNUC_UNUSED, GType G_GNUC_UNUSED,
-                             void* ptr) {
+    static GObject* copy_ptr(JSContext*, GType, void* ptr) {
         return G_OBJECT(g_object_ref(G_OBJECT(ptr)));
     }
 
@@ -425,12 +417,12 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
 
  private:
     static ObjectInstance* wrapped_gobject_list;
-    GJS_USE
-    ObjectInstance* next(void) const { return m_instance_link.next(); }
+    [[nodiscard]] ObjectInstance* next() const {
+        return m_instance_link.next();
+    }
     void link(void);
     void unlink(void);
-    GJS_USE
-    static size_t num_wrapped_gobjects(void) {
+    [[nodiscard]] static size_t num_wrapped_gobjects() {
         return wrapped_gobject_list
                    ? wrapped_gobject_list->m_instance_link.size()
                    : 0;
@@ -442,7 +434,7 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
                                            const Action& action);
 
  public:
-    GJS_USE GjsListLink* get_link(void) { return &m_instance_link; }
+    [[nodiscard]] GjsListLink* get_link() { return &m_instance_link; }
     static void prepare_shutdown(void);
 
     /* JSClass operations */
@@ -493,7 +485,7 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
     GJS_JSAPI_RETURN_CONVENTION
     bool init_impl(JSContext* cx, const JS::CallArgs& args,
                    JS::MutableHandleObject obj);
-    GJS_USE const char* to_string_kind(void) const;
+    [[nodiscard]] const char* to_string_kind() const;
 
     GJS_JSAPI_RETURN_CONVENTION
     bool typecheck_impl(JSContext* cx, GIBaseInfo* expected_info,
diff --git a/gi/param.h b/gi/param.h
index 4ee2df85..44be99d0 100644
--- a/gi/param.h
+++ b/gi/param.h
@@ -44,10 +44,7 @@ GJS_JSAPI_RETURN_CONVENTION
 JSObject*   gjs_param_from_g_param     (JSContext  *context,
                                         GParamSpec *param);
 
-GJS_USE
-bool        gjs_typecheck_param(JSContext       *context,
-                                JS::HandleObject obj,
-                                GType            expected_type,
-                                bool             throw_error);
+[[nodiscard]] bool gjs_typecheck_param(JSContext* cx, JS::HandleObject obj,
+                                       GType expected_type, bool throw_error);
 
 #endif  // GI_PARAM_H_
diff --git a/gi/repo.cpp b/gi/repo.cpp
index af9a7234..18f04568 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -491,7 +491,7 @@ gjs_define_info(JSContext       *context,
                 return false;
             break;
         }
-        /* fall through */
+        [[fallthrough]];
 
     case GI_INFO_TYPE_FLAGS:
         if (!gjs_define_enumeration(context, in_object, (GIEnumInfo*) info))
@@ -566,12 +566,9 @@ gjs_lookup_namespace_object(JSContext  *context,
 
 /* Check if an exception's 'name' property is equal to compare_name. Ignores
  * all errors that might arise. */
-GJS_USE
-static bool
-error_has_name(JSContext       *cx,
-               JS::HandleValue  thrown_value,
-               JSString        *compare_name)
-{
+[[nodiscard]] static bool error_has_name(JSContext* cx,
+                                         JS::HandleValue thrown_value,
+                                         JSString* compare_name) {
     if (!thrown_value.isObject())
         return false;
 
diff --git a/gi/repo.h b/gi/repo.h
index 409f2778..b4f03dac 100644
--- a/gi/repo.h
+++ b/gi/repo.h
@@ -37,8 +37,7 @@ GJS_JSAPI_RETURN_CONVENTION
 bool gjs_define_repo(JSContext              *cx,
                      JS::MutableHandleObject repo);
 
-GJS_USE
-const char* gjs_info_type_name                  (GIInfoType      type);
+[[nodiscard]] const char* gjs_info_type_name(GIInfoType type);
 GJS_JSAPI_RETURN_CONVENTION
 JSObject*   gjs_lookup_private_namespace        (JSContext      *context);
 GJS_JSAPI_RETURN_CONVENTION
@@ -65,9 +64,7 @@ bool gjs_define_info(JSContext       *context,
                      GIBaseInfo      *info,
                      bool            *defined);
 
-GJS_USE
-char*       gjs_hyphen_from_camel               (const char     *camel_name);
-
+[[nodiscard]] char* gjs_hyphen_from_camel(const char* camel_name);
 
 #if GJS_VERBOSE_ENABLE_GI_USAGE
 void _gjs_log_info_usage(GIBaseInfo *info);
diff --git a/gi/toggle.h b/gi/toggle.h
index fa7e01ae..49f61b7f 100644
--- a/gi/toggle.h
+++ b/gi/toggle.h
@@ -34,7 +34,6 @@
 #include <glib-object.h>
 #include <glib.h>
 
-#include "gjs/macros.h"
 #include "util/log.h"
 
 /* Thread-safe queue for enqueueing toggle-up or toggle-down events on GObjects
@@ -69,16 +68,14 @@ private:
         gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "ToggleQueue %s %p", did, what);
     }
 
-    GJS_USE
-    std::deque<Item>::iterator find_operation_locked(const GObject  *gobj,
-                                                     Direction direction);
+    [[nodiscard]] std::deque<Item>::iterator find_operation_locked(
+        const GObject* gobj, Direction direction);
 
-    GJS_USE
-    std::deque<Item>::const_iterator find_operation_locked(const GObject *gobj,
-                                                           Direction direction) const;
+    [[nodiscard]] std::deque<Item>::const_iterator find_operation_locked(
+        const GObject* gobj, Direction direction) const;
 
-    GJS_USE
-    bool find_and_erase_operation_locked(const GObject *gobj, Direction direction);
+    [[nodiscard]] bool find_and_erase_operation_locked(const GObject* gobj,
+                                                       Direction direction);
 
     static gboolean idle_handle_toggle(void *data);
     static void idle_destroy_notify(void *data);
@@ -86,8 +83,7 @@ private:
  public:
     /* These two functions return a pair DOWN, UP signifying whether toggles
      * are / were queued. is_queued() just checks and does not modify. */
-    GJS_USE
-    std::pair<bool, bool> is_queued(GObject *gobj) const;
+    [[nodiscard]] std::pair<bool, bool> is_queued(GObject* gobj) const;
     /* Cancels pending toggles and returns whether any were queued. */
     std::pair<bool, bool> cancel(GObject *gobj);
 
@@ -106,9 +102,7 @@ private:
                  Direction direction,
                  Handler   handler);
 
-    GJS_USE
-    static ToggleQueue&
-    get_default(void) {
+    [[nodiscard]] static ToggleQueue& get_default() {
         static ToggleQueue the_singleton;
         return the_singleton;
     }
diff --git a/gi/union.h b/gi/union.h
index e72dd8ef..7add9b31 100644
--- a/gi/union.h
+++ b/gi/union.h
@@ -58,7 +58,7 @@ class UnionBase
     static const JSClassOps class_ops;
     static const JSClass klass;
 
-    GJS_USE static const char* to_string_kind(void) { return "union"; }
+    [[nodiscard]] static const char* to_string_kind(void) { return "union"; }
 };
 
 class UnionPrototype : public GIWrapperPrototype<UnionBase, UnionPrototype,
@@ -77,7 +77,7 @@ class UnionPrototype : public GIWrapperPrototype<UnionBase, UnionPrototype,
                       const char* prop_name, bool* resolved);
 
     // Overrides GIWrapperPrototype::constructor_nargs().
-    GJS_USE unsigned constructor_nargs(void) const { return 0; }
+    [[nodiscard]] unsigned constructor_nargs(void) const { return 0; }
 };
 
 class UnionInstance
diff --git a/gi/value.cpp b/gi/value.cpp
index a81f4265..ba82c26d 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -73,10 +73,8 @@ static bool gjs_value_from_g_value_internal(JSContext             *context,
  * only works for signals on introspected GObjects, not signals on GJS-defined
  * GObjects nor standalone closures. The return value must be unreffed.
  */
-GJS_USE
-static GISignalInfo *
-get_signal_info_if_available(GSignalQuery *signal_query)
-{
+[[nodiscard]] static GISignalInfo* get_signal_info_if_available(
+    GSignalQuery* signal_query) {
     GIBaseInfo *obj;
     GIInfoType info_type;
     GISignalInfo *signal_info = NULL;
@@ -761,11 +759,7 @@ gjs_value_to_g_value_no_copy(JSContext      *context,
     return gjs_value_to_g_value_internal(context, value, gvalue, true);
 }
 
-GJS_USE
-static JS::Value
-convert_int_to_enum (GType  gtype,
-                     int    v)
-{
+[[nodiscard]] static JS::Value convert_int_to_enum(GType gtype, int v) {
     double v_double;
 
     if (v > 0 && v < G_MAXINT) {
diff --git a/gi/value.h b/gi/value.h
index 4c39184c..d1d0e7a6 100644
--- a/gi/value.h
+++ b/gi/value.h
@@ -46,12 +46,12 @@ bool gjs_value_from_g_value(JSContext             *context,
                             JS::MutableHandleValue value_p,
                             const GValue          *gvalue);
 
-GJS_USE
-GClosure* gjs_closure_new_marshaled(JSContext* cx, JSFunction* callable,
-                                    const char* description);
-GJS_USE
-GClosure* gjs_closure_new_for_signal(JSContext* cx, JSFunction* callable,
-                                     const char* description,
-                                     unsigned signal_id);
+[[nodiscard]] GClosure* gjs_closure_new_marshaled(JSContext* cx,
+                                                  JSFunction* callable,
+                                                  const char* description);
+[[nodiscard]] GClosure* gjs_closure_new_for_signal(JSContext* cx,
+                                                   JSFunction* callable,
+                                                   const char* description,
+                                                   unsigned signal_id);
 
 #endif  // GI_VALUE_H_
diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h
index 5a21cca7..912ab36e 100644
--- a/gi/wrapperutils.h
+++ b/gi/wrapperutils.h
@@ -174,8 +174,7 @@ class GIWrapperBase {
      * Gets the Base belonging to a particular JS object wrapper. Checks that
      * the wrapper object has the right JSClass (Base::klass) and returns null
      * if not. */
-    GJS_USE
-    static Base* for_js(JSContext* cx, JS::HandleObject wrapper) {
+    [[nodiscard]] static Base* for_js(JSContext* cx, JS::HandleObject wrapper) {
         return static_cast<Base*>(
             JS_GetInstancePrivate(cx, wrapper, &Base::klass, nullptr));
     }
@@ -185,8 +184,8 @@ class GIWrapperBase {
      *
      * Checks if the given wrapper object has the right JSClass (Base::klass).
      */
-    GJS_USE
-    static bool check_jsclass(JSContext* cx, JS::HandleObject wrapper) {
+    [[nodiscard]] static bool check_jsclass(JSContext* cx,
+                                            JS::HandleObject wrapper) {
         return !!for_js(cx, wrapper);
     }
 
@@ -221,8 +220,7 @@ class GIWrapperBase {
      * and cannot trigger a GC, so it's safe to use from finalize() and trace().
      * (It can return null if no private data has been set yet on the wrapper.)
      */
-    GJS_USE
-    static Base* for_js_nocheck(JSObject* wrapper) {
+    [[nodiscard]] static Base* for_js_nocheck(JSObject* wrapper) {
         return static_cast<Base*>(JS_GetPrivate(wrapper));
     }
 
@@ -236,7 +234,7 @@ class GIWrapperBase {
      * Returns whether this Base is actually a Prototype (true) or an Instance
      * (false).
      */
-    GJS_USE bool is_prototype(void) const { return !m_proto; }
+    [[nodiscard]] bool is_prototype() const { return !m_proto; }
 
     /*
      * GIWrapperBase::to_prototype:
@@ -246,23 +244,19 @@ class GIWrapperBase {
      * don't want to assert, then either check beforehand with is_prototype(),
      * or use get_prototype().
      */
-    GJS_USE
-    Prototype* to_prototype(void) {
+    [[nodiscard]] Prototype* to_prototype() {
         g_assert(is_prototype());
         return reinterpret_cast<Prototype*>(this);
     }
-    GJS_USE
-    const Prototype* to_prototype(void) const {
+    [[nodiscard]] const Prototype* to_prototype() const {
         g_assert(is_prototype());
         return reinterpret_cast<const Prototype*>(this);
     }
-    GJS_USE
-    Instance* to_instance(void) {
+    [[nodiscard]] Instance* to_instance() {
         g_assert(!is_prototype());
         return reinterpret_cast<Instance*>(this);
     }
-    GJS_USE
-    const Instance* to_instance(void) const {
+    [[nodiscard]] const Instance* to_instance() const {
         g_assert(!is_prototype());
         return reinterpret_cast<const Instance*>(this);
     }
@@ -275,12 +269,10 @@ class GIWrapperBase {
      * Instance, it returns you the Prototype belonging to the corresponding JS
      * prototype.
      */
-    GJS_USE
-    Prototype* get_prototype(void) {
+    [[nodiscard]] Prototype* get_prototype() {
         return is_prototype() ? to_prototype() : m_proto;
     }
-    GJS_USE
-    const Prototype* get_prototype(void) const {
+    [[nodiscard]] const Prototype* get_prototype() const {
         return is_prototype() ? to_prototype() : m_proto;
     }
 
@@ -288,25 +280,22 @@ class GIWrapperBase {
     // should be able to access the GIFooInfo and the GType, but for space
     // reasons we store them only on Prototype.
 
-    GJS_USE GIBaseInfo* info(void) const { return get_prototype()->info(); }
-    GJS_USE GType gtype(void) const { return get_prototype()->gtype(); }
+    [[nodiscard]] GIBaseInfo* info() const { return get_prototype()->info(); }
+    [[nodiscard]] GType gtype() const { return get_prototype()->gtype(); }
 
     // The next three methods are operations derived from the GIFooInfo.
 
-    GJS_USE const char* type_name(void) const { return g_type_name(gtype()); }
-    GJS_USE
-    const char* ns(void) const {
+    [[nodiscard]] const char* type_name() const { return g_type_name(gtype()); }
+    [[nodiscard]] const char* ns() const {
         return info() ? g_base_info_get_namespace(info()) : "";
     }
-    GJS_USE
-    const char* name(void) const {
+    [[nodiscard]] const char* name() const {
         return info() ? g_base_info_get_name(info()) : type_name();
     }
 
  private:
     // Accessor for Instance member. Used only in debug methods and toString().
-    GJS_USE
-    const void* ptr_addr(void) const {
+    [[nodiscard]] const void* ptr_addr() const {
         return is_prototype() ? nullptr : to_instance()->ptr();
     }
 
@@ -393,8 +382,7 @@ class GIWrapperBase {
      * Base::proto_methods. You should add any identifiers in the override that
      * you have added to the prototype object.
      */
-    GJS_USE
-    static bool id_is_never_lazy(jsid id, const GjsAtoms& atoms) {
+    [[nodiscard]] static bool id_is_never_lazy(jsid id, const GjsAtoms& atoms) {
         // toString() is always defined somewhere on the prototype chain, so it
         // is never a lazy property.
         return id == atoms.to_string();
@@ -706,10 +694,10 @@ class GIWrapperBase {
 
         return false;
     }
-    GJS_USE
-    static bool typecheck(JSContext* cx, JS::HandleObject object,
-                          GIBaseInfo* expected_info, GType expected_gtype,
-                          GjsTypecheckNoThrow) {
+    [[nodiscard]] static bool typecheck(JSContext* cx, JS::HandleObject object,
+                                        GIBaseInfo* expected_info,
+                                        GType expected_gtype,
+                                        GjsTypecheckNoThrow) {
         Base* priv = Base::for_js(cx, object);
         if (!priv || priv->is_prototype())
             return false;
@@ -795,7 +783,7 @@ class GIWrapperPrototype : public Base {
      *
      * Override this if the type's constructor takes other than 1 argument.
      */
-    GJS_USE unsigned constructor_nargs(void) const { return 1; }
+    [[nodiscard]] unsigned constructor_nargs() const { return 1; }
 
     /*
      * GIWrapperPrototype::define_jsclass:
@@ -982,7 +970,8 @@ class GIWrapperPrototype : public Base {
      * Like Base::for_js(), but asserts that the returned private struct is a
      * Prototype and not an Instance.
      */
-    GJS_USE static Prototype* for_js(JSContext* cx, JS::HandleObject wrapper) {
+    [[nodiscard]] static Prototype* for_js(JSContext* cx,
+                                           JS::HandleObject wrapper) {
         return Base::for_js(cx, wrapper)->to_prototype();
     }
 
@@ -992,9 +981,8 @@ class GIWrapperPrototype : public Base {
      * Gets the Prototype private data from to @wrapper.prototype. Cannot return
      * null, and asserts so.
      */
-    GJS_USE
-    static Prototype* for_js_prototype(JSContext* cx,
-                                       JS::HandleObject wrapper) {
+    [[nodiscard]] static Prototype* for_js_prototype(JSContext* cx,
+                                                     JS::HandleObject wrapper) {
         JS::RootedObject proto(cx);
         JS_GetPrototype(cx, wrapper, &proto);
         Base* retval = Base::for_js(cx, proto);
@@ -1004,8 +992,8 @@ class GIWrapperPrototype : public Base {
 
     // Accessors
 
-    GJS_USE Info* info(void) const { return m_info; }
-    GJS_USE GType gtype(void) const { return m_gtype; }
+    [[nodiscard]] Info* info() const { return m_info; }
+    [[nodiscard]] GType gtype() const { return m_gtype; }
 
     // Helper methods
 
@@ -1061,8 +1049,8 @@ class GIWrapperInstance : public Base {
      * Creates a GIWrapperInstance and associates it with @obj as its private
      * data. This is called by the JS constructor. Uses the slice allocator.
      */
-    GJS_USE
-    static Instance* new_for_js_object(JSContext* cx, JS::HandleObject obj) {
+    [[nodiscard]] static Instance* new_for_js_object(JSContext* cx,
+                                                     JS::HandleObject obj) {
         g_assert(!JS_GetPrivate(obj));
         auto* priv = g_slice_new0(Instance);
         new (priv) Instance(cx, obj);
@@ -1083,19 +1071,20 @@ class GIWrapperInstance : public Base {
      * Like Base::for_js(), but asserts that the returned private struct is an
      * Instance and not a Prototype.
      */
-    GJS_USE static Instance* for_js(JSContext* cx, JS::HandleObject wrapper) {
+    [[nodiscard]] static Instance* for_js(JSContext* cx,
+                                          JS::HandleObject wrapper) {
         return Base::for_js(cx, wrapper)->to_instance();
     }
 
     // Accessors
 
-    GJS_USE Wrapped* ptr(void) const { return m_ptr; }
+    [[nodiscard]] Wrapped* ptr() const { return m_ptr; }
     /*
      * GIWrapperInstance::raw_ptr:
      *
      * Like ptr(), but returns a byte pointer for use in byte arithmetic.
      */
-    GJS_USE uint8_t* raw_ptr(void) const {
+    [[nodiscard]] uint8_t* raw_ptr() const {
         return reinterpret_cast<uint8_t*>(m_ptr);
     }
 
@@ -1122,9 +1111,8 @@ class GIWrapperInstance : public Base {
      * It's possible to override typecheck_impl() if you need an extra step in
      * the check.
      */
-    GJS_USE
-    bool typecheck_impl(JSContext*, GIBaseInfo* expected_info,
-                        GType expected_gtype) const {
+    [[nodiscard]] bool typecheck_impl(JSContext*, GIBaseInfo* expected_info,
+                                      GType expected_gtype) const {
         if (expected_gtype != G_TYPE_NONE)
             return g_type_is_a(Base::gtype(), expected_gtype);
         else if (expected_info)
diff --git a/gjs/atoms.h b/gjs/atoms.h
index eb53a785..7e94d651 100644
--- a/gjs/atoms.h
+++ b/gjs/atoms.h
@@ -98,11 +98,11 @@ struct GjsAtom {
     /* It's OK to return JS::HandleId here, to avoid an extra root, with the
      * caveat that you should not use this value after the GjsContext has been
      * destroyed.*/
-    GJS_USE JS::HandleId operator()() const {
+    [[nodiscard]] JS::HandleId operator()() const {
         return JS::HandleId::fromMarkedLocation(&m_jsid.get());
     }
 
-    GJS_USE JS::Heap<jsid>* id() { return &m_jsid; }
+    [[nodiscard]] JS::Heap<jsid>* id() { return &m_jsid; }
 
  protected:
     JS::Heap<jsid> m_jsid;
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 10d463d7..2706d11f 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -54,7 +54,7 @@ static void gfree_arraybuffer_contents(void* contents, void*) {
     g_free(contents);
 }
 
-static void bytes_unref_arraybuffer(void* contents G_GNUC_UNUSED,
+static void bytes_unref_arraybuffer(void* contents [[maybe_unused]],
                                     void* user_data) {
     auto* gbytes = static_cast<GBytes*>(user_data);
     g_bytes_unref(gbytes);
diff --git a/gjs/byteArray.h b/gjs/byteArray.h
index e0c01aae..fccfb86b 100644
--- a/gjs/byteArray.h
+++ b/gjs/byteArray.h
@@ -45,10 +45,7 @@ GJS_JSAPI_RETURN_CONVENTION
 JSObject *    gjs_byte_array_from_byte_array (JSContext  *context,
                                               GByteArray *array);
 
-GJS_USE
-GByteArray* gjs_byte_array_get_byte_array(JSObject* obj);
-
-GJS_USE
-GBytes* gjs_byte_array_get_bytes(JSObject* obj);
+[[nodiscard]] GByteArray* gjs_byte_array_get_byte_array(JSObject* obj);
+[[nodiscard]] GBytes* gjs_byte_array_get_bytes(JSObject* obj);
 
 #endif  // GJS_BYTEARRAY_H_
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 9e335594..ad571e0e 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -69,11 +69,7 @@ static GOptionEntry entries[] = {
 };
 // clang-format on
 
-GJS_USE
-static char **
-strndupv(int           n,
-         char * const *strv)
-{
+[[nodiscard]] static char** strndupv(int n, char* const* strv) {
     int ix;
     if (n == 0)
         return NULL;
@@ -84,11 +80,7 @@ strndupv(int           n,
     return retval;
 }
 
-GJS_USE
-static char **
-strcatv(char **strv1,
-        char **strv2)
-{
+[[nodiscard]] static char** strcatv(char** strv1, char** strv2) {
     if (strv1 == NULL && strv2 == NULL)
         return NULL;
     if (strv1 == NULL)
@@ -110,9 +102,8 @@ strcatv(char **strv1,
     return retval;
 }
 
-static gboolean parse_profile_arg(const char* option_name G_GNUC_UNUSED,
-                                  const char* value, void*,
-                                  GError** error_out G_GNUC_UNUSED) {
+static gboolean parse_profile_arg(const char* option_name [[maybe_unused]],
+                                  const char* value, void*, GError**) {
     enable_profiler = true;
     g_free(profile_output_path);
     profile_output_path = g_strdup(value);
diff --git a/gjs/context-private.h b/gjs/context-private.h
index 3cf6066d..ef8f28b6 100644
--- a/gjs/context-private.h
+++ b/gjs/context-private.h
@@ -171,45 +171,48 @@ class GjsContextPrivate : public JS::JobQueue {
 
  public:
     /* Retrieving a GjsContextPrivate from JSContext or GjsContext */
-    GJS_USE GJS_ALWAYS_INLINE static GjsContextPrivate* from_cx(JSContext* cx) {
+    [[nodiscard]] static GjsContextPrivate* from_cx(JSContext* cx) {
         return static_cast<GjsContextPrivate*>(JS_GetContextPrivate(cx));
     }
-    GJS_USE static GjsContextPrivate* from_object(GObject* public_context);
-    GJS_USE static GjsContextPrivate* from_object(GjsContext* public_context);
-    GJS_USE static GjsContextPrivate* from_current_context();
+    [[nodiscard]] static GjsContextPrivate* from_object(
+        GObject* public_context);
+    [[nodiscard]] static GjsContextPrivate* from_object(
+        GjsContext* public_context);
+    [[nodiscard]] static GjsContextPrivate* from_current_context();
 
     GjsContextPrivate(JSContext* cx, GjsContext* public_context);
     ~GjsContextPrivate(void);
 
     /* Accessors */
-    GJS_USE GjsContext* public_context(void) const { return m_public_context; }
-    GJS_USE JSContext* context(void) const { return m_cx; }
-    GJS_USE JSObject* global(void) const { return m_global.get(); }
-    GJS_USE GjsProfiler* profiler(void) const { return m_profiler; }
-    GJS_USE const GjsAtoms& atoms(void) const { return *m_atoms; }
-    GJS_USE bool destroying(void) const { return m_destroying; }
-    GJS_USE bool sweeping(void) const { return m_in_gc_sweep; }
-    GJS_USE const char* program_name(void) const { return m_program_name; }
+    [[nodiscard]] GjsContext* public_context() const {
+        return m_public_context;
+    }
+    [[nodiscard]] JSContext* context() const { return m_cx; }
+    [[nodiscard]] JSObject* global() const { return m_global.get(); }
+    [[nodiscard]] GjsProfiler* profiler() const { return m_profiler; }
+    [[nodiscard]] const GjsAtoms& atoms() const { return *m_atoms; }
+    [[nodiscard]] bool destroying() const { return m_destroying; }
+    [[nodiscard]] bool sweeping() const { return m_in_gc_sweep; }
+    [[nodiscard]] const char* program_name() const { return m_program_name; }
     void set_program_name(char* value) { m_program_name = value; }
     void set_search_path(char** value) { m_search_path = value; }
     void set_should_profile(bool value) { m_should_profile = value; }
     void set_should_listen_sigusr2(bool value) {
         m_should_listen_sigusr2 = value;
     }
-    GJS_USE bool is_owner_thread(void) const {
+    [[nodiscard]] bool is_owner_thread() const {
         return m_owner_thread == g_thread_self();
     }
-    GJS_USE JS::WeakCache<FundamentalTable>& fundamental_table(void) {
+    [[nodiscard]] JS::WeakCache<FundamentalTable>& fundamental_table() {
         return *m_fundamental_table;
     }
-    GJS_USE JS::WeakCache<GTypeTable>& gtype_table(void) {
+    [[nodiscard]] JS::WeakCache<GTypeTable>& gtype_table() {
         return *m_gtype_table;
     }
-    GJS_USE ObjectInitList& object_init_list(void) {
+    [[nodiscard]] ObjectInitList& object_init_list() {
         return m_object_init_list;
     }
-    GJS_USE
-    static const GjsAtoms& atoms(JSContext* cx) {
+    [[nodiscard]] static const GjsAtoms& atoms(JSContext* cx) {
         return *(from_cx(cx)->m_atoms);
     }
 
@@ -229,7 +232,7 @@ class GjsContextPrivate : public JS::JobQueue {
     void schedule_gc_if_needed(void);
 
     void exit(uint8_t exit_code);
-    GJS_USE bool should_exit(uint8_t* exit_code_p) const;
+    [[nodiscard]] bool should_exit(uint8_t* exit_code_p) const;
 
     // Implementations of JS::JobQueue virtual functions
     GJS_JSAPI_RETURN_CONVENTION
@@ -240,7 +243,7 @@ class GjsContextPrivate : public JS::JobQueue {
                            JS::HandleObject allocation_site,
                            JS::HandleObject incumbent_global) override;
     void runJobs(JSContext* cx) override;
-    GJS_USE bool empty(void) const override { return m_job_queue.empty(); };
+    [[nodiscard]] bool empty() const override { return m_job_queue.empty(); }
     js::UniquePtr<JS::JobQueue::SavedJobQueue> saveJobQueue(
         JSContext* cx) override;
 
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 1f7afb2e..747f6f38 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -184,7 +184,7 @@ static gboolean dump_heap_idle(void*) {
     return false;
 }
 
-static void dump_heap_signal_handler(int signum G_GNUC_UNUSED) {
+static void dump_heap_signal_handler(int signum [[maybe_unused]]) {
     if (dump_heap_idle_id == 0)
         dump_heap_idle_id = g_idle_add_full(G_PRIORITY_HIGH_IDLE,
                                             dump_heap_idle, nullptr, nullptr);
@@ -693,9 +693,9 @@ JSObject* GjsContextPrivate::getIncumbentGlobal(JSContext* cx) {
 
 /* See engine.cpp and JS::SetEnqueuePromiseJobCallback(). */
 bool GjsContextPrivate::enqueuePromiseJob(
-    JSContext* cx, JS::HandleObject promise G_GNUC_UNUSED, JS::HandleObject job,
-    JS::HandleObject allocation_site G_GNUC_UNUSED,
-    JS::HandleObject incumbent_global G_GNUC_UNUSED) {
+    JSContext* cx, JS::HandleObject promise [[maybe_unused]],
+    JS::HandleObject job, JS::HandleObject allocation_site [[maybe_unused]],
+    JS::HandleObject incumbent_global [[maybe_unused]]) {
     g_assert(cx == m_cx);
     g_assert(from_cx(cx) == this);
 
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index 09d1c51e..ab5b6ebf 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -76,31 +76,22 @@ enum {
 
 static GParamSpec *properties[PROP_N] = { NULL, };
 
-GJS_USE
-static char *
-get_file_identifier(GFile *source_file) {
+[[nodiscard]] static char* get_file_identifier(GFile* source_file) {
     char *path = g_file_get_path(source_file);
     if (!path)
         path = g_file_get_uri(source_file);
     return path;
 }
 
-GJS_USE
-static bool
-write_source_file_header(GOutputStream *stream,
-                         GFile         *source_file,
-                         GError       **error)
-{
+[[nodiscard]] static bool write_source_file_header(GOutputStream* stream,
+                                                   GFile* source_file,
+                                                   GError** error) {
     GjsAutoChar path = get_file_identifier(source_file);
     return g_output_stream_printf(stream, NULL, NULL, error, "SF:%s\n", path.get());
 }
 
-GJS_USE
-static bool
-copy_source_file_to_coverage_output(GFile   *source_file,
-                                    GFile   *destination_file,
-                                    GError **error)
-{
+[[nodiscard]] static bool copy_source_file_to_coverage_output(
+    GFile* source_file, GFile* destination_file, GError** error) {
     /* We need to recursively make the directory we
      * want to copy to, as g_file_copy doesn't do that */
     GjsAutoUnref<GFile> destination_dir = g_file_get_parent(destination_file);
@@ -118,10 +109,7 @@ copy_source_file_to_coverage_output(GFile   *source_file,
  * the string with the URI scheme stripped or NULL
  * if the path was not a valid URI
  */
-GJS_USE
-static char *
-strip_uri_scheme(const char *potential_uri)
-{
+[[nodiscard]] static char* strip_uri_scheme(const char* potential_uri) {
     char *uri_header = g_uri_parse_scheme(potential_uri);
 
     if (uri_header) {
@@ -154,11 +142,8 @@ strip_uri_scheme(const char *potential_uri)
  * automatically return the full URI path with
  * the URI scheme and leading slash stripped out.
  */
-GJS_USE
-static char *
-find_diverging_child_components(GFile *child,
-                                GFile *parent)
-{
+[[nodiscard]] static char* find_diverging_child_components(GFile* child,
+                                                           GFile* parent) {
     g_object_ref(parent);
     GFile *ancestor = parent;
     while (ancestor != NULL) {
@@ -187,10 +172,8 @@ find_diverging_child_components(GFile *child,
     return stripped_uri;
 }
 
-GJS_USE
-static bool
-filename_has_coverage_prefixes(GjsCoverage *self, const char *filename)
-{
+[[nodiscard]] static bool filename_has_coverage_prefixes(GjsCoverage* self,
+                                                         const char* filename) {
     auto priv = static_cast<GjsCoveragePrivate *>(gjs_coverage_get_instance_private(self));
 
     for (const char * const *prefix = priv->prefixes; *prefix; prefix++) {
@@ -208,12 +191,8 @@ write_line(GOutputStream *out,
     return g_output_stream_printf(out, nullptr, nullptr, error, "%s\n", line);
 }
 
-GJS_USE
-static GjsAutoUnref<GFile>
-write_statistics_internal(GjsCoverage *coverage,
-                          JSContext   *cx,
-                          GError     **error)
-{
+[[nodiscard]] static GjsAutoUnref<GFile> write_statistics_internal(
+    GjsCoverage* coverage, JSContext* cx, GError** error) {
     GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
 
     /* Create output directory if it doesn't exist */
diff --git a/gjs/engine.cpp b/gjs/engine.cpp
index bb842e30..f23c47d4 100644
--- a/gjs/engine.cpp
+++ b/gjs/engine.cpp
@@ -147,7 +147,7 @@ bool gjs_load_internal_source(JSContext* cx, const char* filename, char** src,
 
 class GjsSourceHook : public js::SourceHook {
     bool load(JSContext* cx, const char* filename,
-              char16_t** two_byte_source G_GNUC_UNUSED, char** utf8_source,
+              char16_t** two_byte_source [[maybe_unused]], char** utf8_source,
               size_t* length) {
         // caller owns the source, per documentation of SourceHook
         return gjs_load_internal_source(cx, filename, utf8_source, length);
diff --git a/gjs/global.cpp b/gjs/global.cpp
index aaf6a7df..850df908 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -82,18 +82,15 @@ class GjsBaseGlobal {
     }
 
  protected:
-    GJS_USE
-    static JSObject* create(JSContext* cx, const JSClass* clasp) {
+    [[nodiscard]] static JSObject* create(JSContext* cx, const JSClass* clasp) {
         JS::RealmCreationOptions creation;
         creation.setNewCompartmentAndZone();
 
         return base(cx, clasp, creation);
     }
 
-    GJS_USE
-    static JSObject* create_with_compartment(JSContext* cx,
-                                             JS::HandleObject existing,
-                                             const JSClass* clasp) {
+    [[nodiscard]] static JSObject* create_with_compartment(
+        JSContext* cx, JS::HandleObject existing, const JSClass* clasp) {
         JS::RealmCreationOptions creation;
         creation.setExistingCompartment(existing);
 
@@ -180,14 +177,12 @@ class GjsGlobal : GjsBaseGlobal {
         JS_FS_END};
 
  public:
-    GJS_USE
-    static JSObject* create(JSContext* cx) {
+    [[nodiscard]] static JSObject* create(JSContext* cx) {
         return GjsBaseGlobal::create(cx, &klass);
     }
 
-    GJS_USE
-    static JSObject* create_with_compartment(JSContext* cx,
-                                             JS::HandleObject cmp_global) {
+    [[nodiscard]] static JSObject* create_with_compartment(
+        JSContext* cx, JS::HandleObject cmp_global) {
         return GjsBaseGlobal::create_with_compartment(cx, cmp_global, &klass);
     }
 
@@ -241,14 +236,12 @@ class GjsDebuggerGlobal : GjsBaseGlobal {
         JS_FN("loadNative", &load_native_module, 1, 0), JS_FS_END};
 
  public:
-    GJS_USE
-    static JSObject* create(JSContext* cx) {
+    [[nodiscard]] static JSObject* create(JSContext* cx) {
         return GjsBaseGlobal::create(cx, &klass);
     }
 
-    GJS_USE
-    static JSObject* create_with_compartment(JSContext* cx,
-                                             JS::HandleObject cmp_global) {
+    [[nodiscard]] static JSObject* create_with_compartment(
+        JSContext* cx, JS::HandleObject cmp_global) {
         return GjsBaseGlobal::create_with_compartment(cx, cmp_global, &klass);
     }
 
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 58192d97..a013315a 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -616,7 +616,7 @@ static bool do_import(JSContext* context, JS::HandleObject obj, Importer* priv,
 GJS_JSAPI_RETURN_CONVENTION
 static bool importer_new_enumerate(JSContext* context, JS::HandleObject object,
                                    JS::MutableHandleIdVector properties,
-                                   bool enumerable_only G_GNUC_UNUSED) {
+                                   bool enumerable_only [[maybe_unused]]) {
     Importer *priv;
     guint32 search_path_len;
     guint32 i;
@@ -853,8 +853,7 @@ importer_new(JSContext *context,
     return importer;
 }
 
-GJS_USE
-static const std::vector<std::string>& gjs_get_search_path(void) {
+[[nodiscard]] static const std::vector<std::string>& gjs_get_search_path() {
     static std::vector<std::string> gjs_search_path;
     static bool search_path_initialized = false;
 
diff --git a/gjs/jsapi-class.h b/gjs/jsapi-class.h
index 1957ed68..dfdde4e8 100644
--- a/gjs/jsapi-class.h
+++ b/gjs/jsapi-class.h
@@ -44,11 +44,9 @@ bool gjs_init_class_dynamic(
     JSFunctionSpec* fs, JSPropertySpec* static_ps, JSFunctionSpec* static_fs,
     JS::MutableHandleObject prototype, JS::MutableHandleObject constructor);
 
-GJS_USE
-bool gjs_typecheck_instance(JSContext       *cx,
-                            JS::HandleObject obj,
-                            const JSClass   *static_clasp,
-                            bool             throw_error);
+[[nodiscard]] bool gjs_typecheck_instance(JSContext* cx, JS::HandleObject obj,
+                                          const JSClass* static_clasp,
+                                          bool throw_error);
 
 GJS_JSAPI_RETURN_CONVENTION
 JSObject *gjs_construct_object_dynamic(JSContext                  *cx,
@@ -79,16 +77,16 @@ bool gjs_define_property_dynamic(JSContext       *cx,
  *                              do_base_typecheck and priv_from_js
  */
 #define GJS_DEFINE_PRIV_FROM_JS(type, klass)                                   \
-    GJS_ALWAYS_INLINE GJS_USE G_GNUC_UNUSED static inline bool                 \
+    GJS_ALWAYS_INLINE [[nodiscard]] [[maybe_unused]] static inline bool        \
     do_base_typecheck(JSContext* cx, JS::HandleObject obj, bool throw_error) { \
         return gjs_typecheck_instance(cx, obj, &klass, throw_error);           \
     }                                                                          \
-    GJS_ALWAYS_INLINE GJS_USE static inline type* priv_from_js(                \
+    GJS_ALWAYS_INLINE [[nodiscard]] static inline type* priv_from_js(          \
         JSContext* cx, JS::HandleObject obj) {                                 \
         return static_cast<type*>(                                             \
             JS_GetInstancePrivate(cx, obj, &klass, nullptr));                  \
     }                                                                          \
-    G_GNUC_UNUSED GJS_USE static bool priv_from_js_with_typecheck(             \
+    [[nodiscard]] [[maybe_unused]] static bool priv_from_js_with_typecheck(    \
         JSContext* cx, JS::HandleObject obj, type** out) {                     \
         if (!do_base_typecheck(cx, obj, false))                                \
             return false;                                                      \
@@ -182,22 +180,20 @@ _GJS_DEFINE_PROTO_FULL(tn, cn, parent_cn, nullptr, G_TYPE_NONE, flags)
         JSCLASS_HAS_PRIVATE | jsclass_flags,                                \
         &gjs_##cname##_class_ops                                            \
     };                                                                      \
-    _GJS_DEFINE_GET_PROTO(cname)                                            \
-    _GJS_DEFINE_DEFINE_PROTO(cname, parent_cname, ctor, gtype)
+    [[maybe_unused]] [[nodiscard]] _GJS_DEFINE_GET_PROTO(cname)                                            \
+    [[maybe_unused]] GJS_JSAPI_RETURN_CONVENTION _GJS_DEFINE_DEFINE_PROTO(cname, parent_cname, ctor, gtype)
 // clang-format on
 
-#define GJS_DEFINE_PROTO_FUNCS_WITH_PARENT(cname, parent_cname)  \
-G_GNUC_UNUSED static                                             \
-_GJS_DEFINE_GET_PROTO(cname)                                     \
-G_GNUC_UNUSED static                                             \
-_GJS_DEFINE_DEFINE_PROTO(cname, parent_cname,                    \
-                         gjs_##cname##_constructor, G_TYPE_NONE)
+#define GJS_DEFINE_PROTO_FUNCS_WITH_PARENT(cname, parent_cname)                   \
+    [[maybe_unused]] [[nodiscard]] static _GJS_DEFINE_GET_PROTO(cname);           \
+    [[maybe_unused]] GJS_JSAPI_RETURN_CONVENTION static _GJS_DEFINE_DEFINE_PROTO( \
+        cname, parent_cname, gjs_##cname##_constructor, G_TYPE_NONE);
 
 #define GJS_DEFINE_PROTO_FUNCS(cname)  \
 GJS_DEFINE_PROTO_FUNCS_WITH_PARENT(cname, no_parent)
 
 #define _GJS_DEFINE_GET_PROTO(cname)                                           \
-    GJS_USE JSObject* gjs_##cname##_get_proto(JSContext* cx) {                 \
+    JSObject* gjs_##cname##_get_proto(JSContext* cx) {                         \
         JSObject* global = JS::CurrentGlobalOrNull(cx);                        \
         g_assert(global);                                                      \
                                                                                \
@@ -214,7 +210,6 @@ GJS_DEFINE_PROTO_FUNCS_WITH_PARENT(cname, no_parent)
     }
 
 #define _GJS_DEFINE_DEFINE_PROTO(cname, parent_cname, ctor, type)              \
-    GJS_JSAPI_RETURN_CONVENTION                                                \
     bool gjs_##cname##_define_proto(JSContext* cx, JS::HandleObject module,    \
                                     JS::MutableHandleObject proto) {           \
         /* If we've been here more than once, we already have the proto */     \
@@ -293,9 +288,9 @@ GJS_DEFINE_PROTO_FUNCS_WITH_PARENT(cname, no_parent)
  * Declare variables necessary for the constructor; should
  * be at the very top.
  */
-#define GJS_NATIVE_CONSTRUCTOR_VARIABLES(name)                      \
-    JS::RootedObject object(context);                               \
-    JS::CallArgs argv G_GNUC_UNUSED = JS::CallArgsFromVp(argc, vp);
+#define GJS_NATIVE_CONSTRUCTOR_VARIABLES(name) \
+    JS::RootedObject object(context);          \
+    [[maybe_unused]] JS::CallArgs argv = JS::CallArgsFromVp(argc, vp);
 
 /**
  * GJS_NATIVE_CONSTRUCTOR_PRELUDE:
@@ -334,8 +329,8 @@ GJS_DEFINE_PROTO_FUNCS_WITH_PARENT(cname, no_parent)
         return false;                                           \
     }
 
-GJS_USE
-JS::Value gjs_dynamic_property_private_slot(JSObject *accessor_obj);
+[[nodiscard]] JS::Value gjs_dynamic_property_private_slot(
+    JSObject* accessor_obj);
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_object_in_prototype_chain(JSContext* cx, JS::HandleObject proto,
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index bd41bad8..a8bdbb34 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -117,10 +117,7 @@ bool gjs_init_class_dynamic(JSContext* context, JS::HandleObject in_object,
                              GJS_MODULE_PROP_FLAGS);
 }
 
-GJS_USE
-static const char*
-format_dynamic_class_name (const char *name)
-{
+[[nodiscard]] static const char* format_dynamic_class_name(const char* name) {
     if (g_str_has_prefix(name, "_private_"))
         return name + strlen("_private_");
     else
diff --git a/gjs/jsapi-util-args.h b/gjs/jsapi-util-args.h
index 0c91c503..9e49df7d 100644
--- a/gjs/jsapi-util-args.h
+++ b/gjs/jsapi-util-args.h
@@ -43,7 +43,7 @@
 #include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
-GJS_ALWAYS_INLINE GJS_USE static inline bool check_nullable(
+GJS_ALWAYS_INLINE [[nodiscard]] static inline bool check_nullable(
     const char*& fchar, const char*& fmt_string) {
     if (*fchar != '?')
         return false;
@@ -208,7 +208,7 @@ GJS_ALWAYS_INLINE static inline void assign(JSContext* cx, char c,
  * see overload in jsapi-util-args.cpp */
 template <typename T, typename std::enable_if_t<
                           !std::is_same_v<T, JS::RootedObject*>, int> = 0>
-static inline void free_if_necessary(T param_ref G_GNUC_UNUSED) {}
+static inline void free_if_necessary(T param_ref [[maybe_unused]]) {}
 
 GJS_ALWAYS_INLINE
 static inline void
@@ -279,7 +279,7 @@ GJS_JSAPI_RETURN_CONVENTION static bool parse_call_args_helper(
 }
 
 /* Empty-args version of the template */
-G_GNUC_UNUSED GJS_JSAPI_RETURN_CONVENTION static bool gjs_parse_call_args(
+GJS_JSAPI_RETURN_CONVENTION [[maybe_unused]] static bool gjs_parse_call_args(
     JSContext* cx, const char* function_name, const JS::CallArgs& args,
     const char* format) {
     bool ignore_trailing_args = false;
diff --git a/gjs/jsapi-util-root.h b/gjs/jsapi-util-root.h
index bde43414..ca1f25cd 100644
--- a/gjs/jsapi-util-root.h
+++ b/gjs/jsapi-util-root.h
@@ -80,13 +80,13 @@
  */
 template<typename T>
 struct GjsHeapOperation {
-    GJS_USE static bool update_after_gc(JS::Heap<T>* location);
+    [[nodiscard]] static bool update_after_gc(JS::Heap<T>* location);
     static void expose_to_js(JS::Heap<T>& thing);
 };
 
 template<>
 struct GjsHeapOperation<JSObject *> {
-    GJS_USE static bool update_after_gc(JS::Heap<JSObject*>* location) {
+    [[nodiscard]] static bool update_after_gc(JS::Heap<JSObject*>* location) {
         JS_UpdateWeakPointerAfterGC(location);
         return (location->unbarrieredGet() == nullptr);
     }
@@ -141,7 +141,7 @@ class GjsMaybeOwned {
         ~Notifier() { disconnect(); }
 
         static void on_context_destroy(void* data,
-                                       GObject* ex_context G_GNUC_UNUSED) {
+                                       GObject* ex_context [[maybe_unused]]) {
             auto self = static_cast<Notifier*>(data);
             auto *parent = self->m_parent;
             self->m_parent = nullptr;
@@ -196,14 +196,14 @@ class GjsMaybeOwned {
      * GjsMaybeOwned wrapper in place of the GC thing itself due to the implicit
      * cast operator. But if you want to call methods on the GC thing, for
      * example if it's a JS::Value, you have to use get(). */
-    GJS_USE const T get() const {
+    [[nodiscard]] const T get() const {
         return m_root ? m_root->get() : m_heap.get();
     }
     operator const T() const { return get(); }
 
     /* Use debug_addr() only for debug logging, because it is unbarriered. */
     template <typename U = T>
-    GJS_USE const void* debug_addr(
+    [[nodiscard]] const void* debug_addr(
         std::enable_if_t<std::is_pointer_v<U>>* = nullptr) const {
         return m_root ? m_root->get() : m_heap.unbarrieredGet();
     }
@@ -234,7 +234,7 @@ class GjsMaybeOwned {
     /* You can get a Handle<T> if the thing is rooted, so that you can use this
      * wrapper with stack rooting. However, you must not do this if the
      * JSContext can be destroyed while the Handle is live. */
-    GJS_USE JS::Handle<T> handle() {
+    [[nodiscard]] JS::Handle<T> handle() {
         g_assert(m_root);
         return *m_root;
     }
@@ -335,7 +335,7 @@ class GjsMaybeOwned {
         return GjsHeapOperation<T>::update_after_gc(&m_heap);
     }
 
-    GJS_USE bool rooted() const { return m_root != nullptr; }
+    [[nodiscard]] bool rooted() const { return m_root != nullptr; }
 };
 
 #endif  // GJS_JSAPI_UTIL_ROOT_H_
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index 5c6d9e56..49919411 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -380,10 +380,7 @@ gjs_intern_string_to_id(JSContext  *cx,
     return INTERNED_STRING_TO_JSID(cx, str);
 }
 
-GJS_USE
-static std::string
-gjs_debug_flat_string(JSFlatString *fstr)
-{
+[[nodiscard]] static std::string gjs_debug_flat_string(JSFlatString* fstr) {
     JSLinearString *str = js::FlatStringToLinearString(fstr);
     size_t len = js::GetLinearStringLength(str);
 
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 4d7193b2..2f8aee00 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -263,11 +263,8 @@ JSObject* gjs_define_string_array(JSContext* context,
  * are \x escaped.
  *
  */
-GJS_USE
-static char *
-gjs_string_readable(JSContext       *context,
-                    JS::HandleString string)
-{
+[[nodiscard]] static char* gjs_string_readable(JSContext* context,
+                                               JS::HandleString string) {
     GString *buf = g_string_new("");
 
     g_string_append_c(buf, '"');
@@ -295,10 +292,7 @@ gjs_string_readable(JSContext       *context,
     return g_string_free(buf, false);
 }
 
-GJS_USE
-static char *
-_gjs_g_utf8_make_valid (const char *name)
-{
+[[nodiscard]] static char* _gjs_g_utf8_make_valid(const char* name) {
     GString *string;
     const char *remainder, *invalid;
     int remaining_bytes, valid_bytes;
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index b2ff920a..4ce9e844 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -80,11 +80,12 @@ _Pragma("GCC diagnostic pop")
     operator T*() const { return this->get(); }
     T& operator[](size_t i) const { return static_cast<T*>(*this)[i]; }
 
-    GJS_USE
-    T* copy() const { return reinterpret_cast<T*>(ref_func(this->get())); }
+    [[nodiscard]] T* copy() const {
+        return reinterpret_cast<T*>(ref_func(this->get()));
+    }
 
     template <typename C>
-    GJS_USE C* as() const {
+    [[nodiscard]] C* as() const {
         return const_cast<C*>(reinterpret_cast<const C*>(this->get()));
     }
 };
@@ -121,9 +122,15 @@ struct GjsAutoBaseInfo : GjsAutoPointer<GIBaseInfo, GIBaseInfo,
     GjsAutoBaseInfo(GIBaseInfo* ptr = nullptr)  // NOLINT(runtime/explicit)
         : GjsAutoPointer(ptr) {}
 
-    GJS_USE const char* name() const { return g_base_info_get_name(*this); }
-    GJS_USE const char* ns() const { return g_base_info_get_namespace(*this); }
-    GJS_USE GIInfoType type() const { return g_base_info_get_type(*this); }
+    [[nodiscard]] const char* name() const {
+        return g_base_info_get_name(*this);
+    }
+    [[nodiscard]] const char* ns() const {
+        return g_base_info_get_namespace(*this);
+    }
+    [[nodiscard]] GIInfoType type() const {
+        return g_base_info_get_type(*this);
+    }
 };
 
 // Use GjsAutoInfo, preferably its typedefs below, when you know for sure that
@@ -223,8 +230,7 @@ struct GCPolicy<GjsAutoParam> : public IgnoreGCPolicy<GjsAutoParam> {};
     if (!args.computeThis(cx, &to))                   \
         return false;
 
-GJS_USE
-JSObject*   gjs_get_import_global            (JSContext       *context);
+[[nodiscard]] JSObject* gjs_get_import_global(JSContext* cx);
 
 void gjs_throw_constructor_error             (JSContext       *context);
 
@@ -260,9 +266,8 @@ bool gjs_log_exception_uncaught(JSContext* cx);
 bool gjs_log_exception_full(JSContext* cx, JS::HandleValue exc,
                             JS::HandleString message, GLogLevelFlags level);
 
-GJS_USE
-char *gjs_value_debug_string(JSContext      *context,
-                             JS::HandleValue value);
+[[nodiscard]] char* gjs_value_debug_string(JSContext* cx,
+                                           JS::HandleValue value);
 
 void gjs_warning_reporter(JSContext*, JSErrorReport* report);
 
@@ -322,8 +327,8 @@ bool        gjs_unichar_from_string          (JSContext       *context,
 void gjs_maybe_gc (JSContext *context);
 void gjs_gc_if_needed(JSContext *cx);
 
-GJS_USE
-std::u16string gjs_utf8_script_to_utf16(const char* script, ssize_t len);
+[[nodiscard]] std::u16string gjs_utf8_script_to_utf16(const char* script,
+                                                      ssize_t len);
 
 GJS_JSAPI_RETURN_CONVENTION
 GjsAutoChar gjs_format_stack_trace(JSContext       *cx,
@@ -373,17 +378,16 @@ bool gjs_object_require_converted_property(JSContext       *context,
                                            JS::HandleId     property_name,
                                            uint32_t        *value);
 
-GJS_USE std::string gjs_debug_string(JSString* str);
-GJS_USE std::string gjs_debug_symbol(JS::Symbol* const sym);
-GJS_USE std::string gjs_debug_object(JSObject* obj);
-GJS_USE std::string gjs_debug_value(JS::Value v);
-GJS_USE std::string gjs_debug_id(jsid id);
+[[nodiscard]] std::string gjs_debug_string(JSString* str);
+[[nodiscard]] std::string gjs_debug_symbol(JS::Symbol* const sym);
+[[nodiscard]] std::string gjs_debug_object(JSObject* obj);
+[[nodiscard]] std::string gjs_debug_value(JS::Value v);
+[[nodiscard]] std::string gjs_debug_id(jsid id);
 
-GJS_USE
-char* gjs_hyphen_to_underscore(const char* str);
+[[nodiscard]] char* gjs_hyphen_to_underscore(const char* str);
 
 #if defined(G_OS_WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1900))
-GJS_USE std::wstring gjs_win32_vc140_utf8_to_utf16(const char* str);
+[[nodiscard]] std::wstring gjs_win32_vc140_utf8_to_utf16(const char* str);
 #endif
 
 #endif  // GJS_JSAPI_UTIL_H_
diff --git a/gjs/macros.h b/gjs/macros.h
index 18b0b909..9411da86 100644
--- a/gjs/macros.h
+++ b/gjs/macros.h
@@ -41,8 +41,8 @@
  * GJS_USE:
  *
  * Indicates a return value must be used, or the compiler should log a warning.
- * If it is really okay to ignore the return value, use mozilla::Unused to
- * bypass this warning.
+ * Equivalent to [[nodiscard]], but this macro is for use in external headers
+ * which are not necessarily compiled with a C++ compiler.
  */
 #if defined(__GNUC__) || defined(__clang__)
 #    define GJS_USE __attribute__((warn_unused_result))
@@ -53,21 +53,20 @@
 /**
  * GJS_JSAPI_RETURN_CONVENTION:
  *
- * Same as %GJS_USE, but indicates that a return value of true or non-null means
- * that no exception must be pending on the passed-in #JSContext. Conversely, a
- * return value of false or nullptr means that an exception must be pending, or
- * else an uncatchable exception has been thrown.
+ * Same as [[nodiscard]], but indicates that a return value of true or non-null
+ * means that no exception must be pending on the passed-in #JSContext.
+ * Conversely, a return value of false or nullptr means that an exception must
+ * be pending, or else an uncatchable exception has been thrown.
  *
  * It's intended for use by static analysis tools to do better consistency
- * checks. If not using them, then it has the same effect as %GJS_USE above.
+ * checks. If not using them, then it has the same effect as [[nodiscard]].
  * It's also intended as documentation for the programmer.
  */
 #ifdef __clang_analyzer__
 #    define GJS_JSAPI_RETURN_CONVENTION \
-        GJS_USE                         \
-        __attribute__((annotate("jsapi_return_convention")))
+        [[nodiscard]] __attribute__((annotate("jsapi_return_convention")))
 #else
-#    define GJS_JSAPI_RETURN_CONVENTION GJS_USE
+#    define GJS_JSAPI_RETURN_CONVENTION [[nodiscard]]
 #endif
 
 #ifdef __GNUC__
diff --git a/gjs/module.cpp b/gjs/module.cpp
index 6942ee46..dfb7d94d 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -62,17 +62,12 @@ class GjsScriptModule {
 
     /* Private data accessors */
 
-    GJS_USE
-    static inline GjsScriptModule* priv(JSObject* module) {
+    [[nodiscard]] static inline GjsScriptModule* priv(JSObject* module) {
         return static_cast<GjsScriptModule*>(JS_GetPrivate(module));
     }
 
     /* Creates a JS module object. Use instead of the class's constructor */
-    GJS_USE
-    static JSObject *
-    create(JSContext  *cx,
-           const char *name)
-    {
+    [[nodiscard]] static JSObject* create(JSContext* cx, const char* name) {
         JSObject* module = JS_NewObject(cx, &GjsScriptModule::klass);
         JS_SetPrivate(module, new GjsScriptModule(name));
         return module;
diff --git a/gjs/native.h b/gjs/native.h
index b52efeb3..0d838446 100644
--- a/gjs/native.h
+++ b/gjs/native.h
@@ -39,8 +39,7 @@ void   gjs_register_native_module (const char            *module_id,
                                    GjsDefineModuleFunc  func);
 
 /* called by importer.c to to check for already loaded modules */
-GJS_USE
-bool gjs_is_registered_native_module(const char* name);
+[[nodiscard]] bool gjs_is_registered_native_module(const char* name);
 
 /* called by importer.cpp to load a statically linked native module */
 GJS_JSAPI_RETURN_CONVENTION
diff --git a/gjs/profiler-private.h b/gjs/profiler-private.h
index fde18bd6..c8ea3a44 100644
--- a/gjs/profiler-private.h
+++ b/gjs/profiler-private.h
@@ -37,8 +37,7 @@ void _gjs_profiler_add_mark(GjsProfiler* self, int64_t time, int64_t duration,
                             const char* group, const char* name,
                             const char* message);
 
-GJS_USE
-bool _gjs_profiler_is_running(GjsProfiler *self);
+[[nodiscard]] bool _gjs_profiler_is_running(GjsProfiler* self);
 
 void _gjs_profiler_setup_signals(GjsProfiler *self, GjsContext *context);
 
diff --git a/gjs/profiler.cpp b/gjs/profiler.cpp
index bfcc0c68..c5113bec 100644
--- a/gjs/profiler.cpp
+++ b/gjs/profiler.cpp
@@ -54,7 +54,6 @@
 
 #include "gjs/context.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/macros.h"
 #include "gjs/profiler.h"
 
 #define FLUSH_DELAY_SECONDS 3
@@ -142,10 +141,7 @@ static GjsContext *profiling_context;
  * Returns: %TRUE if successful; otherwise %FALSE and the profile
  *   should abort.
  */
-GJS_USE
-static bool
-gjs_profiler_extract_maps(GjsProfiler *self)
-{
+[[nodiscard]] static bool gjs_profiler_extract_maps(GjsProfiler* self) {
     int64_t now = g_get_monotonic_time() * 1000L;
 
     g_assert(((void) "Profiler must be set up before extracting maps", self));
@@ -291,7 +287,7 @@ _gjs_profiler_is_running(GjsProfiler *self)
 
 #ifdef ENABLE_PROFILER
 
-static void gjs_profiler_sigprof(int signum G_GNUC_UNUSED, siginfo_t* info,
+static void gjs_profiler_sigprof(int signum [[maybe_unused]], siginfo_t* info,
                                  void*) {
     GjsProfiler *self = gjs_context_get_profiler(profiling_context);
 
diff --git a/modules/cairo-context.cpp b/modules/cairo-context.cpp
index 59efe992..45e8f7f0 100644
--- a/modules/cairo-context.cpp
+++ b/modules/cairo-context.cpp
@@ -246,8 +246,7 @@ _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method)                               \
     argv.rval().setUndefined();                                            \
 _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
 
-GJS_USE
-static JSObject *gjs_cairo_context_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_context_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_GTYPE("Context", cairo_context,
                             CAIRO_GOBJECT_TYPE_CONTEXT,
@@ -967,16 +966,10 @@ gjs_cairo_context_get_context(JSContext       *context,
     return priv_from_js(context, object);
 }
 
-GJS_USE
-static bool
-context_to_g_argument(JSContext      *context,
-                      JS::Value       value,
-                      const char     *arg_name,
-                      GjsArgumentType argument_type,
-                      GITransfer      transfer,
-                      bool            may_be_null,
-                      GArgument      *arg)
-{
+[[nodiscard]] static bool context_to_g_argument(
+    JSContext* context, JS::Value value, const char* arg_name,
+    GjsArgumentType argument_type, GITransfer transfer, bool may_be_null,
+    GIArgument* arg) {
     if (value.isNull()) {
         if (!may_be_null) {
             GjsAutoChar display_name =
diff --git a/modules/cairo-image-surface.cpp b/modules/cairo-image-surface.cpp
index 0e48a9e4..b2f8d8b7 100644
--- a/modules/cairo-image-surface.cpp
+++ b/modules/cairo-image-surface.cpp
@@ -39,8 +39,7 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_image_surface_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_image_surface_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("ImageSurface", cairo_image_surface,
                              cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/cairo-linear-gradient.cpp b/modules/cairo-linear-gradient.cpp
index 1994a541..5913daf5 100644
--- a/modules/cairo-linear-gradient.cpp
+++ b/modules/cairo-linear-gradient.cpp
@@ -38,8 +38,7 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_linear_gradient_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_linear_gradient_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("LinearGradient", cairo_linear_gradient,
                              cairo_gradient, JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/cairo-path.cpp b/modules/cairo-path.cpp
index dce55685..6735d709 100644
--- a/modules/cairo-path.cpp
+++ b/modules/cairo-path.cpp
@@ -34,10 +34,8 @@
 
 #include "gjs/jsapi-class.h"
 #include "gjs/jsapi-util.h"
-#include "gjs/macros.h"
 
-GJS_USE
-static JSObject *gjs_cairo_path_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_path_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_ABSTRACT("Path", cairo_path, JSCLASS_BACKGROUND_FINALIZE)
 
diff --git a/modules/cairo-pdf-surface.cpp b/modules/cairo-pdf-surface.cpp
index cc6db374..3b73e8b9 100644
--- a/modules/cairo-pdf-surface.cpp
+++ b/modules/cairo-pdf-surface.cpp
@@ -44,8 +44,7 @@
 #    include "gjs/macros.h"
 #    include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_pdf_surface_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_pdf_surface_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("PDFSurface", cairo_pdf_surface,
                              cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/cairo-private.h b/modules/cairo-private.h
index d41db0ef..4156ab45 100644
--- a/modules/cairo-private.h
+++ b/modules/cairo-private.h
@@ -49,9 +49,8 @@ bool gjs_cairo_context_define_proto(JSContext              *cx,
                                     JS::HandleObject        module,
                                     JS::MutableHandleObject proto);
 
-GJS_USE
-cairo_t *        gjs_cairo_context_get_context          (JSContext       *context,
-                                                         JS::HandleObject object);
+[[nodiscard]] cairo_t* gjs_cairo_context_get_context(JSContext* cx,
+                                                     JS::HandleObject object);
 GJS_JSAPI_RETURN_CONVENTION
 JSObject *       gjs_cairo_context_from_context         (JSContext       *context,
                                                          cairo_t         *cr);
@@ -72,8 +71,7 @@ cairo_path_t* gjs_cairo_path_get_path(JSContext* cx,
                                       JS::HandleObject path_wrapper);
 
 /* surface */
-GJS_USE
-JSObject *gjs_cairo_surface_get_proto(JSContext *cx);
+[[nodiscard]] JSObject* gjs_cairo_surface_get_proto(JSContext* cx);
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_cairo_surface_define_proto(JSContext              *cx,
@@ -137,8 +135,7 @@ JSObject *       gjs_cairo_svg_surface_from_surface     (JSContext       *contex
                                                          cairo_surface_t *surface);
 
 /* pattern */
-GJS_USE
-JSObject *gjs_cairo_pattern_get_proto(JSContext *cx);
+[[nodiscard]] JSObject* gjs_cairo_pattern_get_proto(JSContext* cx);
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_cairo_pattern_define_proto(JSContext              *cx,
@@ -156,8 +153,7 @@ cairo_pattern_t* gjs_cairo_pattern_get_pattern(
     JSContext* cx, JS::HandleObject pattern_wrapper);
 
 /* gradient */
-GJS_USE
-JSObject *gjs_cairo_gradient_get_proto(JSContext *cx);
+[[nodiscard]] JSObject* gjs_cairo_gradient_get_proto(JSContext* cx);
 
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_cairo_gradient_define_proto(JSContext              *cx,
diff --git a/modules/cairo-ps-surface.cpp b/modules/cairo-ps-surface.cpp
index 1d3ae811..be78b366 100644
--- a/modules/cairo-ps-surface.cpp
+++ b/modules/cairo-ps-surface.cpp
@@ -44,8 +44,7 @@
 #    include "gjs/macros.h"
 #    include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_ps_surface_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_ps_surface_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("PSSurface", cairo_ps_surface, cairo_surface,
                              JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/cairo-radial-gradient.cpp b/modules/cairo-radial-gradient.cpp
index 2fcc4437..498af76f 100644
--- a/modules/cairo-radial-gradient.cpp
+++ b/modules/cairo-radial-gradient.cpp
@@ -38,8 +38,7 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_radial_gradient_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_radial_gradient_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("RadialGradient", cairo_radial_gradient,
                              cairo_gradient, JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/cairo-region.cpp b/modules/cairo-region.cpp
index becad04f..b6ef6652 100644
--- a/modules/cairo-region.cpp
+++ b/modules/cairo-region.cpp
@@ -48,8 +48,7 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_region_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_region_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_GTYPE("Region", cairo_region,
                             CAIRO_GOBJECT_TYPE_REGION,
@@ -296,16 +295,10 @@ gjs_cairo_region_from_region(JSContext *context,
     return object;
 }
 
-GJS_USE
-static bool
-region_to_g_argument(JSContext      *context,
-                     JS::Value       value,
-                     const char     *arg_name,
-                     GjsArgumentType argument_type,
-                     GITransfer      transfer,
-                     bool            may_be_null,
-                     GArgument      *arg)
-{
+[[nodiscard]] static bool region_to_g_argument(
+    JSContext* context, JS::Value value, const char* arg_name,
+    GjsArgumentType argument_type, GITransfer transfer, bool may_be_null,
+    GIArgument* arg) {
     if (value.isNull()) {
         if (!may_be_null) {
             GjsAutoChar display_name =
diff --git a/modules/cairo-solid-pattern.cpp b/modules/cairo-solid-pattern.cpp
index ae43e489..2b9bba88 100644
--- a/modules/cairo-solid-pattern.cpp
+++ b/modules/cairo-solid-pattern.cpp
@@ -39,8 +39,7 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_solid_pattern_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_solid_pattern_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_ABSTRACT_WITH_PARENT("SolidPattern", cairo_solid_pattern,
                                       cairo_pattern,
diff --git a/modules/cairo-surface-pattern.cpp b/modules/cairo-surface-pattern.cpp
index 0be9a9f0..c6b0fec4 100644
--- a/modules/cairo-surface-pattern.cpp
+++ b/modules/cairo-surface-pattern.cpp
@@ -39,8 +39,7 @@
 #include "gjs/macros.h"
 #include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_surface_pattern_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_surface_pattern_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("SurfacePattern", cairo_surface_pattern,
                              cairo_pattern, JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/cairo-surface.cpp b/modules/cairo-surface.cpp
index a7542bbf..f2532c9d 100644
--- a/modules/cairo-surface.cpp
+++ b/modules/cairo-surface.cpp
@@ -240,16 +240,10 @@ cairo_surface_t* gjs_cairo_surface_get_surface(
     return static_cast<cairo_surface_t*>(JS_GetPrivate(surface_wrapper));
 }
 
-GJS_USE
-static bool
-surface_to_g_argument(JSContext      *context,
-                      JS::Value       value,
-                      const char     *arg_name,
-                      GjsArgumentType argument_type,
-                      GITransfer      transfer,
-                      bool            may_be_null,
-                      GArgument      *arg)
-{
+[[nodiscard]] static bool surface_to_g_argument(
+    JSContext* context, JS::Value value, const char* arg_name,
+    GjsArgumentType argument_type, GITransfer transfer, bool may_be_null,
+    GIArgument* arg) {
     if (value.isNull()) {
         if (!may_be_null) {
             GjsAutoChar display_name =
diff --git a/modules/cairo-svg-surface.cpp b/modules/cairo-svg-surface.cpp
index 450ebd73..e5ed7202 100644
--- a/modules/cairo-svg-surface.cpp
+++ b/modules/cairo-svg-surface.cpp
@@ -44,8 +44,7 @@
 #    include "gjs/macros.h"
 #    include "modules/cairo-private.h"
 
-GJS_USE
-static JSObject *gjs_cairo_svg_surface_get_proto(JSContext *);
+[[nodiscard]] static JSObject* gjs_cairo_svg_surface_get_proto(JSContext*);
 
 GJS_DEFINE_PROTO_WITH_PARENT("SVGSurface", cairo_svg_surface,
                              cairo_surface, JSCLASS_BACKGROUND_FINALIZE)
diff --git a/modules/console.cpp b/modules/console.cpp
index 100bbbda..a8519bc6 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -247,8 +247,8 @@ public:
     }
 };
 
-GJS_USE
-static bool gjs_console_readline(char** bufp, const char* prompt) {
+[[nodiscard]] static bool gjs_console_readline(char** bufp,
+                                               const char* prompt) {
 #ifdef HAVE_READLINE_READLINE_H
     char *line;
     line = readline(prompt);
@@ -272,13 +272,10 @@ static bool gjs_console_readline(char** bufp, const char* prompt) {
  * exception. (This is because the exception should be auto-printed around the
  * invocation of this function.)
  */
-GJS_USE
-static bool
-gjs_console_eval_and_print(JSContext  *cx,
-                           const char *bytes,
-                           size_t      length,
-                           int         lineno)
-{
+[[nodiscard]] static bool gjs_console_eval_and_print(JSContext* cx,
+                                                     const char* bytes,
+                                                     size_t length,
+                                                     int lineno) {
     JS::SourceText<mozilla::Utf8Unit> source;
     if (!source.init(cx, bytes, length, JS::SourceOwnership::Borrowed))
         return false;
diff --git a/util/log.h b/util/log.h
index feb49e05..0000abe6 100644
--- a/util/log.h
+++ b/util/log.h
@@ -107,7 +107,7 @@ typedef enum {
             gjs_debug(topic, __VA_ARGS__); \
         } while (0)
 #else
-#    define GJS_USED_VERBOSE_PROPS G_GNUC_UNUSED
+#    define GJS_USED_VERBOSE_PROPS [[maybe_unused]]
 #    define gjs_debug_jsprop(topic, ...) ((void)0)
 #endif
 
@@ -118,7 +118,7 @@ typedef enum {
             gjs_debug(topic, __VA_ARGS__); \
         } while (0)
 #else
-#    define GJS_USED_VERBOSE_MARSHAL G_GNUC_UNUSED
+#    define GJS_USED_VERBOSE_MARSHAL [[maybe_unused]]
 #    define gjs_debug_marshal(topic, ...) ((void)0)
 #endif
 
@@ -129,7 +129,7 @@ typedef enum {
             gjs_debug(topic, __VA_ARGS__);  \
         } while (0)
 #else
-#    define GJS_USED_VERBOSE_LIFECYCLE G_GNUC_UNUSED
+#    define GJS_USED_VERBOSE_LIFECYCLE [[maybe_unused]]
 #    define gjs_debug_lifecycle(topic, ...) ((void)0)
 #endif
 
@@ -140,7 +140,7 @@ typedef enum {
             gjs_debug(GJS_DEBUG_GI_USAGE, __VA_ARGS__); \
         } while (0)
 #else
-#    define GJS_USED_VERBOSE_GI_USAGE G_GNUC_UNUSED
+#    define GJS_USED_VERBOSE_GI_USAGE [[maybe_unused]]
 #    define gjs_debug_gi_usage(...) ((void)0)
 #endif
 
@@ -151,7 +151,7 @@ typedef enum {
             gjs_debug(GJS_DEBUG_GCLOSURE, __VA_ARGS__); \
         } while (0)
 #else
-#    define GJS_USED_VERBOSE_GCLOSURE G_GNUC_UNUSED
+#    define GJS_USED_VERBOSE_GCLOSURE [[maybe_unused]]
 #    define gjs_debug_closure(...) ((void)0)
 #endif
 
@@ -162,7 +162,7 @@ typedef enum {
             gjs_debug(GJS_DEBUG_GOBJECT, __VA_ARGS__); \
         } while (0)
 #else
-#    define GJS_USED_VERBOSE_GSIGNAL G_GNUC_UNUSED
+#    define GJS_USED_VERBOSE_GSIGNAL [[maybe_unused]]
 #    define gjs_debug_gsignal(...) ((void)0)
 #endif
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]