| Index: base/debug/crash_logging.h
|
| diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h
|
| index 97bac754a4b626985fe26935d37de8008fb7f7d7..eaa65e4cff9959d527f5694e52107737a42fc886 100644
|
| --- a/base/debug/crash_logging.h
|
| +++ b/base/debug/crash_logging.h
|
| @@ -8,6 +8,7 @@
|
| #include <stddef.h>
|
|
|
| #include <string>
|
| +#include <type_traits>
|
| #include <vector>
|
|
|
| #include "base/base_export.h"
|
| @@ -49,12 +50,47 @@ class BASE_EXPORT ScopedCrashKey {
|
| ScopedCrashKey(const base::StringPiece& key, const base::StringPiece& value);
|
| ~ScopedCrashKey();
|
|
|
| + // Helper to force a static_assert when instantiating a ScopedCrashKey
|
| + // temporary without a name. The usual idiom is to just #define a macro that
|
| + // static_asserts with the message; however, that doesn't work well when the
|
| + // type is in a namespace.
|
| + //
|
| + // Instead, we use a templated helper to trigger the static_assert, observing
|
| + // two rules:
|
| + // - The static_assert needs to be in a normally uninstantiated template;
|
| + // otherwise, it will fail to compile =)
|
| + // - Similarly, the static_assert must be dependent on the template argument,
|
| + // to prevent it from being evaluated until the template is instantiated.
|
| + //
|
| + // To prevent this constructor from being accidentally invoked, it takes a
|
| + // special enum as an argument.
|
| +
|
| + // Finally, note that this can't just be a template function that takes only
|
| + // one parameter, because this ends up triggering the vexing parse issue.
|
| + enum ScopedCrashKeyNeedsNameTag {
|
| + KEY_NEEDS_NAME,
|
| + };
|
| +
|
| + template <typename... Args>
|
| + explicit ScopedCrashKey(ScopedCrashKeyNeedsNameTag, const Args&...) {
|
| + constexpr bool always_false = sizeof...(Args) == 0 && sizeof...(Args) != 0;
|
| + static_assert(
|
| + always_false,
|
| + "scoped crash key objects should not be unnamed temporaries.");
|
| + }
|
| +
|
| private:
|
| std::string key_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ScopedCrashKey);
|
| };
|
|
|
| +// Disallow an instantation of ScopedCrashKey without a name, since this results
|
| +// in a temporary that is immediately destroyed. Doing so will trigger the
|
| +// static_assert in the templated constructor helper in ScopedCrashKey.
|
| +#define ScopedCrashKey(...) \
|
| + ScopedCrashKey(base::debug::ScopedCrashKey::KEY_NEEDS_NAME, __VA_ARGS__)
|
| +
|
| // Before setting values for a key, all the keys must be registered.
|
| struct BASE_EXPORT CrashKey {
|
| // The name of the crash key, used in the above functions.
|
|
|