Commit 288f45d2 authored by dcheng's avatar dcheng Committed by Commit bot

Make it a compile error to use a crash key with no variable name.

BUG=

Review-Url: https://codereview.chromium.org/2137863002
Cr-Commit-Position: refs/heads/master@{#407083}
parent 92c5d3d1
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
// Undef the macro so the preprocessor doesn't garble the constructor.
#undef ScopedCrashKey
namespace base { namespace base {
namespace debug { namespace debug {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <stddef.h> #include <stddef.h>
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
#include "base/base_export.h" #include "base/base_export.h"
...@@ -49,12 +50,47 @@ class BASE_EXPORT ScopedCrashKey { ...@@ -49,12 +50,47 @@ class BASE_EXPORT ScopedCrashKey {
ScopedCrashKey(const base::StringPiece& key, const base::StringPiece& value); ScopedCrashKey(const base::StringPiece& key, const base::StringPiece& value);
~ScopedCrashKey(); ~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: private:
std::string key_; std::string key_;
DISALLOW_COPY_AND_ASSIGN(ScopedCrashKey); 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. // Before setting values for a key, all the keys must be registered.
struct BASE_EXPORT CrashKey { struct BASE_EXPORT CrashKey {
// The name of the crash key, used in the above functions. // The name of the crash key, used in the above functions.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment