Add [[nodiscard]] throughput Google Test.

`EXPECT_THAT(foo, Matcher(bar))` can sometimes get accidentally written as a
no-op `foo, Matcher(bar)`, causing the code to be exercised but defeating the
purpose of testing.

PiperOrigin-RevId: 841880995
Change-Id: Ia55548e3dd83a6f44fff7b5433c8c8ecd7ecbe03
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index fe3b41c..94552ce 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -196,7 +196,7 @@
 // other type T, the built-in default T value is undefined, and the
 // function will abort the process.
 template <typename T>
-class BuiltInDefaultValue {
+class [[nodiscard]] BuiltInDefaultValue {
  public:
   // This function returns true if and only if type T has a built-in default
   // value.
@@ -211,7 +211,7 @@
 // This partial specialization says that we use the same built-in
 // default value for T and const T.
 template <typename T>
-class BuiltInDefaultValue<const T> {
+class [[nodiscard]] BuiltInDefaultValue<const T> {
  public:
   static bool Exists() { return BuiltInDefaultValue<T>::Exists(); }
   static T Get() { return BuiltInDefaultValue<T>::Get(); }
@@ -220,7 +220,7 @@
 // This partial specialization defines the default values for pointer
 // types.
 template <typename T>
-class BuiltInDefaultValue<T*> {
+class [[nodiscard]] BuiltInDefaultValue<T*> {
  public:
   static bool Exists() { return true; }
   static T* Get() { return nullptr; }
@@ -383,7 +383,7 @@
 
 // Specialized for function types below.
 template <typename F>
-class OnceAction;
+class [[nodiscard]] OnceAction;
 
 // An action that can only be used once.
 //
@@ -421,7 +421,7 @@
 // A less-contrived example would be an action that returns an arbitrary type,
 // whose &&-qualified call operator is capable of dealing with move-only types.
 template <typename Result, typename... Args>
-class OnceAction<Result(Args...)> final {
+class [[nodiscard]] OnceAction<Result(Args...)> final {
  private:
   // True iff we can use the given callable type (or lvalue reference) directly
   // via StdFunctionAdaptor.
@@ -574,7 +574,7 @@
 //   // Sets the default value for type T to be foo.
 //   DefaultValue<T>::Set(foo);
 template <typename T>
-class DefaultValue {
+class [[nodiscard]] DefaultValue {
  public:
   // Sets the default value for type T; requires T to be
   // copy-constructable and have a public destructor.
@@ -651,7 +651,7 @@
 // This partial specialization allows a user to set default values for
 // reference types.
 template <typename T>
-class DefaultValue<T&> {
+class [[nodiscard]] DefaultValue<T&> {
  public:
   // Sets the default value for type T&.
   static void Set(T& x) {  // NOLINT
@@ -685,7 +685,7 @@
 // This specialization allows DefaultValue<void>::Get() to
 // compile.
 template <>
-class DefaultValue<void> {
+class [[nodiscard]] DefaultValue<void> {
  public:
   static bool Exists() { return true; }
   static void Get() {}
@@ -701,7 +701,7 @@
 
 // Implement this interface to define an action for function type F.
 template <typename F>
-class ActionInterface {
+class [[nodiscard]] ActionInterface {
  public:
   typedef typename internal::Function<F>::Result Result;
   typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
@@ -721,7 +721,7 @@
 };
 
 template <typename F>
-class Action;
+class [[nodiscard]] Action;
 
 // An Action<R(Args...)> is a copyable and IMMUTABLE (except by assignment)
 // object that represents an action to be taken when a mock function of type
@@ -730,7 +730,7 @@
 // can view an object implementing ActionInterface<F> as a concrete action
 // (including its current state), and an Action<F> object as a handle to it.
 template <typename R, typename... Args>
-class Action<R(Args...)> {
+class [[nodiscard]] Action<R(Args...)> {
  private:
   using F = R(Args...);
 
@@ -869,7 +869,7 @@
 // the definition of Return(void) and SetArgumentPointee<N>(value) for
 // complete examples.
 template <typename Impl>
-class PolymorphicAction {
+class [[nodiscard]] PolymorphicAction {
  public:
   explicit PolymorphicAction(const Impl& impl) : impl_(impl) {}
 
@@ -929,7 +929,7 @@
 
 // The general implementation of Return(R). Specializations follow below.
 template <typename R>
-class ReturnAction final {
+class [[nodiscard]] ReturnAction final {
  public:
   explicit ReturnAction(R value) : value_(std::move(value)) {}
 
@@ -1095,7 +1095,7 @@
 // the const call operator, checking at runtime that it isn't called more than
 // once, since the user has declared their intent to do so by using ByMove.
 template <typename T>
-class ReturnAction<ByMoveWrapper<T>> final {
+class [[nodiscard]] ReturnAction<ByMoveWrapper<T>> final {
  public:
   explicit ReturnAction(ByMoveWrapper<T> wrapper)
       : state_(new State(std::move(wrapper.payload))) {}
@@ -1122,7 +1122,7 @@
 };
 
 // Implements the ReturnNull() action.
-class ReturnNullAction {
+class [[nodiscard]] ReturnNullAction {
  public:
   // Allows ReturnNull() to be used in any pointer-returning function. In C++11
   // this is enforced by returning nullptr, and in non-C++11 by asserting a
@@ -1134,7 +1134,7 @@
 };
 
 // Implements the Return() action.
-class ReturnVoidAction {
+class [[nodiscard]] ReturnVoidAction {
  public:
   // Allows Return() to be used in any void-returning function.
   template <typename Result, typename ArgumentTuple>
@@ -1147,7 +1147,7 @@
 // in any function that returns a reference to the type of x,
 // regardless of the argument types.
 template <typename T>
-class ReturnRefAction {
+class [[nodiscard]] ReturnRefAction {
  public:
   // Constructs a ReturnRefAction object from the reference to be returned.
   explicit ReturnRefAction(T& ref) : ref_(ref) {}  // NOLINT
@@ -1188,7 +1188,7 @@
 // used in any function that returns a reference to the type of x,
 // regardless of the argument types.
 template <typename T>
-class ReturnRefOfCopyAction {
+class [[nodiscard]] ReturnRefOfCopyAction {
  public:
   // Constructs a ReturnRefOfCopyAction object from the reference to
   // be returned.
@@ -1229,7 +1229,7 @@
 // Implements the polymorphic ReturnRoundRobin(v) action, which can be
 // used in any function that returns the element_type of v.
 template <typename T>
-class ReturnRoundRobinAction {
+class [[nodiscard]] ReturnRoundRobinAction {
  public:
   explicit ReturnRoundRobinAction(std::vector<T> values) {
     GTEST_CHECK_(!values.empty())
@@ -1257,7 +1257,7 @@
 };
 
 // Implements the polymorphic DoDefault() action.
-class DoDefaultAction {
+class [[nodiscard]] DoDefaultAction {
  public:
   // This template type conversion operator allows DoDefault() to be
   // used in any function.
@@ -1270,7 +1270,7 @@
 // Implements the Assign action to set a given pointer referent to a
 // particular value.
 template <typename T1, typename T2>
-class AssignAction {
+class [[nodiscard]] AssignAction {
  public:
   AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {}
 
@@ -1289,7 +1289,7 @@
 // Implements the SetErrnoAndReturn action to simulate return from
 // various system calls and libc functions.
 template <typename T>
-class SetErrnoAndReturnAction {
+class [[nodiscard]] SetErrnoAndReturnAction {
  public:
   SetErrnoAndReturnAction(int errno_value, T result)
       : errno_(errno_value), result_(result) {}
@@ -1397,7 +1397,7 @@
 
     void Perform(const ArgumentTuple& args) override {
       // Performs the action and ignores its result.
-      action_.Perform(args);
+      (void)action_.Perform(args);
     }
 
    private:
@@ -1503,11 +1503,11 @@
 };
 
 template <typename... Actions>
-class DoAllAction;
+class [[nodiscard]] DoAllAction;
 
 // Base case: only a single action.
 template <typename FinalAction>
-class DoAllAction<FinalAction> {
+class [[nodiscard]] DoAllAction<FinalAction> {
  public:
   struct UserConstructorTag {};
 
@@ -1561,7 +1561,7 @@
 // Recursive case: support N actions by calling the initial action and then
 // calling through to the base class containing N-1 actions.
 template <typename InitialAction, typename... OtherActions>
-class DoAllAction<InitialAction, OtherActions...>
+class [[nodiscard]] DoAllAction<InitialAction, OtherActions...>
     : private DoAllAction<OtherActions...> {
  private:
   using Base = DoAllAction<OtherActions...>;
@@ -1796,7 +1796,7 @@
 };
 
 template <size_t k>
-class DeleteArgAction {
+class [[nodiscard]] DeleteArgAction {
  public:
   template <typename... Args>
   void operator()(const Args&... args) const {
diff --git a/googlemock/include/gmock/gmock-cardinalities.h b/googlemock/include/gmock/gmock-cardinalities.h
index 533e604..c88c00c 100644
--- a/googlemock/include/gmock/gmock-cardinalities.h
+++ b/googlemock/include/gmock/gmock-cardinalities.h
@@ -63,7 +63,7 @@
 // management as Cardinality objects can now be copied like plain values.
 
 // The implementation of a cardinality.
-class CardinalityInterface {
+class [[nodiscard]] CardinalityInterface {
  public:
   virtual ~CardinalityInterface() = default;
 
@@ -88,7 +88,7 @@
 // object that specifies how many times a mock function is expected to
 // be called.  The implementation of Cardinality is just a std::shared_ptr
 // to const CardinalityInterface. Don't inherit from Cardinality!
-class GTEST_API_ Cardinality {
+class GTEST_API_ [[nodiscard]] Cardinality {
  public:
   // Constructs a null cardinality.  Needed for storing Cardinality
   // objects in STL containers.
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index 666baaf..60ddeab 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -303,7 +303,7 @@
 // plain values.
 
 // A match result listener that stores the explanation in a string.
-class StringMatchResultListener : public MatchResultListener {
+class [[nodiscard]] StringMatchResultListener : public MatchResultListener {
  public:
   StringMatchResultListener() : MatchResultListener(&ss_) {}
 
@@ -336,7 +336,7 @@
 // Matcher but is not one yet; for example, Eq(value)) or a value (for
 // example, "hello").
 template <typename T, typename M>
-class MatcherCastImpl {
+class [[nodiscard]] MatcherCastImpl {
  public:
   static Matcher<T> Cast(const M& polymorphic_matcher_or_value) {
     // M can be a polymorphic matcher, in which case we want to use
@@ -406,7 +406,7 @@
 // is already a Matcher.  This only compiles when type T can be
 // statically converted to type U.
 template <typename T, typename U>
-class MatcherCastImpl<T, Matcher<U>> {
+class [[nodiscard]] MatcherCastImpl<T, Matcher<U>> {
  public:
   static Matcher<T> Cast(const Matcher<U>& source_matcher) {
     return Matcher<T>(new Impl(source_matcher));
@@ -468,14 +468,14 @@
 // This even more specialized version is used for efficiently casting
 // a matcher to its own type.
 template <typename T>
-class MatcherCastImpl<T, Matcher<T>> {
+class [[nodiscard]] MatcherCastImpl<T, Matcher<T>> {
  public:
   static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
 };
 
 // Template specialization for parameterless Matcher.
 template <typename Derived>
-class MatcherBaseImpl {
+class [[nodiscard]] MatcherBaseImpl {
  public:
   MatcherBaseImpl() = default;
 
@@ -488,7 +488,7 @@
 
 // Template specialization for Matcher with parameters.
 template <template <typename...> class Derived, typename... Ts>
-class MatcherBaseImpl<Derived<Ts...>> {
+class [[nodiscard]] MatcherBaseImpl<Derived<Ts...>> {
  public:
   // Mark the constructor explicit for single argument T to avoid implicit
   // conversions.
@@ -626,7 +626,7 @@
 // An internal helper class for doing compile-time loop on a tuple's
 // fields.
 template <size_t N>
-class TuplePrefix {
+class [[nodiscard]] TuplePrefix {
  public:
   // TuplePrefix<N>::Matches(matcher_tuple, value_tuple) returns true
   // if and only if the first N fields of matcher_tuple matches
@@ -674,7 +674,7 @@
 
 // The base case.
 template <>
-class TuplePrefix<0> {
+class [[nodiscard]] TuplePrefix<0> {
  public:
   template <typename MatcherTuple, typename ValueTuple>
   static bool Matches(const MatcherTuple& /* matcher_tuple */,
@@ -719,7 +719,7 @@
 // TransformTupleValuesHelper hides the internal machinery that
 // TransformTupleValues uses to implement a tuple traversal.
 template <typename Tuple, typename Func, typename OutIter>
-class TransformTupleValuesHelper {
+class [[nodiscard]] TransformTupleValuesHelper {
  private:
   typedef ::std::tuple_size<Tuple> TupleSize;
 
@@ -758,7 +758,7 @@
 // type.  This is a polymorphic matcher, so we need a template type
 // conversion operator to make it appearing as a Matcher<T> for any
 // type T.
-class AnythingMatcher {
+class [[nodiscard]] AnythingMatcher {
  public:
   using is_gtest_matcher = void;
 
@@ -777,7 +777,7 @@
 
 // Implements the polymorphic IsNull() matcher, which matches any raw or smart
 // pointer that is NULL.
-class IsNullMatcher {
+class [[nodiscard]] IsNullMatcher {
  public:
   template <typename Pointer>
   bool MatchAndExplain(const Pointer& p,
@@ -791,7 +791,7 @@
 
 // Implements the polymorphic NotNull() matcher, which matches any raw or smart
 // pointer that is not NULL.
-class NotNullMatcher {
+class [[nodiscard]] NotNullMatcher {
  public:
   template <typename Pointer>
   bool MatchAndExplain(const Pointer& p,
@@ -817,10 +817,10 @@
 //   Matcher<int> m1 = Ref(n);   // This won't compile.
 //   Matcher<int&> m2 = Ref(n);  // This will compile.
 template <typename T>
-class RefMatcher;
+class [[nodiscard]] RefMatcher;
 
 template <typename T>
-class RefMatcher<T&> {
+class [[nodiscard]] RefMatcher<T&> {
   // Google Mock is a generic framework and thus needs to support
   // mocking any function types, including those that take non-const
   // reference arguments.  Therefore the template parameter T (and
@@ -909,7 +909,7 @@
 
 // Implements equality-based string matchers like StrEq, StrCaseNe, and etc.
 template <typename StringType>
-class StrEqualityMatcher {
+class [[nodiscard]] StrEqualityMatcher {
  public:
   StrEqualityMatcher(StringType str, bool expect_eq, bool case_sensitive)
       : string_(std::move(str)),
@@ -979,7 +979,7 @@
 // can be used as a Matcher<T> as long as T can be converted to a
 // string.
 template <typename StringType>
-class HasSubstrMatcher {
+class [[nodiscard]] HasSubstrMatcher {
  public:
   explicit HasSubstrMatcher(const StringType& substring)
       : substring_(substring) {}
@@ -1033,7 +1033,7 @@
 // can be used as a Matcher<T> as long as T can be converted to a
 // string.
 template <typename StringType>
-class StartsWithMatcher {
+class [[nodiscard]] StartsWithMatcher {
  public:
   explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {}
 
@@ -1087,7 +1087,7 @@
 // can be used as a Matcher<T> as long as T can be converted to a
 // string.
 template <typename StringType>
-class EndsWithMatcher {
+class [[nodiscard]] EndsWithMatcher {
  public:
   explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
 
@@ -1139,7 +1139,7 @@
 
 // Implements the polymorphic WhenBase64Unescaped(matcher) matcher, which can be
 // used as a Matcher<T> as long as T can be converted to a string.
-class WhenBase64UnescapedMatcher {
+class [[nodiscard]] WhenBase64UnescapedMatcher {
  public:
   using is_gtest_matcher = void;
 
@@ -1185,7 +1185,7 @@
 // etc).  Therefore we use a template type conversion operator in the
 // implementation.
 template <typename D, typename Op>
-class PairMatchBase {
+class [[nodiscard]] PairMatchBase {
  public:
   template <typename T1, typename T2>
   operator Matcher<::std::tuple<T1, T2>>() const {
@@ -1217,27 +1217,32 @@
   };
 };
 
-class Eq2Matcher : public PairMatchBase<Eq2Matcher, std::equal_to<>> {
+class [[nodiscard]] Eq2Matcher
+    : public PairMatchBase<Eq2Matcher, std::equal_to<>> {
  public:
   static const char* Desc() { return "an equal pair"; }
 };
-class Ne2Matcher : public PairMatchBase<Ne2Matcher, std::not_equal_to<>> {
+class [[nodiscard]] Ne2Matcher
+    : public PairMatchBase<Ne2Matcher, std::not_equal_to<>> {
  public:
   static const char* Desc() { return "an unequal pair"; }
 };
-class Lt2Matcher : public PairMatchBase<Lt2Matcher, std::less<>> {
+class [[nodiscard]] Lt2Matcher : public PairMatchBase<Lt2Matcher, std::less<>> {
  public:
   static const char* Desc() { return "a pair where the first < the second"; }
 };
-class Gt2Matcher : public PairMatchBase<Gt2Matcher, std::greater<>> {
+class [[nodiscard]] Gt2Matcher
+    : public PairMatchBase<Gt2Matcher, std::greater<>> {
  public:
   static const char* Desc() { return "a pair where the first > the second"; }
 };
-class Le2Matcher : public PairMatchBase<Le2Matcher, std::less_equal<>> {
+class [[nodiscard]] Le2Matcher
+    : public PairMatchBase<Le2Matcher, std::less_equal<>> {
  public:
   static const char* Desc() { return "a pair where the first <= the second"; }
 };
-class Ge2Matcher : public PairMatchBase<Ge2Matcher, std::greater_equal<>> {
+class [[nodiscard]] Ge2Matcher
+    : public PairMatchBase<Ge2Matcher, std::greater_equal<>> {
  public:
   static const char* Desc() { return "a pair where the first >= the second"; }
 };
@@ -1247,7 +1252,7 @@
 // will prevent different instantiations of NotMatcher from sharing
 // the same NotMatcherImpl<T> class.
 template <typename T>
-class NotMatcherImpl : public MatcherInterface<const T&> {
+class [[nodiscard]] NotMatcherImpl : public MatcherInterface<const T&> {
  public:
   explicit NotMatcherImpl(const Matcher<T>& matcher) : matcher_(matcher) {}
 
@@ -1271,7 +1276,7 @@
 // Implements the Not(m) matcher, which matches a value that doesn't
 // match matcher m.
 template <typename InnerMatcher>
-class NotMatcher {
+class [[nodiscard]] NotMatcher {
  public:
   explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {}
 
@@ -1291,7 +1296,7 @@
 // that will prevent different instantiations of BothOfMatcher from
 // sharing the same BothOfMatcherImpl<T> class.
 template <typename T>
-class AllOfMatcherImpl : public MatcherInterface<const T&> {
+class [[nodiscard]] AllOfMatcherImpl : public MatcherInterface<const T&> {
  public:
   explicit AllOfMatcherImpl(std::vector<Matcher<T>> matchers)
       : matchers_(std::move(matchers)) {}
@@ -1383,7 +1388,7 @@
 // CombiningMatcher<T> is used to recursively combine the provided matchers
 // (of type Args...).
 template <template <typename T> class CombiningMatcher, typename... Args>
-class VariadicMatcher {
+class [[nodiscard]] VariadicMatcher {
  public:
   VariadicMatcher(const Args&... matchers)  // NOLINT
       : matchers_(matchers...) {
@@ -1427,7 +1432,7 @@
 // that will prevent different instantiations of AnyOfMatcher from
 // sharing the same EitherOfMatcherImpl<T> class.
 template <typename T>
-class AnyOfMatcherImpl : public MatcherInterface<const T&> {
+class [[nodiscard]] AnyOfMatcherImpl : public MatcherInterface<const T&> {
  public:
   explicit AnyOfMatcherImpl(std::vector<Matcher<T>> matchers)
       : matchers_(std::move(matchers)) {}
@@ -1519,7 +1524,7 @@
 
 // ConditionalMatcher is the implementation of Conditional(cond, m1, m2)
 template <typename MatcherTrue, typename MatcherFalse>
-class ConditionalMatcher {
+class [[nodiscard]] ConditionalMatcher {
  public:
   ConditionalMatcher(bool condition, MatcherTrue matcher_true,
                      MatcherFalse matcher_false)
@@ -1541,7 +1546,7 @@
 
 // Wrapper for implementation of Any/AllOfArray().
 template <template <class> class MatcherImpl, typename T>
-class SomeOfArrayMatcher {
+class [[nodiscard]] SomeOfArrayMatcher {
  public:
   // Constructs the matcher from a sequence of element values or
   // element matchers.
@@ -1572,7 +1577,7 @@
 // Used for implementing Truly(pred), which turns a predicate into a
 // matcher.
 template <typename Predicate>
-class TrulyMatcher {
+class [[nodiscard]] TrulyMatcher {
  public:
   explicit TrulyMatcher(Predicate pred) : predicate_(pred) {}
 
@@ -1609,7 +1614,7 @@
 // Used for implementing Matches(matcher), which turns a matcher into
 // a predicate.
 template <typename M>
-class MatcherAsPredicate {
+class [[nodiscard]] MatcherAsPredicate {
  public:
   explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {}
 
@@ -1645,7 +1650,7 @@
 // For implementing ASSERT_THAT() and EXPECT_THAT().  The template
 // argument M must be a type that can be converted to a matcher.
 template <typename M>
-class PredicateFormatterFromMatcher {
+class [[nodiscard]] PredicateFormatterFromMatcher {
  public:
   explicit PredicateFormatterFromMatcher(M m) : matcher_(std::move(m)) {}
 
@@ -1704,7 +1709,7 @@
 
 // Implements the polymorphic IsNan() matcher, which matches any floating type
 // value that is Nan.
-class IsNanMatcher {
+class [[nodiscard]] IsNanMatcher {
  public:
   template <typename FloatType>
   bool MatchAndExplain(const FloatType& f,
@@ -1721,7 +1726,7 @@
 // user-specified epsilon.  The template is meant to be instantiated with
 // FloatType being either float or double.
 template <typename FloatType>
-class FloatingEqMatcher {
+class [[nodiscard]] FloatingEqMatcher {
  public:
   // Constructor for FloatingEqMatcher.
   // The matcher's input will be compared with expected.  The matcher treats two
@@ -1869,7 +1874,7 @@
 // against y. The former implements "Eq", the latter "Near". At present, there
 // is no version that compares NaNs as equal.
 template <typename FloatType>
-class FloatingEq2Matcher {
+class [[nodiscard]] FloatingEq2Matcher {
  public:
   FloatingEq2Matcher() { Init(-1, false); }
 
@@ -1941,7 +1946,7 @@
 // Implements the Pointee(m) matcher for matching a pointer whose
 // pointee matches matcher m.  The pointer can be either raw or smart.
 template <typename InnerMatcher>
-class PointeeMatcher {
+class [[nodiscard]] PointeeMatcher {
  public:
   explicit PointeeMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
 
@@ -2000,7 +2005,7 @@
 // m.  The pointer can be either raw or smart, and will match `m` against the
 // raw pointer.
 template <typename InnerMatcher>
-class PointerMatcher {
+class [[nodiscard]] PointerMatcher {
  public:
   explicit PointerMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
 
@@ -2061,7 +2066,7 @@
 // If To is a reference and the cast fails, this matcher returns false
 // immediately.
 template <typename To>
-class WhenDynamicCastToMatcherBase {
+class [[nodiscard]] WhenDynamicCastToMatcherBase {
  public:
   explicit WhenDynamicCastToMatcherBase(const Matcher<To>& matcher)
       : matcher_(matcher) {}
@@ -2090,7 +2095,8 @@
 // Primary template.
 // To is a pointer. Cast and forward the result.
 template <typename To>
-class WhenDynamicCastToMatcher : public WhenDynamicCastToMatcherBase<To> {
+class [[nodiscard]] WhenDynamicCastToMatcher
+    : public WhenDynamicCastToMatcherBase<To> {
  public:
   explicit WhenDynamicCastToMatcher(const Matcher<To>& matcher)
       : WhenDynamicCastToMatcherBase<To>(matcher) {}
@@ -2105,7 +2111,8 @@
 // Specialize for references.
 // In this case we return false if the dynamic_cast fails.
 template <typename To>
-class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
+class [[nodiscard]]
+WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
  public:
   explicit WhenDynamicCastToMatcher(const Matcher<To&>& matcher)
       : WhenDynamicCastToMatcherBase<To&>(matcher) {}
@@ -2126,7 +2133,7 @@
 // Implements the Field() matcher for matching a field (i.e. member
 // variable) of an object.
 template <typename Class, typename FieldType>
-class FieldMatcher {
+class [[nodiscard]] FieldMatcher {
  public:
   FieldMatcher(FieldType Class::* field,
                const Matcher<const FieldType&>& matcher)
@@ -2190,7 +2197,7 @@
 // Property is a const-qualified member function of Class returning
 // PropertyType.
 template <typename Class, typename PropertyType, typename Property>
-class PropertyMatcher {
+class [[nodiscard]] PropertyMatcher {
  public:
   typedef const PropertyType& RefToConstProperty;
 
@@ -2285,7 +2292,7 @@
 // Implements the ResultOf() matcher for matching a return value of a
 // unary function of an object.
 template <typename Callable, typename InnerMatcher>
-class ResultOfMatcher {
+class [[nodiscard]] ResultOfMatcher {
  public:
   ResultOfMatcher(Callable callable, InnerMatcher matcher)
       : ResultOfMatcher(/*result_description=*/"", std::move(callable),
@@ -2375,7 +2382,7 @@
 
 // Implements a matcher that checks the size of an STL-style container.
 template <typename SizeMatcher>
-class SizeIsMatcher {
+class [[nodiscard]] SizeIsMatcher {
  public:
   explicit SizeIsMatcher(const SizeMatcher& size_matcher)
       : size_matcher_(size_matcher) {}
@@ -2423,7 +2430,7 @@
 // Implements a matcher that checks the begin()..end() distance of an STL-style
 // container.
 template <typename DistanceMatcher>
-class BeginEndDistanceIsMatcher {
+class [[nodiscard]] BeginEndDistanceIsMatcher {
  public:
   explicit BeginEndDistanceIsMatcher(const DistanceMatcher& distance_matcher)
       : distance_matcher_(distance_matcher) {}
@@ -2487,7 +2494,7 @@
 // Uses the container's const_iterator, value_type, operator ==,
 // begin(), and end().
 template <typename Container>
-class ContainerEqMatcher {
+class [[nodiscard]] ContainerEqMatcher {
  public:
   typedef internal::StlContainerView<Container> View;
   typedef typename View::type StlContainer;
@@ -2574,7 +2581,7 @@
 
 // Implements WhenSortedBy(comparator, container_matcher).
 template <typename Comparator, typename ContainerMatcher>
-class WhenSortedByMatcher {
+class [[nodiscard]] WhenSortedByMatcher {
  public:
   WhenSortedByMatcher(const Comparator& comparator,
                       const ContainerMatcher& matcher)
@@ -2655,7 +2662,7 @@
 // T2&> >, where T1 and T2 are the types of elements in the LHS
 // container and the RHS container respectively.
 template <typename TupleMatcher, typename RhsContainer>
-class PointwiseMatcher {
+class [[nodiscard]] PointwiseMatcher {
   static_assert(
       !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value,
       "use UnorderedPointwise with hash tables");
@@ -2773,7 +2780,7 @@
 
 // Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
 template <typename Container>
-class QuantifierMatcherImpl : public MatcherInterface<Container> {
+class [[nodiscard]] QuantifierMatcherImpl : public MatcherInterface<Container> {
  public:
   typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
   typedef StlContainerView<RawContainer> View;
@@ -2863,7 +2870,8 @@
 // Implements Contains(element_matcher) for the given argument type Container.
 // Symmetric to EachMatcherImpl.
 template <typename Container>
-class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
+class [[nodiscard]] ContainsMatcherImpl
+    : public QuantifierMatcherImpl<Container> {
  public:
   template <typename InnerMatcher>
   explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
@@ -2894,7 +2902,7 @@
 //   * GetDistance is the type of the functor for computing the distance between
 //     V and T.
 template <typename V, typename T, typename Distance, typename GetDistance>
-class DistanceFromMatcherImpl : public MatcherInterface<V> {
+class [[nodiscard]] DistanceFromMatcherImpl : public MatcherInterface<V> {
  public:
   // Arguments:
   //   * target: the target value.
@@ -2937,7 +2945,7 @@
 // Implements Each(element_matcher) for the given argument type Container.
 // Symmetric to ContainsMatcherImpl.
 template <typename Container>
-class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
+class [[nodiscard]] EachMatcherImpl : public QuantifierMatcherImpl<Container> {
  public:
   template <typename InnerMatcher>
   explicit EachMatcherImpl(InnerMatcher inner_matcher)
@@ -2963,7 +2971,8 @@
 // Implements Contains(element_matcher).Times(n) for the given argument type
 // Container.
 template <typename Container>
-class ContainsTimesMatcherImpl : public QuantifierMatcherImpl<Container> {
+class [[nodiscard]] ContainsTimesMatcherImpl
+    : public QuantifierMatcherImpl<Container> {
  public:
   template <typename InnerMatcher>
   explicit ContainsTimesMatcherImpl(InnerMatcher inner_matcher,
@@ -2996,7 +3005,7 @@
 
 // Implements polymorphic Contains(element_matcher).Times(n).
 template <typename M>
-class ContainsTimesMatcher {
+class [[nodiscard]] ContainsTimesMatcher {
  public:
   explicit ContainsTimesMatcher(M m, Matcher<size_t> count_matcher)
       : inner_matcher_(m), count_matcher_(std::move(count_matcher)) {}
@@ -3014,7 +3023,7 @@
 
 // Implements polymorphic Contains(element_matcher).
 template <typename M>
-class ContainsMatcher {
+class [[nodiscard]] ContainsMatcher {
  public:
   explicit ContainsMatcher(M m) : inner_matcher_(m) {}
 
@@ -3034,7 +3043,7 @@
 
 // Implements polymorphic Each(element_matcher).
 template <typename M>
-class EachMatcher {
+class [[nodiscard]] EachMatcher {
  public:
   explicit EachMatcher(M m) : inner_matcher_(m) {}
 
@@ -3086,7 +3095,7 @@
 //     the value being matched and the target.
 //   * DistanceMatcher is the type of the matcher for checking the distance.
 template <typename T, typename GetDistance, typename DistanceMatcher>
-class DistanceFromMatcher {
+class [[nodiscard]] DistanceFromMatcher {
  public:
   // Arguments:
   //   * target: the target value.
@@ -3120,7 +3129,7 @@
 // inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
 // std::map that contains at least one element whose key is >= 5.
 template <typename PairType>
-class KeyMatcherImpl : public MatcherInterface<PairType> {
+class [[nodiscard]] KeyMatcherImpl : public MatcherInterface<PairType> {
  public:
   typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
   typedef typename RawPairType::first_type KeyType;
@@ -3162,7 +3171,7 @@
 
 // Implements polymorphic Key(matcher_for_key).
 template <typename M>
-class KeyMatcher {
+class [[nodiscard]] KeyMatcher {
  public:
   explicit KeyMatcher(M m) : matcher_for_key_(m) {}
 
@@ -3178,7 +3187,7 @@
 
 // Implements polymorphic Address(matcher_for_address).
 template <typename InnerMatcher>
-class AddressMatcher {
+class [[nodiscard]] AddressMatcher {
  public:
   explicit AddressMatcher(InnerMatcher m) : matcher_(m) {}
 
@@ -3222,7 +3231,7 @@
 // Implements Pair(first_matcher, second_matcher) for the given argument pair
 // type with its two matchers. See Pair() function below.
 template <typename PairType>
-class PairMatcherImpl : public MatcherInterface<PairType> {
+class [[nodiscard]] PairMatcherImpl : public MatcherInterface<PairType> {
  public:
   typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
   typedef typename RawPairType::first_type FirstType;
@@ -3305,7 +3314,7 @@
 
 // Implements polymorphic Pair(first_matcher, second_matcher).
 template <typename FirstMatcher, typename SecondMatcher>
-class PairMatcher {
+class [[nodiscard]] PairMatcher {
  public:
   PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher)
       : first_matcher_(first_matcher), second_matcher_(second_matcher) {}
@@ -3489,10 +3498,10 @@
 void VariadicExpand(const T (&)[N]) {}
 
 template <typename Struct, typename StructSize>
-class FieldsAreMatcherImpl;
+class [[nodiscard]] FieldsAreMatcherImpl;
 
 template <typename Struct, size_t... I>
-class FieldsAreMatcherImpl<Struct, std::index_sequence<I...>>
+class [[nodiscard]] FieldsAreMatcherImpl<Struct, std::index_sequence<I...>>
     : public MatcherInterface<Struct> {
   using UnpackedType =
       decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>()));
@@ -3567,7 +3576,7 @@
 };
 
 template <typename... Inner>
-class FieldsAreMatcher {
+class [[nodiscard]] FieldsAreMatcher {
  public:
   explicit FieldsAreMatcher(Inner... inner) : matchers_(std::move(inner)...) {}
 
@@ -3584,7 +3593,8 @@
 
 // Implements ElementsAre() and ElementsAreArray().
 template <typename Container>
-class ElementsAreMatcherImpl : public MatcherInterface<Container> {
+class [[nodiscard]] ElementsAreMatcherImpl
+    : public MatcherInterface<Container> {
  public:
   typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
   typedef internal::StlContainerView<RawContainer> View;
@@ -3760,7 +3770,7 @@
 // Initially, there are no edges.
 // Use NextGraph() to iterate over all possible edge configurations.
 // Use Randomize() to generate a random edge configuration.
-class GTEST_API_ MatchMatrix {
+class GTEST_API_ [[nodiscard]] MatchMatrix {
  public:
   MatchMatrix(size_t num_elements, size_t num_matchers)
       : num_elements_(num_elements),
@@ -3817,7 +3827,7 @@
 // Untyped base class for implementing UnorderedElementsAre.  By
 // putting logic that's not specific to the element type here, we
 // reduce binary bloat and increase compilation speed.
-class GTEST_API_ UnorderedElementsAreMatcherImplBase {
+class GTEST_API_ [[nodiscard]] UnorderedElementsAreMatcherImplBase {
  protected:
   explicit UnorderedElementsAreMatcherImplBase(
       UnorderedMatcherRequire::Flags matcher_flags)
@@ -3857,7 +3867,7 @@
 // Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and
 // IsSupersetOf.
 template <typename Container>
-class UnorderedElementsAreMatcherImpl
+class [[nodiscard]] UnorderedElementsAreMatcherImpl
     : public MatcherInterface<Container>,
       public UnorderedElementsAreMatcherImplBase {
  public:
@@ -3945,7 +3955,7 @@
 
 // Implements UnorderedElementsAre.
 template <typename MatcherTuple>
-class UnorderedElementsAreMatcher {
+class [[nodiscard]] UnorderedElementsAreMatcher {
  public:
   explicit UnorderedElementsAreMatcher(const MatcherTuple& args)
       : matchers_(args) {}
@@ -3972,7 +3982,7 @@
 
 // Implements ElementsAre.
 template <typename MatcherTuple>
-class ElementsAreMatcher {
+class [[nodiscard]] ElementsAreMatcher {
  public:
   explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {}
 
@@ -4001,7 +4011,7 @@
 
 // Implements UnorderedElementsAreArray(), IsSubsetOf(), and IsSupersetOf().
 template <typename T>
-class UnorderedElementsAreArrayMatcher {
+class [[nodiscard]] UnorderedElementsAreArrayMatcher {
  public:
   template <typename Iter>
   UnorderedElementsAreArrayMatcher(UnorderedMatcherRequire::Flags match_flags,
@@ -4022,7 +4032,7 @@
 
 // Implements ElementsAreArray().
 template <typename T>
-class ElementsAreArrayMatcher {
+class [[nodiscard]] ElementsAreArrayMatcher {
  public:
   template <typename Iter>
   ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
@@ -4051,7 +4061,7 @@
 // instances of this class in a vector when implementing
 // UnorderedPointwise().
 template <typename Tuple2Matcher, typename Second>
-class BoundSecondMatcher {
+class [[nodiscard]] BoundSecondMatcher {
  public:
   BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second)
       : tuple2_matcher_(tm), second_value_(second) {}
@@ -4142,7 +4152,7 @@
 
 // Implements a matcher that checks the value of a optional<> type variable.
 template <typename ValueMatcher>
-class OptionalMatcher {
+class [[nodiscard]] OptionalMatcher {
  public:
   explicit OptionalMatcher(const ValueMatcher& value_matcher)
       : value_matcher_(value_matcher) {}
@@ -4206,7 +4216,7 @@
 
 // Implements a matcher that checks the value of a variant<> type variable.
 template <typename T>
-class VariantMatcher {
+class [[nodiscard]] VariantMatcher {
  public:
   explicit VariantMatcher(::testing::Matcher<const T&> matcher)
       : matcher_(std::move(matcher)) {}
@@ -4267,7 +4277,7 @@
 
 // Implements a matcher that any_casts the value.
 template <typename T>
-class AnyCastMatcher {
+class [[nodiscard]] AnyCastMatcher {
  public:
   explicit AnyCastMatcher(const ::testing::Matcher<const T&>& matcher)
       : matcher_(matcher) {}
@@ -4322,7 +4332,7 @@
 
 // Implements the Args() matcher.
 template <class ArgsTuple, size_t... k>
-class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
+class [[nodiscard]] ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
  public:
   using RawArgsTuple = typename std::decay<ArgsTuple>::type;
   using SelectedArgs =
@@ -4384,7 +4394,7 @@
 };
 
 template <class InnerMatcher, size_t... k>
-class ArgsMatcher {
+class [[nodiscard]] ArgsMatcher {
  public:
   explicit ArgsMatcher(InnerMatcher inner_matcher)
       : inner_matcher_(std::move(inner_matcher)) {}
@@ -5571,7 +5581,7 @@
 // and must not be used in user code!
 namespace internal {
 
-class WithWhatMatcherImpl {
+class [[nodiscard]] WithWhatMatcherImpl {
  public:
   WithWhatMatcherImpl(Matcher<std::string> matcher)
       : matcher_(std::move(matcher)) {}
@@ -5603,7 +5613,7 @@
 }
 
 template <typename Err>
-class ExceptionMatcherImpl {
+class [[nodiscard]] ExceptionMatcherImpl {
   class NeverThrown {
    public:
     const char* what() const noexcept {
diff --git a/googlemock/include/gmock/gmock-more-matchers.h b/googlemock/include/gmock/gmock-more-matchers.h
index 54ea68b..39aad4c 100644
--- a/googlemock/include/gmock/gmock-more-matchers.h
+++ b/googlemock/include/gmock/gmock-more-matchers.h
@@ -61,7 +61,7 @@
 // Implements the polymorphic IsEmpty matcher, which
 // can be used as a Matcher<T> as long as T is either a container that defines
 // empty() and size() (e.g. std::vector or std::string), or a C-style string.
-class IsEmptyMatcher {
+class [[nodiscard]] IsEmptyMatcher {
  public:
   // Matches anything that defines empty() and size().
   template <typename MatcheeContainerType>
diff --git a/googlemock/include/gmock/gmock-nice-strict.h b/googlemock/include/gmock/gmock-nice-strict.h
index 056d471..5a3537e 100644
--- a/googlemock/include/gmock/gmock-nice-strict.h
+++ b/googlemock/include/gmock/gmock-nice-strict.h
@@ -71,11 +71,11 @@
 
 namespace testing {
 template <class MockClass>
-class NiceMock;
+class [[nodiscard]] NiceMock;
 template <class MockClass>
-class NaggyMock;
+class [[nodiscard]] NaggyMock;
 template <class MockClass>
-class StrictMock;
+class [[nodiscard]] StrictMock;
 
 namespace internal {
 template <typename T>
@@ -108,7 +108,7 @@
 #endif
 
 template <typename Base>
-class NiceMockImpl {
+class [[nodiscard]] NiceMockImpl {
  public:
   NiceMockImpl() {
     ::testing::Mock::AllowUninterestingCalls(reinterpret_cast<uintptr_t>(this));
@@ -120,7 +120,7 @@
 };
 
 template <typename Base>
-class NaggyMockImpl {
+class [[nodiscard]] NaggyMockImpl {
  public:
   NaggyMockImpl() {
     ::testing::Mock::WarnUninterestingCalls(reinterpret_cast<uintptr_t>(this));
@@ -132,7 +132,7 @@
 };
 
 template <typename Base>
-class StrictMockImpl {
+class [[nodiscard]] StrictMockImpl {
  public:
   StrictMockImpl() {
     ::testing::Mock::FailUninterestingCalls(reinterpret_cast<uintptr_t>(this));
@@ -146,7 +146,7 @@
 }  // namespace internal
 
 template <class MockClass>
-class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
+class [[nodiscard]] GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
     : private internal::NiceMockImpl<MockClass>,
       public MockClass {
  public:
@@ -187,7 +187,7 @@
 };
 
 template <class MockClass>
-class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
+class [[nodiscard]] GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
     : private internal::NaggyMockImpl<MockClass>,
       public MockClass {
   static_assert(!internal::HasStrictnessModifier<MockClass>(),
@@ -229,7 +229,7 @@
 };
 
 template <class MockClass>
-class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
+class [[nodiscard]] GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
     : private internal::StrictMockImpl<MockClass>,
       public MockClass {
  public:
diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h
index 487d685..cf05d76 100644
--- a/googlemock/include/gmock/internal/gmock-internal-utils.h
+++ b/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -220,7 +220,7 @@
 
 // This interface knows how to report a Google Mock failure (either
 // non-fatal or fatal).
-class FailureReporterInterface {
+class [[nodiscard]] FailureReporterInterface {
  public:
   // The type of a failure (either non-fatal or fatal).
   enum FailureType { kNonfatal, kFatal };
@@ -296,10 +296,14 @@
 //
 //    ON_CALL(mock, Method({}, nullptr))...
 //
-class WithoutMatchers {
+class [[nodiscard]] WithoutMatchers {
  private:
   WithoutMatchers() = default;
-  friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
+  friend
+#ifdef GTEST_OS_WINDOWS
+      GTEST_API_
+#endif
+          WithoutMatchers GetWithoutMatchers();
 };
 
 // Internal use only: access the singleton instance of WithoutMatchers.
@@ -340,7 +344,7 @@
 // This generic version is used when RawContainer itself is already an
 // STL-style container.
 template <class RawContainer>
-class StlContainerView {
+class [[nodiscard]] StlContainerView {
  public:
   typedef RawContainer type;
   typedef const type& const_reference;
@@ -355,7 +359,7 @@
 
 // This specialization is used when RawContainer is a native array type.
 template <typename Element, size_t N>
-class StlContainerView<Element[N]> {
+class [[nodiscard]] StlContainerView<Element[N]> {
  public:
   typedef typename std::remove_const<Element>::type RawElement;
   typedef internal::NativeArray<RawElement> type;
@@ -379,7 +383,7 @@
 // This specialization is used when RawContainer is a native array
 // represented as a (pointer, size) tuple.
 template <typename ElementPointer, typename Size>
-class StlContainerView< ::std::tuple<ElementPointer, Size> > {
+class [[nodiscard]] StlContainerView< ::std::tuple<ElementPointer, Size> > {
  public:
   typedef typename std::remove_const<
       typename std::pointer_traits<ElementPointer>::element_type>::type
diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc
index 6200611..7596532 100644
--- a/googlemock/test/gmock-actions_test.cc
+++ b/googlemock/test/gmock-actions_test.cc
@@ -2170,7 +2170,7 @@
   EXPECT_EQ(7, d.Perform(std::make_tuple(1)));
 
   // Ensure creation of an empty action succeeds.
-  Action<void(int)>(nullptr);
+  (void)Action<void(int)>(nullptr);
 }
 
 TEST(FunctorActionTest, UnusedArguments) {
diff --git a/googlemock/test/gmock-cardinalities_test.cc b/googlemock/test/gmock-cardinalities_test.cc
index ad49752..06daa05 100644
--- a/googlemock/test/gmock-cardinalities_test.cc
+++ b/googlemock/test/gmock-cardinalities_test.cc
@@ -133,7 +133,7 @@
 TEST(AtLeastTest, OnNegativeNumber) {
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        AtLeast(-1);
+        (void)AtLeast(-1);
       },
       "The invocation lower bound must be >= 0");
 }
@@ -186,7 +186,7 @@
 TEST(AtMostTest, OnNegativeNumber) {
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        AtMost(-1);
+        (void)AtMost(-1);
       },
       "The invocation upper bound must be >= 0");
 }
@@ -239,7 +239,7 @@
 TEST(BetweenTest, OnNegativeStart) {
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        Between(-1, 2);
+        (void)Between(-1, 2);
       },
       "The invocation lower bound must be >= 0, but is actually -1");
 }
@@ -247,7 +247,7 @@
 TEST(BetweenTest, OnNegativeEnd) {
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        Between(1, -2);
+        (void)Between(1, -2);
       },
       "The invocation upper bound must be >= 0, but is actually -2");
 }
@@ -255,7 +255,7 @@
 TEST(BetweenTest, OnStartBiggerThanEnd) {
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        Between(2, 1);
+        (void)Between(2, 1);
       },
       "The invocation upper bound (1) must be >= "
       "the invocation lower bound (2)");
@@ -340,7 +340,7 @@
 TEST(ExactlyTest, OnNegativeNumber) {
   EXPECT_NONFATAL_FAILURE(
       {  // NOLINT
-        Exactly(-1);
+        (void)Exactly(-1);
       },
       "The invocation lower bound must be >= 0");
 }
diff --git a/googlemock/test/gmock-matchers-arithmetic_test.cc b/googlemock/test/gmock-matchers-arithmetic_test.cc
index 40a1704..65f8a5f 100644
--- a/googlemock/test/gmock-matchers-arithmetic_test.cc
+++ b/googlemock/test/gmock-matchers-arithmetic_test.cc
@@ -720,7 +720,6 @@
 
   m = AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), Ne(9),
             Ne(10), Ne(11));
-  AllOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
   EXPECT_THAT(Describe(m), EndsWith("and (isn't equal to 11)"));
   AllOfMatches(11, m);
 }
diff --git a/googlemock/test/gmock-matchers-containers_test.cc b/googlemock/test/gmock-matchers-containers_test.cc
index c3b3ef0..a5e1aeb 100644
--- a/googlemock/test/gmock-matchers-containers_test.cc
+++ b/googlemock/test/gmock-matchers-containers_test.cc
@@ -1047,8 +1047,8 @@
 // a NULL function pointer.
 TEST(ResultOfDeathTest, DiesOnNullFunctionPointers) {
   EXPECT_DEATH_IF_SUPPORTED(
-      ResultOf(static_cast<std::string (*)(int dummy)>(nullptr),
-               Eq(std::string("foo"))),
+      (void)ResultOf(static_cast<std::string (*)(int dummy)>(nullptr),
+                     Eq(std::string("foo"))),
       "NULL function pointer is passed into ResultOf\\(\\)\\.");
 }
 
diff --git a/googletest/include/gtest/gtest-assertion-result.h b/googletest/include/gtest/gtest-assertion-result.h
index 954e7c4..52a6d62 100644
--- a/googletest/include/gtest/gtest-assertion-result.h
+++ b/googletest/include/gtest/gtest-assertion-result.h
@@ -137,7 +137,7 @@
 class [[nodiscard]] AssertionResult;
 #endif  // !SWIG
 
-class GTEST_API_ AssertionResult {
+class GTEST_API_ [[nodiscard]] AssertionResult {
  public:
   // Copy constructor.
   // Used in EXPECT_TRUE/FALSE(assertion_result).
diff --git a/googletest/include/gtest/gtest-death-test.h b/googletest/include/gtest/gtest-death-test.h
index 3c61909..afd7b3a 100644
--- a/googletest/include/gtest/gtest-death-test.h
+++ b/googletest/include/gtest/gtest-death-test.h
@@ -192,7 +192,7 @@
 // Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
 
 // Tests that an exit code describes a normal exit with a given exit code.
-class GTEST_API_ ExitedWithCode {
+class GTEST_API_ [[nodiscard]] ExitedWithCode {
  public:
   explicit ExitedWithCode(int exit_code);
   ExitedWithCode(const ExitedWithCode&) = default;
@@ -206,7 +206,7 @@
 #if !defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_FUCHSIA)
 // Tests that an exit code describes an exit due to termination by a
 // given signal.
-class GTEST_API_ KilledBySignal {
+class GTEST_API_ [[nodiscard]] KilledBySignal {
  public:
   explicit KilledBySignal(int signum);
   bool operator()(int exit_status) const;
@@ -317,7 +317,7 @@
     GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
                         << "Statement '" #statement "' cannot be verified.";   \
   } else if (::testing::internal::AlwaysFalse()) {                             \
-    ::testing::internal::MakeDeathTestMatcher(regex_or_matcher);               \
+    (void)::testing::internal::MakeDeathTestMatcher(regex_or_matcher);         \
     GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);                 \
     terminator;                                                                \
   } else                                                                       \
diff --git a/googletest/include/gtest/gtest-matchers.h b/googletest/include/gtest/gtest-matchers.h
index bd8dfe9..08ffbeb 100644
--- a/googletest/include/gtest/gtest-matchers.h
+++ b/googletest/include/gtest/gtest-matchers.h
@@ -75,7 +75,7 @@
 //   2. a factory function that creates a Matcher<T> object from a
 //      FooMatcherMatcher.
 
-class MatchResultListener {
+class [[nodiscard]] MatchResultListener {
  public:
   // Creates a listener object with the given underlying ostream.  The
   // listener does not own the ostream, and does not dereference it
@@ -111,7 +111,7 @@
 
 // An instance of a subclass of this knows how to describe itself as a
 // matcher.
-class GTEST_API_ MatcherDescriberInterface {
+class GTEST_API_ [[nodiscard]] MatcherDescriberInterface {
  public:
   virtual ~MatcherDescriberInterface() = default;
 
@@ -137,7 +137,7 @@
 
 // The implementation of a matcher.
 template <typename T>
-class MatcherInterface : public MatcherDescriberInterface {
+class [[nodiscard]] MatcherInterface : public MatcherDescriberInterface {
  public:
   // Returns true if and only if the matcher matches x; also explains the
   // match result to 'listener' if necessary (see the next paragraph), in
@@ -180,7 +180,7 @@
 namespace internal {
 
 // A match result listener that ignores the explanation.
-class DummyMatchResultListener : public MatchResultListener {
+class [[nodiscard]] DummyMatchResultListener : public MatchResultListener {
  public:
   DummyMatchResultListener() : MatchResultListener(nullptr) {}
 
@@ -192,7 +192,7 @@
 // A match result listener that forwards the explanation to a given
 // ostream.  The difference between this and MatchResultListener is
 // that the former is concrete.
-class StreamMatchResultListener : public MatchResultListener {
+class [[nodiscard]] StreamMatchResultListener : public MatchResultListener {
  public:
   explicit StreamMatchResultListener(::std::ostream* os)
       : MatchResultListener(os) {}
@@ -225,7 +225,7 @@
 // from it.  We put functionalities common to all Matcher<T>
 // specializations here to avoid code duplication.
 template <typename T>
-class MatcherBase : private MatcherDescriberInterface {
+class [[nodiscard]] MatcherBase : private MatcherDescriberInterface {
  public:
   // Returns true if and only if the matcher matches x; also explains the
   // match result to 'listener'.
@@ -460,7 +460,7 @@
 // implementation of Matcher<T> is just a std::shared_ptr to const
 // MatcherInterface<T>.  Don't inherit from Matcher!
 template <typename T>
-class Matcher : public internal::MatcherBase<T> {
+class [[nodiscard]] Matcher : public internal::MatcherBase<T> {
  public:
   // Constructs a null matcher.  Needed for storing Matcher objects in STL
   // containers.  A default-constructed matcher is not yet initialized.  You
@@ -491,8 +491,8 @@
 // instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
 // matcher is expected.
 template <>
-class GTEST_API_ Matcher<const std::string&>
-    : public internal::MatcherBase<const std::string&> {
+class GTEST_API_ [[nodiscard]]
+Matcher<const std::string&> : public internal::MatcherBase<const std::string&> {
  public:
   Matcher() = default;
 
@@ -513,8 +513,8 @@
 };
 
 template <>
-class GTEST_API_ Matcher<std::string>
-    : public internal::MatcherBase<std::string> {
+class GTEST_API_ [[nodiscard]]
+Matcher<std::string> : public internal::MatcherBase<std::string> {
  public:
   Matcher() = default;
 
@@ -541,7 +541,7 @@
 // instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
 // matcher is expected.
 template <>
-class GTEST_API_ Matcher<const internal::StringView&>
+class GTEST_API_ [[nodiscard]] Matcher<const internal::StringView&>
     : public internal::MatcherBase<const internal::StringView&> {
  public:
   Matcher() = default;
@@ -567,7 +567,7 @@
 };
 
 template <>
-class GTEST_API_ Matcher<internal::StringView>
+class GTEST_API_ [[nodiscard]] Matcher<internal::StringView>
     : public internal::MatcherBase<internal::StringView> {
  public:
   Matcher() = default;
@@ -614,7 +614,7 @@
 //
 // See the definition of NotNull() for a complete example.
 template <class Impl>
-class PolymorphicMatcher {
+class [[nodiscard]] PolymorphicMatcher {
  public:
   explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
 
@@ -689,7 +689,7 @@
 // The following template definition assumes that the Rhs parameter is
 // a "bare" type (i.e. neither 'const T' nor 'T&').
 template <typename D, typename Rhs, typename Op>
-class ComparisonBase {
+class [[nodiscard]] ComparisonBase {
  public:
   explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
 
@@ -722,7 +722,8 @@
 };
 
 template <typename Rhs>
-class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>> {
+class [[nodiscard]] EqMatcher
+    : public ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>> {
  public:
   explicit EqMatcher(const Rhs& rhs)
       : ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>>(rhs) {}
@@ -730,7 +731,7 @@
   static const char* NegatedDesc() { return "isn't equal to"; }
 };
 template <typename Rhs>
-class NeMatcher
+class [[nodiscard]] NeMatcher
     : public ComparisonBase<NeMatcher<Rhs>, Rhs, std::not_equal_to<>> {
  public:
   explicit NeMatcher(const Rhs& rhs)
@@ -739,7 +740,8 @@
   static const char* NegatedDesc() { return "is equal to"; }
 };
 template <typename Rhs>
-class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>> {
+class [[nodiscard]] LtMatcher
+    : public ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>> {
  public:
   explicit LtMatcher(const Rhs& rhs)
       : ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>>(rhs) {}
@@ -747,7 +749,8 @@
   static const char* NegatedDesc() { return "isn't <"; }
 };
 template <typename Rhs>
-class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>> {
+class [[nodiscard]] GtMatcher
+    : public ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>> {
  public:
   explicit GtMatcher(const Rhs& rhs)
       : ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>>(rhs) {}
@@ -755,7 +758,7 @@
   static const char* NegatedDesc() { return "isn't >"; }
 };
 template <typename Rhs>
-class LeMatcher
+class [[nodiscard]] LeMatcher
     : public ComparisonBase<LeMatcher<Rhs>, Rhs, std::less_equal<>> {
  public:
   explicit LeMatcher(const Rhs& rhs)
@@ -764,7 +767,7 @@
   static const char* NegatedDesc() { return "isn't <="; }
 };
 template <typename Rhs>
-class GeMatcher
+class [[nodiscard]] GeMatcher
     : public ComparisonBase<GeMatcher<Rhs>, Rhs, std::greater_equal<>> {
  public:
   explicit GeMatcher(const Rhs& rhs)
@@ -776,7 +779,7 @@
 // Same as `EqMatcher<Rhs>`, except that the `rhs` is stored as `StoredRhs` and
 // must be implicitly convertible to `Rhs`.
 template <typename Rhs, typename StoredRhs>
-class ImplicitCastEqMatcher {
+class [[nodiscard]] ImplicitCastEqMatcher {
  public:
   explicit ImplicitCastEqMatcher(const StoredRhs& rhs) : stored_rhs_(rhs) {}
 
@@ -809,7 +812,7 @@
 // Implements polymorphic matchers MatchesRegex(regex) and
 // ContainsRegex(regex), which can be used as a Matcher<T> as long as
 // T can be converted to a string.
-class MatchesRegexMatcher {
+class [[nodiscard]] MatchesRegexMatcher {
  public:
   MatchesRegexMatcher(const RE* regex, bool full_match)
       : regex_(regex), full_match_(full_match) {}
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h
index 048c32d..d1704bb 100644
--- a/googletest/include/gtest/gtest-printers.h
+++ b/googletest/include/gtest/gtest-printers.h
@@ -382,7 +382,7 @@
 
 // The default case.
 template <typename ToPrint, typename OtherOperand>
-class FormatForComparison {
+class [[nodiscard]] FormatForComparison {
  public:
   static ::std::string Format(const ToPrint& value) {
     return ::testing::PrintToString(value);
@@ -391,7 +391,7 @@
 
 // Array.
 template <typename ToPrint, size_t N, typename OtherOperand>
-class FormatForComparison<ToPrint[N], OtherOperand> {
+class [[nodiscard]] FormatForComparison<ToPrint[N], OtherOperand> {
  public:
   static ::std::string Format(const ToPrint* value) {
     return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
@@ -477,7 +477,7 @@
 // function template), as we need to partially specialize it for
 // reference types, which cannot be done with function templates.
 template <typename T>
-class UniversalPrinter;
+class [[nodiscard]] UniversalPrinter;
 
 // Prints the given value using the << operator if it has one;
 // otherwise prints the bytes in it.  This is what
@@ -889,7 +889,7 @@
 // Implements printing a non-reference type T by letting the compiler
 // pick the right overload of PrintTo() for T.
 template <typename T>
-class UniversalPrinter {
+class [[nodiscard]] UniversalPrinter {
  public:
   // MSVC warns about adding const to a function type, so we want to
   // disable the warning.
@@ -915,11 +915,11 @@
 
 // Remove any const-qualifiers before passing a type to UniversalPrinter.
 template <typename T>
-class UniversalPrinter<const T> : public UniversalPrinter<T> {};
+class [[nodiscard]] UniversalPrinter<const T> : public UniversalPrinter<T> {};
 
 // Printer for std::any
 template <>
-class UniversalPrinter<std::any> {
+class [[nodiscard]] UniversalPrinter<std::any> {
  public:
   static void Print(const std::any& value, ::std::ostream* os) {
     if (value.has_value()) {
@@ -942,7 +942,7 @@
 
 // Printer for std::optional
 template <typename T>
-class UniversalPrinter<std::optional<T>> {
+class [[nodiscard]] UniversalPrinter<std::optional<T>> {
  public:
   static void Print(const std::optional<T>& value, ::std::ostream* os) {
     *os << '(';
@@ -956,14 +956,14 @@
 };
 
 template <>
-class UniversalPrinter<std::nullopt_t> {
+class [[nodiscard]] UniversalPrinter<std::nullopt_t> {
  public:
   static void Print(std::nullopt_t, ::std::ostream* os) { *os << "(nullopt)"; }
 };
 
 // Printer for std::variant
 template <typename... T>
-class UniversalPrinter<std::variant<T...>> {
+class [[nodiscard]] UniversalPrinter<std::variant<T...>> {
  public:
   static void Print(const std::variant<T...>& value, ::std::ostream* os) {
     *os << '(';
@@ -1031,7 +1031,7 @@
 
 // Implements printing an array type T[N].
 template <typename T, size_t N>
-class UniversalPrinter<T[N]> {
+class [[nodiscard]] UniversalPrinter<T[N]> {
  public:
   // Prints the given array, omitting some elements when there are too
   // many.
@@ -1042,7 +1042,7 @@
 
 // Implements printing a reference type T&.
 template <typename T>
-class UniversalPrinter<T&> {
+class [[nodiscard]] UniversalPrinter<T&> {
  public:
   // MSVC warns about adding const to a function type, so we want to
   // disable the warning.
@@ -1065,35 +1065,35 @@
 // NUL-terminated string (but not the pointer) is printed.
 
 template <typename T>
-class UniversalTersePrinter {
+class [[nodiscard]] UniversalTersePrinter {
  public:
   static void Print(const T& value, ::std::ostream* os) {
     UniversalPrint(value, os);
   }
 };
 template <typename T>
-class UniversalTersePrinter<T&> {
+class [[nodiscard]] UniversalTersePrinter<T&> {
  public:
   static void Print(const T& value, ::std::ostream* os) {
     UniversalPrint(value, os);
   }
 };
 template <typename T>
-class UniversalTersePrinter<std::reference_wrapper<T>> {
+class [[nodiscard]] UniversalTersePrinter<std::reference_wrapper<T>> {
  public:
   static void Print(std::reference_wrapper<T> value, ::std::ostream* os) {
     UniversalTersePrinter<T>::Print(value.get(), os);
   }
 };
 template <typename T, size_t N>
-class UniversalTersePrinter<T[N]> {
+class [[nodiscard]] UniversalTersePrinter<T[N]> {
  public:
   static void Print(const T (&value)[N], ::std::ostream* os) {
     UniversalPrinter<T[N]>::Print(value, os);
   }
 };
 template <>
-class UniversalTersePrinter<const char*> {
+class [[nodiscard]] UniversalTersePrinter<const char*> {
  public:
   static void Print(const char* str, ::std::ostream* os) {
     if (str == nullptr) {
@@ -1104,12 +1104,12 @@
   }
 };
 template <>
-class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
-};
+class [[nodiscard]]
+UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {};
 
 #ifdef __cpp_lib_char8_t
 template <>
-class UniversalTersePrinter<const char8_t*> {
+class [[nodiscard]] UniversalTersePrinter<const char8_t*> {
  public:
   static void Print(const char8_t* str, ::std::ostream* os) {
     if (str == nullptr) {
@@ -1120,12 +1120,12 @@
   }
 };
 template <>
-class UniversalTersePrinter<char8_t*>
+class [[nodiscard]] UniversalTersePrinter<char8_t*>
     : public UniversalTersePrinter<const char8_t*> {};
 #endif
 
 template <>
-class UniversalTersePrinter<const char16_t*> {
+class [[nodiscard]] UniversalTersePrinter<const char16_t*> {
  public:
   static void Print(const char16_t* str, ::std::ostream* os) {
     if (str == nullptr) {
@@ -1136,11 +1136,11 @@
   }
 };
 template <>
-class UniversalTersePrinter<char16_t*>
+class [[nodiscard]] UniversalTersePrinter<char16_t*>
     : public UniversalTersePrinter<const char16_t*> {};
 
 template <>
-class UniversalTersePrinter<const char32_t*> {
+class [[nodiscard]] UniversalTersePrinter<const char32_t*> {
  public:
   static void Print(const char32_t* str, ::std::ostream* os) {
     if (str == nullptr) {
@@ -1151,12 +1151,12 @@
   }
 };
 template <>
-class UniversalTersePrinter<char32_t*>
+class [[nodiscard]] UniversalTersePrinter<char32_t*>
     : public UniversalTersePrinter<const char32_t*> {};
 
 #if GTEST_HAS_STD_WSTRING
 template <>
-class UniversalTersePrinter<const wchar_t*> {
+class [[nodiscard]] UniversalTersePrinter<const wchar_t*> {
  public:
   static void Print(const wchar_t* str, ::std::ostream* os) {
     if (str == nullptr) {
@@ -1169,7 +1169,7 @@
 #endif
 
 template <>
-class UniversalTersePrinter<wchar_t*> {
+class [[nodiscard]] UniversalTersePrinter<wchar_t*> {
  public:
   static void Print(wchar_t* str, ::std::ostream* os) {
     UniversalTersePrinter<const wchar_t*>::Print(str, os);
diff --git a/googletest/include/gtest/gtest-spi.h b/googletest/include/gtest/gtest-spi.h
index c0613b6..27c2d66 100644
--- a/googletest/include/gtest/gtest-spi.h
+++ b/googletest/include/gtest/gtest-spi.h
@@ -51,7 +51,7 @@
 // generated in the same thread that created this object or it can intercept
 // all generated failures. The scope of this mock object can be controlled with
 // the second argument to the two arguments constructor.
-class GTEST_API_ ScopedFakeTestPartResultReporter
+class GTEST_API_ [[nodiscard]] ScopedFakeTestPartResultReporter
     : public TestPartResultReporterInterface {
  public:
   // The two possible mocking modes of this object.
@@ -100,7 +100,7 @@
 // TestPartResultArray contains exactly one failure that has the given
 // type and contains the given substring.  If that's not the case, a
 // non-fatal failure will be generated.
-class GTEST_API_ SingleFailureChecker {
+class GTEST_API_ [[nodiscard]] SingleFailureChecker {
  public:
   // The constructor remembers the arguments.
   SingleFailureChecker(const TestPartResultArray* results,
diff --git a/googletest/include/gtest/gtest-test-part.h b/googletest/include/gtest/gtest-test-part.h
index 41c8a9a..90380a9 100644
--- a/googletest/include/gtest/gtest-test-part.h
+++ b/googletest/include/gtest/gtest-test-part.h
@@ -51,7 +51,7 @@
 // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
 //
 // Don't inherit from TestPartResult as its destructor is not virtual.
-class GTEST_API_ TestPartResult {
+class GTEST_API_ [[nodiscard]] TestPartResult {
  public:
   // The possible outcomes of a test part (i.e. an assertion or an
   // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
@@ -131,7 +131,7 @@
 //
 // Don't inherit from TestPartResultArray as its destructor is not
 // virtual.
-class GTEST_API_ TestPartResultArray {
+class GTEST_API_ [[nodiscard]] TestPartResultArray {
  public:
   TestPartResultArray() = default;
 
@@ -152,7 +152,7 @@
 };
 
 // This interface knows how to report a test part result.
-class GTEST_API_ TestPartResultReporterInterface {
+class GTEST_API_ [[nodiscard]] TestPartResultReporterInterface {
  public:
   virtual ~TestPartResultReporterInterface() = default;
 
@@ -167,7 +167,7 @@
 // reported, it only delegates the reporting to the former result reporter.
 // The original result reporter is restored in the destructor.
 // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-class GTEST_API_ HasNewFatalFailureHelper
+class GTEST_API_ [[nodiscard]] HasNewFatalFailureHelper
     : public TestPartResultReporterInterface {
  public:
   HasNewFatalFailureHelper();
diff --git a/googletest/include/gtest/gtest-typed-test.h b/googletest/include/gtest/gtest-typed-test.h
index ae24f94..8575a41 100644
--- a/googletest/include/gtest/gtest-typed-test.h
+++ b/googletest/include/gtest/gtest-typed-test.h
@@ -45,7 +45,7 @@
 // First, define a fixture class template.  It should be parameterized
 // by a type.  Remember to derive it from testing::Test.
 template <typename T>
-class FooTest : public testing::Test {
+class [[nodiscard]] FooTest : public testing::Test {
  public:
   ...
   using List = ::std::list<T>;
@@ -123,7 +123,7 @@
 // First, define a fixture class template.  It should be parameterized
 // by a type.  Remember to derive it from testing::Test.
 template <typename T>
-class FooTest : public testing::Test {
+class [[nodiscard]] FooTest : public testing::Test {
   ...
 };
 
diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h
index 69994ee..b636853 100644
--- a/googletest/include/gtest/gtest.h
+++ b/googletest/include/gtest/gtest.h
@@ -193,7 +193,7 @@
 // A base class that prevents subclasses from being copyable.
 // We do this instead of using '= delete' so as to avoid triggering warnings
 // inside user code regarding any of our declarations.
-class GTestNonCopyable {
+class [[nodiscard]] GTestNonCopyable {
  public:
   GTestNonCopyable() = default;
   GTestNonCopyable(const GTestNonCopyable&) = delete;
@@ -206,15 +206,15 @@
 // The friend relationship of some of these classes is cyclic.
 // If we don't forward declare them the compiler might confuse the classes
 // in friendship clauses with same named classes on the scope.
-class Test;
-class TestSuite;
+class [[nodiscard]] Test;
+class [[nodiscard]] TestSuite;
 
 // Old API is still available but deprecated
 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
 using TestCase = TestSuite;
 #endif
-class TestInfo;
-class UnitTest;
+class [[nodiscard]] TestInfo;
+class [[nodiscard]] UnitTest;
 
 // The abstract class that all tests inherit from.
 //
@@ -239,7 +239,7 @@
 //   TEST_F(FooTest, Baz) { ... }
 //
 // Test is not copyable.
-class GTEST_API_ Test {
+class GTEST_API_ [[nodiscard]] Test {
  public:
   friend class TestInfo;
 
@@ -366,7 +366,7 @@
 // output as a key/value string pair.
 //
 // Don't inherit from TestProperty as its destructor is not virtual.
-class TestProperty {
+class [[nodiscard]] TestProperty {
  public:
   // C'tor.  TestProperty does NOT have a default constructor.
   // Always use this constructor (with parameters) to create a
@@ -396,7 +396,7 @@
 // the Test.
 //
 // TestResult is not copyable.
-class GTEST_API_ TestResult {
+class GTEST_API_ [[nodiscard]] TestResult {
  public:
   // Creates an empty TestResult.
   TestResult();
@@ -530,7 +530,7 @@
 // The constructor of TestInfo registers itself with the UnitTest
 // singleton such that the RUN_ALL_TESTS() macro knows which tests to
 // run.
-class GTEST_API_ TestInfo {
+class GTEST_API_ [[nodiscard]] TestInfo {
  public:
   // Destructs a TestInfo object.  This function is not virtual, so
   // don't inherit from TestInfo.
@@ -669,7 +669,7 @@
 // A test suite, which consists of a vector of TestInfos.
 //
 // TestSuite is not copyable.
-class GTEST_API_ TestSuite {
+class GTEST_API_ [[nodiscard]] TestSuite {
  public:
   // Creates a TestSuite with the given name.
   //
@@ -890,7 +890,7 @@
 //      available.
 //   2. You cannot use ASSERT_* directly in a constructor or
 //      destructor.
-class Environment {
+class [[nodiscard]] Environment {
  public:
   // The d'tor is virtual as we need to subclass Environment.
   virtual ~Environment() = default;
@@ -911,7 +911,7 @@
 #if GTEST_HAS_EXCEPTIONS
 
 // Exception which can be thrown from TestEventListener::OnTestPartResult.
-class GTEST_API_ AssertionException
+class GTEST_API_ [[nodiscard]] AssertionException
     : public internal::GoogleTestFailureException {
  public:
   explicit AssertionException(const TestPartResult& result)
@@ -922,7 +922,7 @@
 
 // The interface for tracing execution of tests. The methods are organized in
 // the order the corresponding events are fired.
-class TestEventListener {
+class [[nodiscard]] TestEventListener {
  public:
   virtual ~TestEventListener() = default;
 
@@ -989,7 +989,7 @@
 // the methods they override will not be caught during the build.  For
 // comments about each method please see the definition of TestEventListener
 // above.
-class EmptyTestEventListener : public TestEventListener {
+class [[nodiscard]] EmptyTestEventListener : public TestEventListener {
  public:
   void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
   void OnTestIterationStart(const UnitTest& /*unit_test*/,
@@ -1019,7 +1019,7 @@
 };
 
 // TestEventListeners lets users add listeners to track events in Google Test.
-class GTEST_API_ TestEventListeners {
+class GTEST_API_ [[nodiscard]] TestEventListeners {
  public:
   TestEventListeners();
   ~TestEventListeners();
@@ -1110,7 +1110,7 @@
 //
 // This class is thread-safe as long as the methods are called
 // according to their specification.
-class GTEST_API_ UnitTest {
+class GTEST_API_ [[nodiscard]] UnitTest {
  public:
   // Gets the singleton UnitTest object.  The first time this method
   // is called, a UnitTest object is constructed and returned.
@@ -1398,7 +1398,7 @@
   return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
 }
 
-class EqHelper {
+class [[nodiscard]] EqHelper {
  public:
   // This templatized version is for the general case.
   template <
@@ -1614,7 +1614,7 @@
 
 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
 // A class that enables one to stream messages to assertion macros
-class GTEST_API_ AssertHelper {
+class GTEST_API_ [[nodiscard]] AssertHelper {
  public:
   // Constructor.
   AssertHelper(TestPartResult::Type type, const char* file, int line,
@@ -1689,7 +1689,7 @@
 // INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
 
 template <typename T>
-class WithParamInterface {
+class [[nodiscard]] WithParamInterface {
  public:
   typedef T ParamType;
   virtual ~WithParamInterface() = default;
@@ -1723,7 +1723,8 @@
 // WithParamInterface, and can just inherit from ::testing::TestWithParam.
 
 template <typename T>
-class TestWithParam : public Test, public WithParamInterface<T> {};
+class [[nodiscard]] TestWithParam : public Test,
+                                    public WithParamInterface<T> {};
 
 // Macros for indicating success/failure in test code.
 
@@ -2071,7 +2072,7 @@
 // Example:
 //   testing::ScopedTrace trace("file.cc", 123, "message");
 //
-class GTEST_API_ ScopedTrace {
+class GTEST_API_ [[nodiscard]] ScopedTrace {
  public:
   // The c'tor pushes the given source file location and message onto
   // a trace stack maintained by Google Test.
diff --git a/googletest/include/gtest/internal/gtest-death-test-internal.h b/googletest/include/gtest/internal/gtest-death-test-internal.h
index b363259..6013a57 100644
--- a/googletest/include/gtest/internal/gtest-death-test-internal.h
+++ b/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -96,7 +96,7 @@
 //               by wait(2)
 // exit code:    The integer code passed to exit(3), _Exit(2), or
 //               returned from main()
-class GTEST_API_ DeathTest {
+class GTEST_API_ [[nodiscard]] DeathTest {
  public:
   // Create returns false if there was an error determining the
   // appropriate action to take for the current death test; for example,
@@ -172,7 +172,7 @@
 GTEST_DISABLE_MSC_WARNINGS_POP_()  //  4251
 
 // Factory interface for death tests.  May be mocked out for testing.
-class DeathTestFactory {
+class [[nodiscard]] DeathTestFactory {
  public:
   virtual ~DeathTestFactory() = default;
   virtual bool Create(const char* statement,
@@ -181,7 +181,7 @@
 };
 
 // A concrete DeathTestFactory implementation for normal use.
-class DefaultDeathTestFactory : public DeathTestFactory {
+class [[nodiscard]] DefaultDeathTestFactory : public DeathTestFactory {
  public:
   bool Create(const char* statement, Matcher<const std::string&> matcher,
               const char* file, int line, DeathTest** test) override;
@@ -256,19 +256,19 @@
 // must accept a streamed message even though the message is never printed.
 // The regex object is not evaluated, but it is used to prevent "unused"
 // warnings and to avoid an expression that doesn't compile in debug mode.
-#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher)    \
-  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                  \
-  if (::testing::internal::AlwaysTrue()) {                       \
-    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);   \
-  } else if (!::testing::internal::AlwaysTrue()) {               \
-    ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
-  } else                                                         \
+#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher)          \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                        \
+  if (::testing::internal::AlwaysTrue()) {                             \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);         \
+  } else if (!::testing::internal::AlwaysTrue()) {                     \
+    (void)::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
+  } else                                                               \
     ::testing::Message()
 
 // A class representing the parsed contents of the
 // --gtest_internal_run_death_test flag, as it existed when
 // RUN_ALL_TESTS was called.
-class InternalRunDeathTestFlag {
+class [[nodiscard]] InternalRunDeathTestFlag {
  public:
   InternalRunDeathTestFlag(const std::string& a_file, int a_line, int an_index,
                            int a_write_fd)
diff --git a/googletest/include/gtest/internal/gtest-filepath.h b/googletest/include/gtest/internal/gtest-filepath.h
index 6dc47be..4dc00ee 100644
--- a/googletest/include/gtest/internal/gtest-filepath.h
+++ b/googletest/include/gtest/internal/gtest-filepath.h
@@ -67,7 +67,7 @@
 // Names are NOT checked for syntax correctness -- no checking for illegal
 // characters, malformed paths, etc.
 
-class GTEST_API_ FilePath {
+class GTEST_API_ [[nodiscard]] FilePath {
  public:
   FilePath() : pathname_("") {}
   FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h
index 808d89b..4379137 100644
--- a/googletest/include/gtest/internal/gtest-internal.h
+++ b/googletest/include/gtest/internal/gtest-internal.h
@@ -95,7 +95,7 @@
 #define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, )
 
 namespace proto2 {
-class MessageLite;
+class [[nodiscard]] MessageLite;
 }
 
 namespace testing {
@@ -115,15 +115,15 @@
 namespace internal {
 
 struct TraceInfo;    // Information about a trace point.
-class TestInfoImpl;  // Opaque implementation of TestInfo
-class UnitTestImpl;  // Opaque implementation of UnitTest
+class [[nodiscard]] TestInfoImpl;  // Opaque implementation of TestInfo
+class [[nodiscard]] UnitTestImpl;  // Opaque implementation of UnitTest
 
 // The text used in failure messages to indicate the start of the
 // stack trace.
 GTEST_API_ extern const char kStackTraceMarker[];
 
 // An IgnoredValue object can be implicitly constructed from ANY value.
-class IgnoredValue {
+class [[nodiscard]] IgnoredValue {
   struct Sink {};
 
  public:
@@ -155,7 +155,8 @@
 // errors presumably detectable only at run time.  Since
 // std::runtime_error inherits from std::exception, many testing
 // frameworks know how to extract and print the message inside it.
-class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+class GTEST_API_ [[nodiscard]] GoogleTestFailureException
+    : public ::std::runtime_error {
  public:
   explicit GoogleTestFailureException(const TestPartResult& failure);
 };
@@ -242,7 +243,7 @@
 //
 //   RawType: the raw floating-point type (either float or double)
 template <typename RawType>
-class FloatingPoint {
+class [[nodiscard]] FloatingPoint {
  public:
   // Defines the unsigned integer type that has the same size as the
   // floating point number.
@@ -392,7 +393,7 @@
 typedef const void* TypeId;
 
 template <typename T>
-class TypeIdHelper {
+class [[nodiscard]] TypeIdHelper {
  public:
   // dummy_ must not have a const type.  Otherwise an overly eager
   // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
@@ -424,7 +425,7 @@
 
 // Defines the abstract factory interface that creates instances
 // of a Test object.
-class TestFactoryBase {
+class [[nodiscard]] TestFactoryBase {
  public:
   virtual ~TestFactoryBase() = default;
 
@@ -443,7 +444,7 @@
 // This class provides implementation of TestFactoryBase interface.
 // It is used in TEST and TEST_F macros.
 template <class TestClass>
-class TestFactoryImpl : public TestFactoryBase {
+class [[nodiscard]] TestFactoryImpl : public TestFactoryBase {
  public:
   Test* CreateTest() override { return new TestClass; }
 };
@@ -570,7 +571,7 @@
 /* class A needs to have dll-interface to be used by clients of class B */)
 
 // State of the definition of a type-parameterized test suite.
-class GTEST_API_ TypedTestSuitePState {
+class GTEST_API_ [[nodiscard]] TypedTestSuitePState {
  public:
   TypedTestSuitePState() : registered_(false) {}
 
@@ -685,7 +686,7 @@
 // Implementation note: The GTEST_TEMPLATE_ macro declares a template
 // template parameter.  It's defined in gtest-type-util.h.
 template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
-class TypeParameterizedTest {
+class [[nodiscard]] TypeParameterizedTest {
  public:
   // 'index' is the index of the test in the type list 'Types'
   // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
@@ -723,7 +724,7 @@
 
 // The base case for the compile time recursion.
 template <GTEST_TEMPLATE_ Fixture, class TestSel>
-class TypeParameterizedTest<Fixture, TestSel, internal::None> {
+class [[nodiscard]] TypeParameterizedTest<Fixture, TestSel, internal::None> {
  public:
   static bool Register(const char* /*prefix*/, CodeLocation,
                        const char* /*case_name*/, const char* /*test_names*/,
@@ -744,7 +745,7 @@
 // Test.  The return value is insignificant - we just need to return
 // something such that we can call this function in a namespace scope.
 template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
-class TypeParameterizedTestSuite {
+class [[nodiscard]] TypeParameterizedTestSuite {
  public:
   static bool Register(const char* prefix, CodeLocation code_location,
                        const TypedTestSuitePState* state, const char* case_name,
@@ -782,7 +783,7 @@
 
 // The base case for the compile time recursion.
 template <GTEST_TEMPLATE_ Fixture, typename Types>
-class TypeParameterizedTestSuite<Fixture, internal::None, Types> {
+class [[nodiscard]] TypeParameterizedTestSuite<Fixture, internal::None, Types> {
  public:
   static bool Register(const char* /*prefix*/, const CodeLocation&,
                        const TypedTestSuitePState* /*state*/,
@@ -838,7 +839,7 @@
 // doesn't use global state (and therefore can't interfere with user
 // code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
 // but it's good enough for our purposes.
-class GTEST_API_ Random {
+class GTEST_API_ [[nodiscard]] Random {
  public:
   static const uint32_t kMaxRange = 1u << 31;
 
@@ -864,7 +865,7 @@
 // that's true if and only if T has methods DebugString() and ShortDebugString()
 // that return std::string.
 template <typename T>
-class HasDebugStringAndShortDebugString {
+class [[nodiscard]] HasDebugStringAndShortDebugString {
  private:
   template <typename C>
   static auto CheckDebugString(C*) -> typename std::is_same<
@@ -1064,7 +1065,7 @@
 // this requirement.  Element can be an array type itself (hence
 // multi-dimensional arrays are supported).
 template <typename Element>
-class NativeArray {
+class [[nodiscard]] NativeArray {
  public:
   // STL-style container typedefs.
   typedef Element value_type;
@@ -1150,7 +1151,7 @@
 struct FlatTupleConstructTag {};
 
 template <typename... T>
-class FlatTuple;
+class [[nodiscard]] FlatTuple;
 
 template <typename Derived, size_t I>
 struct FlatTupleElemBase;
@@ -1209,7 +1210,7 @@
 // std::make_index_sequence, on the other hand, it is recursive but with an
 // instantiation depth of O(ln(N)).
 template <typename... T>
-class FlatTuple
+class [[nodiscard]] FlatTuple
     : private FlatTupleBase<FlatTuple<T...>,
                             std::make_index_sequence<sizeof...(T)>> {
   using Indices =
@@ -1317,7 +1318,7 @@
 namespace testing {
 namespace internal {
 
-class NeverThrown {
+class [[nodiscard]] NeverThrown {
  public:
   const char* what() const noexcept {
     return "this exception should never be thrown";
diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h
index a092a86..7167793 100644
--- a/googletest/include/gtest/internal/gtest-param-util.h
+++ b/googletest/include/gtest/internal/gtest-param-util.h
@@ -90,14 +90,14 @@
                                            const CodeLocation& code_location);
 
 template <typename>
-class ParamGeneratorInterface;
+class [[nodiscard]] ParamGeneratorInterface;
 template <typename>
-class ParamGenerator;
+class [[nodiscard]] ParamGenerator;
 
 // Interface for iterating over elements provided by an implementation
 // of ParamGeneratorInterface<T>.
 template <typename T>
-class ParamIteratorInterface {
+class [[nodiscard]] ParamIteratorInterface {
  public:
   virtual ~ParamIteratorInterface() = default;
   // A pointer to the base generator instance.
@@ -127,7 +127,7 @@
 // ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
 // and implements the const forward iterator concept.
 template <typename T>
-class ParamIterator {
+class [[nodiscard]] ParamIterator {
  public:
   typedef T value_type;
   typedef const T& reference;
@@ -169,7 +169,7 @@
 // ParamGeneratorInterface<T> is the binary interface to access generators
 // defined in other translation units.
 template <typename T>
-class ParamGeneratorInterface {
+class [[nodiscard]] ParamGeneratorInterface {
  public:
   typedef T ParamType;
 
@@ -186,7 +186,7 @@
 // ParamGeneratorInterface<T> instance is shared among all copies
 // of the original object. This is possible because that instance is immutable.
 template <typename T>
-class ParamGenerator {
+class [[nodiscard]] ParamGenerator {
  public:
   typedef ParamIterator<T> iterator;
 
@@ -210,7 +210,7 @@
 // operator<().
 // This class is used in the Range() function.
 template <typename T, typename IncrementT>
-class RangeGenerator : public ParamGeneratorInterface<T> {
+class [[nodiscard]] RangeGenerator : public ParamGeneratorInterface<T> {
  public:
   RangeGenerator(T begin, T end, IncrementT step)
       : begin_(begin),
@@ -296,7 +296,8 @@
 // since the source can be located on the stack, and the generator
 // is likely to persist beyond that stack frame.
 template <typename T>
-class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+class [[nodiscard]] ValuesInIteratorRangeGenerator
+    : public ParamGeneratorInterface<T> {
  public:
   template <typename ForwardIterator>
   ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
@@ -396,7 +397,7 @@
 // Stores a parameter value and later creates tests parameterized with that
 // value.
 template <class TestClass>
-class ParameterizedTestFactory : public TestFactoryBase {
+class [[nodiscard]] ParameterizedTestFactory : public TestFactoryBase {
  public:
   typedef typename TestClass::ParamType ParamType;
   explicit ParameterizedTestFactory(ParamType parameter)
@@ -418,7 +419,7 @@
 // TestMetaFactoryBase is a base class for meta-factories that create
 // test factories for passing into MakeAndRegisterTestInfo function.
 template <class ParamType>
-class TestMetaFactoryBase {
+class [[nodiscard]] TestMetaFactoryBase {
  public:
   virtual ~TestMetaFactoryBase() = default;
 
@@ -434,7 +435,7 @@
 // it for each Test/Parameter value combination. Thus it needs meta factory
 // creator class.
 template <class TestSuite>
-class TestMetaFactory
+class [[nodiscard]] TestMetaFactory
     : public TestMetaFactoryBase<typename TestSuite::ParamType> {
  public:
   using ParamType = typename TestSuite::ParamType;
@@ -460,7 +461,7 @@
 // in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
 // a collection of pointers to the ParameterizedTestSuiteInfo objects
 // and calls RegisterTests() on each of them when asked.
-class ParameterizedTestSuiteInfoBase {
+class [[nodiscard]] ParameterizedTestSuiteInfoBase {
  public:
   virtual ~ParameterizedTestSuiteInfoBase() = default;
 
@@ -503,7 +504,8 @@
 // test suite. It registers tests with all values generated by all
 // generators when asked.
 template <class TestSuite>
-class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
+class [[nodiscard]] ParameterizedTestSuiteInfo
+    : public ParameterizedTestSuiteInfoBase {
  public:
   // ParamType and GeneratorCreationFunc are private types but are required
   // for declarations of public methods AddTestPattern() and
@@ -688,7 +690,7 @@
 // ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
 // and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
 // ParameterizedTestSuiteInfo descriptors.
-class ParameterizedTestSuiteRegistry {
+class [[nodiscard]] ParameterizedTestSuiteRegistry {
  public:
   ParameterizedTestSuiteRegistry() = default;
   ~ParameterizedTestSuiteRegistry() {
@@ -762,7 +764,7 @@
 // Keep track of what type-parameterized test suite are defined and
 // where as well as which are intatiated. This allows susequently
 // identifying suits that are defined but never used.
-class TypeParameterizedTestSuiteRegistry {
+class [[nodiscard]] TypeParameterizedTestSuiteRegistry {
  public:
   // Add a suite definition
   void RegisterTestSuite(const char* test_suite_name,
@@ -801,7 +803,7 @@
 GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
 
 template <typename... Ts>
-class ValueArray {
+class [[nodiscard]] ValueArray {
  public:
   explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
 
@@ -822,7 +824,7 @@
 GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4100
 
 template <typename... T>
-class CartesianProductGenerator
+class [[nodiscard]] CartesianProductGenerator
     : public ParamGeneratorInterface<::std::tuple<T...>> {
  public:
   typedef ::std::tuple<T...> ParamType;
@@ -939,7 +941,7 @@
 };
 
 template <class... Gen>
-class CartesianProductHolder {
+class [[nodiscard]] CartesianProductHolder {
  public:
   CartesianProductHolder(const Gen&... g) : generators_(g...) {}
   template <typename... T>
@@ -953,7 +955,8 @@
 };
 
 template <typename From, typename To, typename Func>
-class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
+class [[nodiscard]] ParamGeneratorConverter
+    : public ParamGeneratorInterface<To> {
  public:
   ParamGeneratorConverter(ParamGenerator<From> gen, Func converter)  // NOLINT
       : generator_(std::move(gen)), converter_(std::move(converter)) {}
@@ -1023,7 +1026,7 @@
 template <class GeneratedT,
           typename StdFunction =
               std::function<const GeneratedT&(const GeneratedT&)>>
-class ParamConverterGenerator {
+class [[nodiscard]] ParamConverterGenerator {
  public:
   ParamConverterGenerator(ParamGenerator<GeneratedT> g)  // NOLINT
       : generator_(std::move(g)), converter_(Identity) {}
diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h
index d433f05..f6394a0 100644
--- a/googletest/include/gtest/internal/gtest-port.h
+++ b/googletest/include/gtest/internal/gtest-port.h
@@ -827,6 +827,8 @@
 #elif defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY
 #define GTEST_API_ __declspec(dllexport)
 #endif
+#elif GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(gnu::visibility)
+#define GTEST_API_ [[gnu::visibility("default")]]
 #elif GTEST_HAVE_ATTRIBUTE_(visibility)
 #define GTEST_API_ __attribute__((visibility("default")))
 #endif  // _MSC_VER
@@ -917,7 +919,7 @@
 // A secret type that Google Test users don't know about.  It has no
 // accessible constructors on purpose.  Therefore it's impossible to create a
 // Secret object, which is what we want.
-class Secret {
+class [[nodiscard]] Secret {
   Secret(const Secret&) = delete;
 };
 
@@ -932,7 +934,7 @@
 // This is almost `using RE = ::RE2`, except it is copy-constructible, and it
 // needs to disambiguate the `std::string`, `absl::string_view`, and `const
 // char*` constructors.
-class GTEST_API_ RE {
+class GTEST_API_ [[nodiscard]] RE {
  public:
   RE(absl::string_view regex) : regex_(regex) {}                  // NOLINT
   RE(const char* regex) : RE(absl::string_view(regex)) {}         // NOLINT
@@ -958,7 +960,7 @@
 
 // A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
 // Regular Expression syntax.
-class GTEST_API_ RE {
+class GTEST_API_ [[nodiscard]] RE {
  public:
   // A copy constructor is required by the Standard to initialize object
   // references from r-values.
@@ -1027,7 +1029,7 @@
 // Formats log entry severity, provides a stream object for streaming the
 // log message, and terminates the message with a newline when going out of
 // scope.
-class GTEST_API_ GTestLog {
+class GTEST_API_ [[nodiscard]] GTestLog {
  public:
   GTestLog(GTestLogSeverity severity, const char* file, int line);
 
@@ -1190,7 +1192,7 @@
 #ifdef GTEST_OS_WINDOWS
 // Provides leak-safe Windows kernel handle ownership.
 // Used in death tests and in threading support.
-class GTEST_API_ AutoHandle {
+class GTEST_API_ [[nodiscard]] AutoHandle {
  public:
   // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
   // avoid including <windows.h> in this header file. Including <windows.h> is
@@ -1234,7 +1236,7 @@
 // This class is only for testing Google Test's own constructs. Do not
 // use it in user tests, either directly or indirectly.
 // TODO(b/203539622): Replace unconditionally with absl::Notification.
-class GTEST_API_ Notification {
+class GTEST_API_ [[nodiscard]] Notification {
  public:
   Notification() : notified_(false) {}
   Notification(const Notification&) = delete;
@@ -1273,7 +1275,7 @@
 // in order to call its Run(). Introducing ThreadWithParamBase as a
 // non-templated base class for ThreadWithParam allows us to bypass this
 // problem.
-class ThreadWithParamBase {
+class [[nodiscard]] ThreadWithParamBase {
  public:
   virtual ~ThreadWithParamBase() = default;
   virtual void Run() = 0;
@@ -1303,7 +1305,7 @@
 // These classes are only for testing Google Test's own constructs. Do
 // not use them in user tests, either directly or indirectly.
 template <typename T>
-class ThreadWithParam : public ThreadWithParamBase {
+class [[nodiscard]] ThreadWithParam : public ThreadWithParamBase {
  public:
   typedef void UserThreadFunc(T);
 
@@ -1369,7 +1371,7 @@
 //   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
 //
 // (A non-static Mutex is defined/declared in the usual way).
-class GTEST_API_ Mutex {
+class GTEST_API_ [[nodiscard]] Mutex {
  public:
   enum MutexType { kStatic = 0, kDynamic = 1 };
   // We rely on kStaticMutex being 0 as it is to what the linker initializes
@@ -1422,7 +1424,7 @@
 // platforms. That macro is used as a defensive measure to prevent against
 // inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
 // "MutexLock l(&mu)".  Hence the typedef trick below.
-class GTestMutexLock {
+class [[nodiscard]] GTestMutexLock {
  public:
   explicit GTestMutexLock(Mutex& mutex) : mutex_(mutex) { mutex_.lock(); }
   ~GTestMutexLock() { mutex_.unlock(); }
@@ -1438,14 +1440,14 @@
 
 // Base class for ValueHolder<T>.  Allows a caller to hold and delete a value
 // without knowing its type.
-class ThreadLocalValueHolderBase {
+class [[nodiscard]] ThreadLocalValueHolderBase {
  public:
   virtual ~ThreadLocalValueHolderBase() {}
 };
 
 // Provides a way for a thread to send notifications to a ThreadLocal
 // regardless of its parameter type.
-class ThreadLocalBase {
+class [[nodiscard]] ThreadLocalBase {
  public:
   // Creates a new ValueHolder<T> object holding a default value passed to
   // this ThreadLocal<T>'s constructor and returns it.  It is the caller's
@@ -1465,7 +1467,7 @@
 // Maps a thread to a set of ThreadLocals that have values instantiated on that
 // thread and notifies them when the thread exits.  A ThreadLocal instance is
 // expected to persist until all threads it has values on have terminated.
-class GTEST_API_ ThreadLocalRegistry {
+class GTEST_API_ [[nodiscard]] ThreadLocalRegistry {
  public:
   // Registers thread_local_instance as having value on the current thread.
   // Returns a value that can be used to identify the thread from other threads.
@@ -1477,7 +1479,7 @@
       const ThreadLocalBase* thread_local_instance);
 };
 
-class GTEST_API_ ThreadWithParamBase {
+class GTEST_API_ [[nodiscard]] ThreadWithParamBase {
  public:
   void Join();
 
@@ -1497,7 +1499,7 @@
 
 // Helper class for testing Google Test's multi-threading constructs.
 template <typename T>
-class ThreadWithParam : public ThreadWithParamBase {
+class [[nodiscard]] ThreadWithParam : public ThreadWithParamBase {
  public:
   typedef void UserThreadFunc(T);
 
@@ -1552,7 +1554,7 @@
 // object managed by Google Test will be leaked as long as all threads
 // using Google Test have exited when main() returns.
 template <typename T>
-class ThreadLocal : public ThreadLocalBase {
+class [[nodiscard]] ThreadLocal : public ThreadLocalBase {
  public:
   ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
   explicit ThreadLocal(const T& value)
@@ -1637,7 +1639,7 @@
 #elif GTEST_HAS_PTHREAD
 
 // MutexBase and Mutex implement mutex on pthreads-based platforms.
-class MutexBase {
+class [[nodiscard]] MutexBase {
  public:
   // Acquires this mutex.
   void lock() {
@@ -1695,7 +1697,7 @@
 
 // The Mutex class can only be used for mutexes created at runtime. It
 // shares its API with MutexBase otherwise.
-class Mutex : public MutexBase {
+class [[nodiscard]] Mutex : public MutexBase {
  public:
   Mutex() {
     GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
@@ -1713,7 +1715,7 @@
 // platforms. That macro is used as a defensive measure to prevent against
 // inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
 // "MutexLock l(&mu)".  Hence the typedef trick below.
-class GTestMutexLock {
+class [[nodiscard]] GTestMutexLock {
  public:
   explicit GTestMutexLock(MutexBase& mutex) : mutex_(mutex) { mutex_.lock(); }
   ~GTestMutexLock() { mutex_.unlock(); }
@@ -1733,7 +1735,7 @@
 // C-linkage.  Therefore it cannot be templatized to access
 // ThreadLocal<T>.  Hence the need for class
 // ThreadLocalValueHolderBase.
-class GTEST_API_ ThreadLocalValueHolderBase {
+class GTEST_API_ [[nodiscard]] ThreadLocalValueHolderBase {
  public:
   virtual ~ThreadLocalValueHolderBase() = default;
 };
@@ -1746,7 +1748,7 @@
 
 // Implements thread-local storage on pthreads-based systems.
 template <typename T>
-class GTEST_API_ ThreadLocal {
+class GTEST_API_ [[nodiscard]] ThreadLocal {
  public:
   ThreadLocal()
       : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
@@ -1859,7 +1861,7 @@
 // mutex is not supported - using Google Test in multiple threads is not
 // supported on such platforms.
 
-class Mutex {
+class [[nodiscard]] Mutex {
  public:
   Mutex() {}
   void lock() {}
@@ -1877,7 +1879,7 @@
 // platforms. That macro is used as a defensive measure to prevent against
 // inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
 // "MutexLock l(&mu)".  Hence the typedef trick below.
-class GTestMutexLock {
+class [[nodiscard]] GTestMutexLock {
  public:
   explicit GTestMutexLock(Mutex&) {}  // NOLINT
 };
@@ -1885,7 +1887,7 @@
 typedef GTestMutexLock MutexLock;
 
 template <typename T>
-class GTEST_API_ ThreadLocal {
+class GTEST_API_ [[nodiscard]] ThreadLocal {
  public:
   ThreadLocal() : value_() {}
   explicit ThreadLocal(const T& value) : value_(value) {}
@@ -2193,7 +2195,7 @@
 // needs.  Other types can be easily added in the future if need
 // arises.
 template <size_t size>
-class TypeWithSize {
+class [[nodiscard]] TypeWithSize {
  public:
   // This prevents the user from using TypeWithSize<N> with incorrect
   // values of N.
@@ -2202,7 +2204,7 @@
 
 // The specialization for size 4.
 template <>
-class TypeWithSize<4> {
+class [[nodiscard]] TypeWithSize<4> {
  public:
   using Int = std::int32_t;
   using UInt = std::uint32_t;
@@ -2210,7 +2212,7 @@
 
 // The specialization for size 8.
 template <>
-class TypeWithSize<8> {
+class [[nodiscard]] TypeWithSize<8> {
  public:
   using Int = std::int64_t;
   using UInt = std::uint64_t;
diff --git a/googletest/include/gtest/internal/gtest-string.h b/googletest/include/gtest/internal/gtest-string.h
index 7c05b58..2363034 100644
--- a/googletest/include/gtest/internal/gtest-string.h
+++ b/googletest/include/gtest/internal/gtest-string.h
@@ -60,7 +60,7 @@
 namespace internal {
 
 // String - an abstract class holding static string utilities.
-class GTEST_API_ String {
+class GTEST_API_ [[nodiscard]] String {
  public:
   // Static utility methods
 
@@ -166,7 +166,7 @@
 
  private:
   String();  // Not meant to be instantiated.
-};           // class String
+};  // class String
 
 // Gets the content of the stringstream's buffer as an std::string.  Each '\0'
 // character in the buffer is replaced with "\\0".