chore: apply clang-format

This commit is contained in:
Sergiu Deitsch 2023-12-30 20:01:33 +01:00
parent e3f5398aa1
commit 93549f3600
43 changed files with 2661 additions and 2791 deletions

View File

@ -58,7 +58,7 @@ ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: true DeriveLineEnding: true
DerivePointerAlignment: true DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true FixNamespaceComments: true
@ -84,7 +84,7 @@ IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: '' IncludeIsMainSourceRegex: ''
IndentCaseLabels: true IndentCaseLabels: true
IndentGotoLabels: true IndentGotoLabels: true
IndentPPDirectives: None IndentPPDirectives: AfterHash
IndentWidth: 2 IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave JavaScriptQuotes: Leave

View File

@ -48,63 +48,64 @@
#ifndef BASE_COMMANDLINEFLAGS_H__ #ifndef BASE_COMMANDLINEFLAGS_H__
#define BASE_COMMANDLINEFLAGS_H__ #define BASE_COMMANDLINEFLAGS_H__
#include "config.h" #include <cstdlib> // for getenv
#include <cstdlib> // for getenv #include <cstring> // for memchr
#include <cstring> // for memchr
#include <string> #include <string>
#include "config.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
#else #else
#include "glog/logging.h" # include "glog/logging.h"
#define DECLARE_VARIABLE(type, shorttype, name, tn) \ # define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \ namespace fL##shorttype { \
extern GLOG_EXPORT type FLAGS_##name; \ extern GLOG_EXPORT type FLAGS_##name; \
} \ } \
using fL##shorttype::FLAGS_##name using fL##shorttype::FLAGS_##name
#define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \ # define DEFINE_VARIABLE(type, shorttype, name, value, meaning, tn) \
namespace fL##shorttype { \ namespace fL##shorttype { \
GLOG_EXPORT type FLAGS_##name(value); \ GLOG_EXPORT type FLAGS_##name(value); \
char FLAGS_no##name; \ char FLAGS_no##name; \
} \ } \
using fL##shorttype::FLAGS_##name using fL##shorttype::FLAGS_##name
// bool specialization // bool specialization
#define DECLARE_bool(name) \ # define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name, bool)
DECLARE_VARIABLE(bool, B, name, bool) # define DEFINE_bool(name, value, meaning) \
#define DEFINE_bool(name, value, meaning) \ DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
DEFINE_VARIABLE(bool, B, name, value, meaning, bool)
// int32 specialization // int32 specialization
#define DECLARE_int32(name) DECLARE_VARIABLE(google::int32, I, name, int32) # define DECLARE_int32(name) DECLARE_VARIABLE(google::int32, I, name, int32)
#define DEFINE_int32(name, value, meaning) \ # define DEFINE_int32(name, value, meaning) \
DEFINE_VARIABLE(google::int32, I, name, value, meaning, int32) DEFINE_VARIABLE(google::int32, I, name, value, meaning, int32)
// uint32 specialization // uint32 specialization
#ifndef DECLARE_uint32 # ifndef DECLARE_uint32
#define DECLARE_uint32(name) DECLARE_VARIABLE(google::uint32, U, name, uint32) # define DECLARE_uint32(name) \
#endif // DECLARE_uint64 DECLARE_VARIABLE(google::uint32, U, name, uint32)
#define DEFINE_uint32(name, value, meaning) \ # endif // DECLARE_uint64
DEFINE_VARIABLE(google::uint32, U, name, value, meaning, uint32) # define DEFINE_uint32(name, value, meaning) \
DEFINE_VARIABLE(google::uint32, U, name, value, meaning, uint32)
// Special case for string, because we have to specify the namespace // Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery. // std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \ # define DECLARE_string(name) \
namespace fLS { \ namespace fLS { \
extern GLOG_EXPORT std::string& FLAGS_##name; \ extern GLOG_EXPORT std::string& FLAGS_##name; \
} \ } \
using fLS::FLAGS_##name using fLS::FLAGS_##name
#define DEFINE_string(name, value, meaning) \ # define DEFINE_string(name, value, meaning) \
namespace fLS { \ namespace fLS { \
std::string FLAGS_##name##_buf(value); \ std::string FLAGS_##name##_buf(value); \
GLOG_EXPORT std::string& FLAGS_##name = FLAGS_##name##_buf; \ GLOG_EXPORT std::string& FLAGS_##name = FLAGS_##name##_buf; \
char FLAGS_no##name; \ char FLAGS_no##name; \
} \ } \
using fLS::FLAGS_##name using fLS::FLAGS_##name
#endif // GLOG_USE_GFLAGS #endif // GLOG_USE_GFLAGS
@ -130,8 +131,7 @@
// These macros (could be functions, but I don't want to bother with a .cc // These macros (could be functions, but I don't want to bother with a .cc
// file), make it easier to initialize flags from the environment. // file), make it easier to initialize flags from the environment.
#define EnvToString(envname, dflt) \ #define EnvToString(envname, dflt) (!getenv(envname) ? (dflt) : getenv(envname))
(!getenv(envname) ? (dflt) : getenv(envname))
#define EnvToBool(envname, dflt) \ #define EnvToBool(envname, dflt) \
(!getenv(envname) ? (dflt) \ (!getenv(envname) ? (dflt) \

View File

@ -1,10 +1,10 @@
// Copyright (c) 2008, Google Inc. // Copyright (c) 2008, Google Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
// //
// * Redistributions of source code must retain the above copyright // * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer. // notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above // * Redistributions in binary form must reproduce the above
@ -14,7 +14,7 @@
// * Neither the name of Google Inc. nor the names of its // * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from // contributors may be used to endorse or promote products derived from
// this software without specific prior written permission. // this software without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -36,16 +36,14 @@
class GoogleInitializer { class GoogleInitializer {
public: public:
using void_function = void (*)(); using void_function = void (*)();
GoogleInitializer(const char*, void_function f) { GoogleInitializer(const char*, void_function f) { f(); }
f();
}
}; };
#define REGISTER_MODULE_INITIALIZER(name, body) \ #define REGISTER_MODULE_INITIALIZER(name, body) \
namespace { \ namespace { \
static void google_init_module_##name () { body; } \ static void google_init_module_##name() { body; } \
GoogleInitializer google_initializer_module_##name(#name, \ GoogleInitializer google_initializer_module_##name( \
google_init_module_##name); \ #name, google_init_module_##name); \
} }
#endif /* _GOOGLEINIT_H */ #endif /* _GOOGLEINIT_H */

View File

@ -102,55 +102,56 @@
#ifndef GOOGLE_MUTEX_H_ #ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_ #define GOOGLE_MUTEX_H_
#include "config.h" // to figure out pthreads support #include "config.h" // to figure out pthreads support
#if defined(NO_THREADS) #if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN__) #elif defined(_WIN32) || defined(__CYGWIN__)
# ifndef WIN32_LEAN_AND_MEAN # ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes # define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif # endif
# ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you // We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT // don't need that functionality, you can remove these _WIN32_WINNT
// lines, and change TryLock() to assert(0) or something. // lines, and change TryLock() to assert(0) or something.
# ifndef _WIN32_WINNT # ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400 # define _WIN32_WINNT 0x0400
# endif # endif
# endif # endif
// To avoid macro definition of ERROR. // To avoid macro definition of ERROR.
# ifndef NOGDI # ifndef NOGDI
# define NOGDI # define NOGDI
# endif # endif
// To avoid macro definition of min/max. // To avoid macro definition of min/max.
# ifndef NOMINMAX # ifndef NOMINMAX
# define NOMINMAX # define NOMINMAX
# endif # endif
# include <windows.h> # include <windows.h>
typedef CRITICAL_SECTION MutexType; typedef CRITICAL_SECTION MutexType;
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
// Needed for pthread_rwlock_*. If it causes problems, you could take it // Needed for pthread_rwlock_*. If it causes problems, you could take it
// out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.) // for locking there.)
# ifdef __linux__ # ifdef __linux__
# ifndef _XOPEN_SOURCE // Some other header might have already set it for us. # ifndef _XOPEN_SOURCE // Some other header might have already set it for
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls // us.
# endif # define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif # endif
# include <pthread.h> # endif
# include <pthread.h>
using MutexType = pthread_rwlock_t; using MutexType = pthread_rwlock_t;
#elif defined(HAVE_PTHREAD) #elif defined(HAVE_PTHREAD)
# include <pthread.h> # include <pthread.h>
typedef pthread_mutex_t MutexType; typedef pthread_mutex_t MutexType;
#else #else
# error Need to implement mutex.h for your architecture, or #define NO_THREADS # error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif #endif
// We need to include these header files after defining _XOPEN_SOURCE // We need to include these header files after defining _XOPEN_SOURCE
// as they may define the _XOPEN_SOURCE macro. // as they may define the _XOPEN_SOURCE macro.
#include <cassert> #include <cassert>
#include <cstdlib> // for abort() #include <cstdlib> // for abort()
#define MUTEX_NAMESPACE glog_internal_namespace_ #define MUTEX_NAMESPACE glog_internal_namespace_
@ -170,16 +171,16 @@ class Mutex {
inline void Lock(); // Block if needed until free then acquire exclusively inline void Lock(); // Block if needed until free then acquire exclusively
inline void Unlock(); // Release a lock acquired via Lock() inline void Unlock(); // Release a lock acquired via Lock()
#ifdef GMUTEX_TRYLOCK #ifdef GMUTEX_TRYLOCK
inline bool TryLock(); // If free, Lock() and return true, else return false inline bool TryLock(); // If free, Lock() and return true, else return false
#endif #endif
// Note that on systems that don't support read-write locks, these may // Note that on systems that don't support read-write locks, these may
// be implemented as synonyms to Lock() and Unlock(). So you can use // be implemented as synonyms to Lock() and Unlock(). So you can use
// these for efficiency, but don't use them anyplace where being able // these for efficiency, but don't use them anyplace where being able
// to do shared reads is necessary to avoid deadlock. // to do shared reads is necessary to avoid deadlock.
inline void ReaderLock(); // Block until free or shared then acquire a share inline void ReaderLock(); // Block until free or shared then acquire a share
inline void ReaderUnlock(); // Release a read share of this Mutex inline void ReaderUnlock(); // Release a read share of this Mutex
inline void WriterLock() { Lock(); } // Acquire an exclusive lock inline void WriterLock() { Lock(); } // Acquire an exclusive lock
inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
// TODO(hamaji): Do nothing, implement correctly. // TODO(hamaji): Do nothing, implement correctly.
inline void AssertHeld() {} inline void AssertHeld() {}
@ -194,10 +195,10 @@ class Mutex {
inline void SetIsSafe() { is_safe_ = true; } inline void SetIsSafe() { is_safe_ = true; }
// Catch the error of writing Mutex when intending MutexLock. // Catch the error of writing Mutex when intending MutexLock.
explicit Mutex(Mutex * /*ignored*/) {} explicit Mutex(Mutex* /*ignored*/) {}
// Disallow "evil" constructors // Disallow "evil" constructors
Mutex(const Mutex &) = delete; Mutex(const Mutex&) = delete;
void operator=(const Mutex &) = delete; void operator=(const Mutex&) = delete;
}; };
// Now the implementation of Mutex for various systems // Now the implementation of Mutex for various systems
@ -213,71 +214,86 @@ class Mutex {
// we do nothing, for efficiency. That's why everything is in an // we do nothing, for efficiency. That's why everything is in an
// assert. // assert.
Mutex::Mutex() : mutex_(0) { } Mutex::Mutex() : mutex_(0) {}
Mutex::~Mutex() { assert(mutex_ == 0); } Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); } void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); } void Mutex::Unlock() { assert(mutex_++ == -1); }
#ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } bool Mutex::TryLock() {
#endif if (mutex_) return false;
void Mutex::ReaderLock() { assert(++mutex_ > 0); } Lock();
return true;
}
# endif
void Mutex::ReaderLock() { assert(++mutex_ > 0); }
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(_WIN32) || defined(__CYGWIN__) #elif defined(_WIN32) || defined(__CYGWIN__)
Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); } Mutex::Mutex() {
Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } InitializeCriticalSection(&mutex_);
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } SetIsSafe();
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } }
#ifdef GMUTEX_TRYLOCK Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
bool Mutex::TryLock() { return is_safe_ ? void Mutex::Lock() {
TryEnterCriticalSection(&mutex_) != 0 : true; } if (is_safe_) EnterCriticalSection(&mutex_);
#endif }
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks void Mutex::Unlock() {
if (is_safe_) LeaveCriticalSection(&mutex_);
}
# ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() {
return is_safe_ ? TryEnterCriticalSection(&mutex_) != 0 : true;
}
# endif
void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks
void Mutex::ReaderUnlock() { Unlock(); } void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ # define SAFE_PTHREAD(fncall) \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \ do { /* run fncall if is_safe_ is true */ \
} while (0) if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() { Mutex::Mutex() {
SetIsSafe(); SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, nullptr) != 0) abort(); if (is_safe_ && pthread_rwlock_init(&mutex_, nullptr) != 0) abort();
} }
Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); } Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ? bool Mutex::TryLock() {
pthread_rwlock_trywrlock(&mutex_) == 0 : return is_safe_ ? pthread_rwlock_trywrlock(&mutex_) == 0 : true;
true; } }
#endif # endif
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#undef SAFE_PTHREAD # undef SAFE_PTHREAD
#elif defined(HAVE_PTHREAD) #elif defined(HAVE_PTHREAD)
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ # define SAFE_PTHREAD(fncall) \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \ do { /* run fncall if is_safe_ is true */ \
} while (0) if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
Mutex::Mutex() { Mutex::Mutex() {
SetIsSafe(); SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, nullptr) != 0) abort(); if (is_safe_ && pthread_mutex_init(&mutex_, nullptr) != 0) abort();
} }
Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
#ifdef GMUTEX_TRYLOCK # ifdef GMUTEX_TRYLOCK
bool Mutex::TryLock() { return is_safe_ ? bool Mutex::TryLock() {
pthread_mutex_trylock(&mutex_) == 0 : true; } return is_safe_ ? pthread_mutex_trylock(&mutex_) == 0 : true;
#endif }
void Mutex::ReaderLock() { Lock(); } # endif
void Mutex::ReaderLock() { Lock(); }
void Mutex::ReaderUnlock() { Unlock(); } void Mutex::ReaderUnlock() { Unlock(); }
#undef SAFE_PTHREAD # undef SAFE_PTHREAD
#endif #endif
@ -287,36 +303,39 @@ void Mutex::ReaderUnlock() { Unlock(); }
// MutexLock(mu) acquires mu when constructed and releases it when destroyed. // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
class MutexLock { class MutexLock {
public: public:
explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } explicit MutexLock(Mutex* mu) : mu_(mu) { mu_->Lock(); }
~MutexLock() { mu_->Unlock(); } ~MutexLock() { mu_->Unlock(); }
private: private:
Mutex * const mu_; Mutex* const mu_;
// Disallow "evil" constructors // Disallow "evil" constructors
MutexLock(const MutexLock &) = delete; MutexLock(const MutexLock&) = delete;
void operator=(const MutexLock &) = delete; void operator=(const MutexLock&) = delete;
}; };
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks // ReaderMutexLock and WriterMutexLock do the same, for rwlocks
class ReaderMutexLock { class ReaderMutexLock {
public: public:
explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } explicit ReaderMutexLock(Mutex* mu) : mu_(mu) { mu_->ReaderLock(); }
~ReaderMutexLock() { mu_->ReaderUnlock(); } ~ReaderMutexLock() { mu_->ReaderUnlock(); }
private: private:
Mutex * const mu_; Mutex* const mu_;
// Disallow "evil" constructors // Disallow "evil" constructors
ReaderMutexLock(const ReaderMutexLock &) = delete; ReaderMutexLock(const ReaderMutexLock&) = delete;
void operator=(const ReaderMutexLock &) = delete; void operator=(const ReaderMutexLock&) = delete;
}; };
class WriterMutexLock { class WriterMutexLock {
public: public:
explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } explicit WriterMutexLock(Mutex* mu) : mu_(mu) { mu_->WriterLock(); }
~WriterMutexLock() { mu_->WriterUnlock(); } ~WriterMutexLock() { mu_->WriterUnlock(); }
private: private:
Mutex * const mu_; Mutex* const mu_;
// Disallow "evil" constructors // Disallow "evil" constructors
WriterMutexLock(const WriterMutexLock &) = delete; WriterMutexLock(const WriterMutexLock&) = delete;
void operator=(const WriterMutexLock &) = delete; void operator=(const WriterMutexLock&) = delete;
}; };
// Catch bug where variable name is omitted, e.g. MutexLock (&mu); // Catch bug where variable name is omitted, e.g. MutexLock (&mu);
@ -330,4 +349,4 @@ using namespace MUTEX_NAMESPACE;
#undef MUTEX_NAMESPACE #undef MUTEX_NAMESPACE
#endif /* #define GOOGLE_MUTEX_H__ */ #endif /* #define GOOGLE_MUTEX_H__ */

View File

@ -33,14 +33,14 @@
#include "googletest.h" #include "googletest.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
#ifdef HAVE_LIB_GMOCK #ifdef HAVE_LIB_GMOCK
#include <gmock/gmock.h> # include <gmock/gmock.h>
#include "mock-log.h" # include "mock-log.h"
// Introduce several symbols from gmock. // Introduce several symbols from gmock.
using google::glog_testing::ScopedMockLog; using google::glog_testing::ScopedMockLog;
using testing::_; using testing::_;
@ -65,7 +65,7 @@ TEST(CleanImmediately, logging) {
google::DisableLogCleaner(); google::DisableLogCleaner();
} }
int main(int argc, char **argv) { int main(int argc, char** argv) {
FLAGS_colorlogtostderr = false; FLAGS_colorlogtostderr = false;
FLAGS_timestamp_in_logfile_name = true; FLAGS_timestamp_in_logfile_name = true;
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS

View File

@ -33,14 +33,14 @@
#include "googletest.h" #include "googletest.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
#ifdef HAVE_LIB_GMOCK #ifdef HAVE_LIB_GMOCK
#include <gmock/gmock.h> # include <gmock/gmock.h>
#include "mock-log.h" # include "mock-log.h"
// Introduce several symbols from gmock. // Introduce several symbols from gmock.
using google::glog_testing::ScopedMockLog; using google::glog_testing::ScopedMockLog;
using testing::_; using testing::_;
@ -70,7 +70,7 @@ TEST(CleanImmediatelyWithAbsolutePrefix, logging) {
google::DisableLogCleaner(); google::DisableLogCleaner();
} }
int main(int argc, char **argv) { int main(int argc, char** argv) {
FLAGS_colorlogtostderr = false; FLAGS_colorlogtostderr = false;
FLAGS_timestamp_in_logfile_name = true; FLAGS_timestamp_in_logfile_name = true;
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS

View File

@ -33,14 +33,14 @@
#include "googletest.h" #include "googletest.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
#ifdef HAVE_LIB_GMOCK #ifdef HAVE_LIB_GMOCK
#include <gmock/gmock.h> # include <gmock/gmock.h>
#include "mock-log.h" # include "mock-log.h"
// Introduce several symbols from gmock. // Introduce several symbols from gmock.
using google::glog_testing::ScopedMockLog; using google::glog_testing::ScopedMockLog;
using testing::_; using testing::_;
@ -66,7 +66,7 @@ TEST(CleanImmediatelyWithRelativePrefix, logging) {
google::DisableLogCleaner(); google::DisableLogCleaner();
} }
int main(int argc, char **argv) { int main(int argc, char** argv) {
FLAGS_colorlogtostderr = false; FLAGS_colorlogtostderr = false;
FLAGS_timestamp_in_logfile_name = true; FLAGS_timestamp_in_logfile_name = true;
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS

View File

@ -43,15 +43,15 @@
#include "utilities.h" #include "utilities.h"
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
#include <dbghelp.h> # include <dbghelp.h>
#endif #endif
namespace google { namespace google {
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
struct AbbrevPair { struct AbbrevPair {
const char *abbrev; const char* abbrev;
const char *real_name; const char* real_name;
}; };
// List of operators from Itanium C++ ABI. // List of operators from Itanium C++ ABI.
@ -102,11 +102,11 @@ static const AbbrevPair kSubstitutionList[] = {
// State needed for demangling. // State needed for demangling.
struct State { struct State {
const char *mangled_cur; // Cursor of mangled name. const char* mangled_cur; // Cursor of mangled name.
char *out_cur; // Cursor of output string. char* out_cur; // Cursor of output string.
const char *out_begin; // Beginning of output string. const char* out_begin; // Beginning of output string.
const char *out_end; // End of output string. const char* out_end; // End of output string.
const char *prev_name; // For constructors/destructors. const char* prev_name; // For constructors/destructors.
ssize_t prev_name_length; // For constructors/destructors. ssize_t prev_name_length; // For constructors/destructors.
short nest_level; // For nested names. short nest_level; // For nested names.
bool append; // Append flag. bool append; // Append flag.
@ -118,7 +118,7 @@ struct State {
// We don't use strlen() in libc since it's not guaranteed to be async // We don't use strlen() in libc since it's not guaranteed to be async
// signal safe. // signal safe.
static size_t StrLen(const char *str) { static size_t StrLen(const char* str) {
size_t len = 0; size_t len = 0;
while (*str != '\0') { while (*str != '\0') {
++str; ++str;
@ -128,7 +128,7 @@ static size_t StrLen(const char *str) {
} }
// Returns true if "str" has at least "n" characters remaining. // Returns true if "str" has at least "n" characters remaining.
static bool AtLeastNumCharsRemaining(const char *str, ssize_t n) { static bool AtLeastNumCharsRemaining(const char* str, ssize_t n) {
for (ssize_t i = 0; i < n; ++i) { for (ssize_t i = 0; i < n; ++i) {
if (str[i] == '\0') { if (str[i] == '\0') {
return false; return false;
@ -138,17 +138,16 @@ static bool AtLeastNumCharsRemaining(const char *str, ssize_t n) {
} }
// Returns true if "str" has "prefix" as a prefix. // Returns true if "str" has "prefix" as a prefix.
static bool StrPrefix(const char *str, const char *prefix) { static bool StrPrefix(const char* str, const char* prefix) {
size_t i = 0; size_t i = 0;
while (str[i] != '\0' && prefix[i] != '\0' && while (str[i] != '\0' && prefix[i] != '\0' && str[i] == prefix[i]) {
str[i] == prefix[i]) {
++i; ++i;
} }
return prefix[i] == '\0'; // Consumed everything in "prefix". return prefix[i] == '\0'; // Consumed everything in "prefix".
} }
static void InitState(State *state, const char *mangled, static void InitState(State* state, const char* mangled, char* out,
char *out, size_t out_size) { size_t out_size) {
state->mangled_cur = mangled; state->mangled_cur = mangled;
state->out_cur = out; state->out_cur = out;
state->out_begin = out; state->out_begin = out;
@ -166,7 +165,7 @@ static void InitState(State *state, const char *mangled,
// Returns true and advances "mangled_cur" if we find "one_char_token" // Returns true and advances "mangled_cur" if we find "one_char_token"
// at "mangled_cur" position. It is assumed that "one_char_token" does // at "mangled_cur" position. It is assumed that "one_char_token" does
// not contain '\0'. // not contain '\0'.
static bool ParseOneCharToken(State *state, const char one_char_token) { static bool ParseOneCharToken(State* state, const char one_char_token) {
if (state->mangled_cur[0] == one_char_token) { if (state->mangled_cur[0] == one_char_token) {
++state->mangled_cur; ++state->mangled_cur;
return true; return true;
@ -177,7 +176,7 @@ static bool ParseOneCharToken(State *state, const char one_char_token) {
// Returns true and advances "mangled_cur" if we find "two_char_token" // Returns true and advances "mangled_cur" if we find "two_char_token"
// at "mangled_cur" position. It is assumed that "two_char_token" does // at "mangled_cur" position. It is assumed that "two_char_token" does
// not contain '\0'. // not contain '\0'.
static bool ParseTwoCharToken(State *state, const char *two_char_token) { static bool ParseTwoCharToken(State* state, const char* two_char_token) {
if (state->mangled_cur[0] == two_char_token[0] && if (state->mangled_cur[0] == two_char_token[0] &&
state->mangled_cur[1] == two_char_token[1]) { state->mangled_cur[1] == two_char_token[1]) {
state->mangled_cur += 2; state->mangled_cur += 2;
@ -188,8 +187,8 @@ static bool ParseTwoCharToken(State *state, const char *two_char_token) {
// Returns true and advances "mangled_cur" if we find any character in // Returns true and advances "mangled_cur" if we find any character in
// "char_class" at "mangled_cur" position. // "char_class" at "mangled_cur" position.
static bool ParseCharClass(State *state, const char *char_class) { static bool ParseCharClass(State* state, const char* char_class) {
const char *p = char_class; const char* p = char_class;
for (; *p != '\0'; ++p) { for (; *p != '\0'; ++p) {
if (state->mangled_cur[0] == *p) { if (state->mangled_cur[0] == *p) {
++state->mangled_cur; ++state->mangled_cur;
@ -200,13 +199,11 @@ static bool ParseCharClass(State *state, const char *char_class) {
} }
// This function is used for handling an optional non-terminal. // This function is used for handling an optional non-terminal.
static bool Optional(bool) { static bool Optional(bool) { return true; }
return true;
}
// This function is used for handling <non-terminal>+ syntax. // This function is used for handling <non-terminal>+ syntax.
using ParseFunc = bool (*)(State *); using ParseFunc = bool (*)(State*);
static bool OneOrMore(ParseFunc parse_func, State *state) { static bool OneOrMore(ParseFunc parse_func, State* state) {
if (parse_func(state)) { if (parse_func(state)) {
while (parse_func(state)) { while (parse_func(state)) {
} }
@ -219,7 +216,7 @@ static bool OneOrMore(ParseFunc parse_func, State *state) {
// always returns true and must be followed by a termination token or a // always returns true and must be followed by a termination token or a
// terminating sequence not handled by parse_func (e.g. // terminating sequence not handled by parse_func (e.g.
// ParseOneCharToken(state, 'E')). // ParseOneCharToken(state, 'E')).
static bool ZeroOrMore(ParseFunc parse_func, State *state) { static bool ZeroOrMore(ParseFunc parse_func, State* state) {
while (parse_func(state)) { while (parse_func(state)) {
} }
return true; return true;
@ -228,7 +225,7 @@ static bool ZeroOrMore(ParseFunc parse_func, State *state) {
// Append "str" at "out_cur". If there is an overflow, "overflowed" // Append "str" at "out_cur". If there is an overflow, "overflowed"
// is set to true for later use. The output string is ensured to // is set to true for later use. The output string is ensured to
// always terminate with '\0' as long as there is no overflow. // always terminate with '\0' as long as there is no overflow.
static void Append(State *state, const char * const str, ssize_t length) { static void Append(State* state, const char* const str, ssize_t length) {
if (state->out_cur == nullptr) { if (state->out_cur == nullptr) {
state->overflowed = true; state->overflowed = true;
return; return;
@ -248,23 +245,19 @@ static void Append(State *state, const char * const str, ssize_t length) {
} }
// We don't use equivalents in libc to avoid locale issues. // We don't use equivalents in libc to avoid locale issues.
static bool IsLower(char c) { static bool IsLower(char c) { return c >= 'a' && c <= 'z'; }
return c >= 'a' && c <= 'z';
}
static bool IsAlpha(char c) { static bool IsAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
} }
static bool IsDigit(char c) { static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
return c >= '0' && c <= '9';
}
// Returns true if "str" is a function clone suffix. These suffixes are used // Returns true if "str" is a function clone suffix. These suffixes are used
// by GCC 4.5.x and later versions to indicate functions which have been // by GCC 4.5.x and later versions to indicate functions which have been
// cloned during optimization. We treat any sequence (.<alpha>+.<digit>+)+ as // cloned during optimization. We treat any sequence (.<alpha>+.<digit>+)+ as
// a function clone suffix. // a function clone suffix.
static bool IsFunctionCloneSuffix(const char *str) { static bool IsFunctionCloneSuffix(const char* str) {
size_t i = 0; size_t i = 0;
while (str[i] != '\0') { while (str[i] != '\0') {
// Consume a single .<alpha>+.<digit>+ sequence. // Consume a single .<alpha>+.<digit>+ sequence.
@ -288,12 +281,12 @@ static bool IsFunctionCloneSuffix(const char *str) {
// Append "str" with some tweaks, iff "append" state is true. // Append "str" with some tweaks, iff "append" state is true.
// Returns true so that it can be placed in "if" conditions. // Returns true so that it can be placed in "if" conditions.
static void MaybeAppendWithLength(State *state, const char * const str, static void MaybeAppendWithLength(State* state, const char* const str,
ssize_t length) { ssize_t length) {
if (state->append && length > 0) { if (state->append && length > 0) {
// Append a space if the output buffer ends with '<' and "str" // Append a space if the output buffer ends with '<' and "str"
// starts with '<' to avoid <<<. // starts with '<' to avoid <<<.
if (str[0] == '<' && state->out_begin < state->out_cur && if (str[0] == '<' && state->out_begin < state->out_cur &&
state->out_cur[-1] == '<') { state->out_cur[-1] == '<') {
Append(state, " ", 1); Append(state, " ", 1);
} }
@ -307,7 +300,7 @@ static void MaybeAppendWithLength(State *state, const char * const str,
} }
// A convenient wrapper around MaybeAppendWithLength(). // A convenient wrapper around MaybeAppendWithLength().
static bool MaybeAppend(State *state, const char * const str) { static bool MaybeAppend(State* state, const char* const str) {
if (state->append) { if (state->append) {
size_t length = StrLen(str); size_t length = StrLen(str);
MaybeAppendWithLength(state, str, static_cast<ssize_t>(length)); MaybeAppendWithLength(state, str, static_cast<ssize_t>(length));
@ -316,45 +309,45 @@ static bool MaybeAppend(State *state, const char * const str) {
} }
// This function is used for handling nested names. // This function is used for handling nested names.
static bool EnterNestedName(State *state) { static bool EnterNestedName(State* state) {
state->nest_level = 0; state->nest_level = 0;
return true; return true;
} }
// This function is used for handling nested names. // This function is used for handling nested names.
static bool LeaveNestedName(State *state, short prev_value) { static bool LeaveNestedName(State* state, short prev_value) {
state->nest_level = prev_value; state->nest_level = prev_value;
return true; return true;
} }
// Disable the append mode not to print function parameters, etc. // Disable the append mode not to print function parameters, etc.
static bool DisableAppend(State *state) { static bool DisableAppend(State* state) {
state->append = false; state->append = false;
return true; return true;
} }
// Restore the append mode to the previous state. // Restore the append mode to the previous state.
static bool RestoreAppend(State *state, bool prev_value) { static bool RestoreAppend(State* state, bool prev_value) {
state->append = prev_value; state->append = prev_value;
return true; return true;
} }
// Increase the nest level for nested names. // Increase the nest level for nested names.
static void MaybeIncreaseNestLevel(State *state) { static void MaybeIncreaseNestLevel(State* state) {
if (state->nest_level > -1) { if (state->nest_level > -1) {
++state->nest_level; ++state->nest_level;
} }
} }
// Appends :: for nested names if necessary. // Appends :: for nested names if necessary.
static void MaybeAppendSeparator(State *state) { static void MaybeAppendSeparator(State* state) {
if (state->nest_level >= 1) { if (state->nest_level >= 1) {
MaybeAppend(state, "::"); MaybeAppend(state, "::");
} }
} }
// Cancel the last separator if necessary. // Cancel the last separator if necessary.
static void MaybeCancelLastSeparator(State *state) { static void MaybeCancelLastSeparator(State* state) {
if (state->nest_level >= 1 && state->append && if (state->nest_level >= 1 && state->append &&
state->out_begin <= state->out_cur - 2) { state->out_begin <= state->out_cur - 2) {
state->out_cur -= 2; state->out_cur -= 2;
@ -364,7 +357,7 @@ static void MaybeCancelLastSeparator(State *state) {
// Returns true if the identifier of the given length pointed to by // Returns true if the identifier of the given length pointed to by
// "mangled_cur" is anonymous namespace. // "mangled_cur" is anonymous namespace.
static bool IdentifierIsAnonymousNamespace(State *state, ssize_t length) { static bool IdentifierIsAnonymousNamespace(State* state, ssize_t length) {
static const char anon_prefix[] = "_GLOBAL__N_"; static const char anon_prefix[] = "_GLOBAL__N_";
return (length > static_cast<ssize_t>(sizeof(anon_prefix)) - return (length > static_cast<ssize_t>(sizeof(anon_prefix)) -
1 && // Should be longer. 1 && // Should be longer.
@ -372,45 +365,45 @@ static bool IdentifierIsAnonymousNamespace(State *state, ssize_t length) {
} }
// Forward declarations of our parsing functions. // Forward declarations of our parsing functions.
static bool ParseMangledName(State *state); static bool ParseMangledName(State* state);
static bool ParseEncoding(State *state); static bool ParseEncoding(State* state);
static bool ParseName(State *state); static bool ParseName(State* state);
static bool ParseUnscopedName(State *state); static bool ParseUnscopedName(State* state);
static bool ParseUnscopedTemplateName(State *state); static bool ParseUnscopedTemplateName(State* state);
static bool ParseNestedName(State *state); static bool ParseNestedName(State* state);
static bool ParsePrefix(State *state); static bool ParsePrefix(State* state);
static bool ParseUnqualifiedName(State *state); static bool ParseUnqualifiedName(State* state);
static bool ParseSourceName(State *state); static bool ParseSourceName(State* state);
static bool ParseLocalSourceName(State *state); static bool ParseLocalSourceName(State* state);
static bool ParseNumber(State *state, int *number_out); static bool ParseNumber(State* state, int* number_out);
static bool ParseFloatNumber(State *state); static bool ParseFloatNumber(State* state);
static bool ParseSeqId(State *state); static bool ParseSeqId(State* state);
static bool ParseIdentifier(State *state, ssize_t length); static bool ParseIdentifier(State* state, ssize_t length);
static bool ParseAbiTags(State *state); static bool ParseAbiTags(State* state);
static bool ParseAbiTag(State *state); static bool ParseAbiTag(State* state);
static bool ParseOperatorName(State *state); static bool ParseOperatorName(State* state);
static bool ParseSpecialName(State *state); static bool ParseSpecialName(State* state);
static bool ParseCallOffset(State *state); static bool ParseCallOffset(State* state);
static bool ParseNVOffset(State *state); static bool ParseNVOffset(State* state);
static bool ParseVOffset(State *state); static bool ParseVOffset(State* state);
static bool ParseCtorDtorName(State *state); static bool ParseCtorDtorName(State* state);
static bool ParseType(State *state); static bool ParseType(State* state);
static bool ParseCVQualifiers(State *state); static bool ParseCVQualifiers(State* state);
static bool ParseBuiltinType(State *state); static bool ParseBuiltinType(State* state);
static bool ParseFunctionType(State *state); static bool ParseFunctionType(State* state);
static bool ParseBareFunctionType(State *state); static bool ParseBareFunctionType(State* state);
static bool ParseClassEnumType(State *state); static bool ParseClassEnumType(State* state);
static bool ParseArrayType(State *state); static bool ParseArrayType(State* state);
static bool ParsePointerToMemberType(State *state); static bool ParsePointerToMemberType(State* state);
static bool ParseTemplateParam(State *state); static bool ParseTemplateParam(State* state);
static bool ParseTemplateTemplateParam(State *state); static bool ParseTemplateTemplateParam(State* state);
static bool ParseTemplateArgs(State *state); static bool ParseTemplateArgs(State* state);
static bool ParseTemplateArg(State *state); static bool ParseTemplateArg(State* state);
static bool ParseExpression(State *state); static bool ParseExpression(State* state);
static bool ParseExprPrimary(State *state); static bool ParseExprPrimary(State* state);
static bool ParseLocalName(State *state); static bool ParseLocalName(State* state);
static bool ParseDiscriminator(State *state); static bool ParseDiscriminator(State* state);
static bool ParseSubstitution(State *state); static bool ParseSubstitution(State* state);
// Implementation note: the following code is a straightforward // Implementation note: the following code is a straightforward
// translation of the Itanium C++ ABI defined in BNF with a couple of // translation of the Itanium C++ ABI defined in BNF with a couple of
@ -443,14 +436,14 @@ static bool ParseSubstitution(State *state);
// <http://www.codesourcery.com/cxx-abi/abi.html#mangling> // <http://www.codesourcery.com/cxx-abi/abi.html#mangling>
// <mangled-name> ::= _Z <encoding> // <mangled-name> ::= _Z <encoding>
static bool ParseMangledName(State *state) { static bool ParseMangledName(State* state) {
return ParseTwoCharToken(state, "_Z") && ParseEncoding(state); return ParseTwoCharToken(state, "_Z") && ParseEncoding(state);
} }
// <encoding> ::= <(function) name> <bare-function-type> // <encoding> ::= <(function) name> <bare-function-type>
// ::= <(data) name> // ::= <(data) name>
// ::= <special-name> // ::= <special-name>
static bool ParseEncoding(State *state) { static bool ParseEncoding(State* state) {
State copy = *state; State copy = *state;
if (ParseName(state) && ParseBareFunctionType(state)) { if (ParseName(state) && ParseBareFunctionType(state)) {
return true; return true;
@ -467,14 +460,13 @@ static bool ParseEncoding(State *state) {
// ::= <unscoped-template-name> <template-args> // ::= <unscoped-template-name> <template-args>
// ::= <unscoped-name> // ::= <unscoped-name>
// ::= <local-name> // ::= <local-name>
static bool ParseName(State *state) { static bool ParseName(State* state) {
if (ParseNestedName(state) || ParseLocalName(state)) { if (ParseNestedName(state) || ParseLocalName(state)) {
return true; return true;
} }
State copy = *state; State copy = *state;
if (ParseUnscopedTemplateName(state) && if (ParseUnscopedTemplateName(state) && ParseTemplateArgs(state)) {
ParseTemplateArgs(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -488,14 +480,13 @@ static bool ParseName(State *state) {
// <unscoped-name> ::= <unqualified-name> // <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> // ::= St <unqualified-name>
static bool ParseUnscopedName(State *state) { static bool ParseUnscopedName(State* state) {
if (ParseUnqualifiedName(state)) { if (ParseUnqualifiedName(state)) {
return true; return true;
} }
State copy = *state; State copy = *state;
if (ParseTwoCharToken(state, "St") && if (ParseTwoCharToken(state, "St") && MaybeAppend(state, "std::") &&
MaybeAppend(state, "std::") &&
ParseUnqualifiedName(state)) { ParseUnqualifiedName(state)) {
return true; return true;
} }
@ -505,18 +496,16 @@ static bool ParseUnscopedName(State *state) {
// <unscoped-template-name> ::= <unscoped-name> // <unscoped-template-name> ::= <unscoped-name>
// ::= <substitution> // ::= <substitution>
static bool ParseUnscopedTemplateName(State *state) { static bool ParseUnscopedTemplateName(State* state) {
return ParseUnscopedName(state) || ParseSubstitution(state); return ParseUnscopedName(state) || ParseSubstitution(state);
} }
// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
static bool ParseNestedName(State *state) { static bool ParseNestedName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'N') && if (ParseOneCharToken(state, 'N') && EnterNestedName(state) &&
EnterNestedName(state) && Optional(ParseCVQualifiers(state)) && ParsePrefix(state) &&
Optional(ParseCVQualifiers(state)) &&
ParsePrefix(state) &&
LeaveNestedName(state, copy.nest_level) && LeaveNestedName(state, copy.nest_level) &&
ParseOneCharToken(state, 'E')) { ParseOneCharToken(state, 'E')) {
return true; return true;
@ -536,12 +525,11 @@ static bool ParseNestedName(State *state) {
// <template-prefix> ::= <prefix> <(template) unqualified-name> // <template-prefix> ::= <prefix> <(template) unqualified-name>
// ::= <template-param> // ::= <template-param>
// ::= <substitution> // ::= <substitution>
static bool ParsePrefix(State *state) { static bool ParsePrefix(State* state) {
bool has_something = false; bool has_something = false;
while (true) { while (true) {
MaybeAppendSeparator(state); MaybeAppendSeparator(state);
if (ParseTemplateParam(state) || if (ParseTemplateParam(state) || ParseSubstitution(state) ||
ParseSubstitution(state) ||
ParseUnscopedName(state)) { ParseUnscopedName(state)) {
has_something = true; has_something = true;
MaybeIncreaseNestLevel(state); MaybeIncreaseNestLevel(state);
@ -561,15 +549,14 @@ static bool ParsePrefix(State *state) {
// ::= <ctor-dtor-name> // ::= <ctor-dtor-name>
// ::= <source-name> [<abi-tags>] // ::= <source-name> [<abi-tags>]
// ::= <local-source-name> [<abi-tags>] // ::= <local-source-name> [<abi-tags>]
static bool ParseUnqualifiedName(State *state) { static bool ParseUnqualifiedName(State* state) {
return (ParseOperatorName(state) || return (ParseOperatorName(state) || ParseCtorDtorName(state) ||
ParseCtorDtorName(state) ||
(ParseSourceName(state) && Optional(ParseAbiTags(state))) || (ParseSourceName(state) && Optional(ParseAbiTags(state))) ||
(ParseLocalSourceName(state) && Optional(ParseAbiTags(state)))); (ParseLocalSourceName(state) && Optional(ParseAbiTags(state))));
} }
// <source-name> ::= <positive length number> <identifier> // <source-name> ::= <positive length number> <identifier>
static bool ParseSourceName(State *state) { static bool ParseSourceName(State* state) {
State copy = *state; State copy = *state;
int length = -1; int length = -1;
if (ParseNumber(state, &length) && ParseIdentifier(state, length)) { if (ParseNumber(state, &length) && ParseIdentifier(state, length)) {
@ -584,7 +571,7 @@ static bool ParseSourceName(State *state) {
// References: // References:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
// http://gcc.gnu.org/viewcvs?view=rev&revision=124467 // http://gcc.gnu.org/viewcvs?view=rev&revision=124467
static bool ParseLocalSourceName(State *state) { static bool ParseLocalSourceName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'L') && ParseSourceName(state) && if (ParseOneCharToken(state, 'L') && ParseSourceName(state) &&
Optional(ParseDiscriminator(state))) { Optional(ParseDiscriminator(state))) {
@ -597,15 +584,15 @@ static bool ParseLocalSourceName(State *state) {
// <number> ::= [n] <non-negative decimal integer> // <number> ::= [n] <non-negative decimal integer>
// If "number_out" is non-null, then *number_out is set to the value of the // If "number_out" is non-null, then *number_out is set to the value of the
// parsed number on success. // parsed number on success.
static bool ParseNumber(State *state, int *number_out) { static bool ParseNumber(State* state, int* number_out) {
int sign = 1; int sign = 1;
if (ParseOneCharToken(state, 'n')) { if (ParseOneCharToken(state, 'n')) {
sign = -1; sign = -1;
} }
const char *p = state->mangled_cur; const char* p = state->mangled_cur;
int number = 0; int number = 0;
constexpr int int_max_by_10 = std::numeric_limits<int>::max() / 10; constexpr int int_max_by_10 = std::numeric_limits<int>::max() / 10;
for (;*p != '\0'; ++p) { for (; *p != '\0'; ++p) {
if (IsDigit(*p)) { if (IsDigit(*p)) {
// Prevent signed integer overflow when multiplying // Prevent signed integer overflow when multiplying
if (number > int_max_by_10) { if (number > int_max_by_10) {
@ -637,9 +624,9 @@ static bool ParseNumber(State *state, int *number_out) {
// Floating-point literals are encoded using a fixed-length lowercase // Floating-point literals are encoded using a fixed-length lowercase
// hexadecimal string. // hexadecimal string.
static bool ParseFloatNumber(State *state) { static bool ParseFloatNumber(State* state) {
const char *p = state->mangled_cur; const char* p = state->mangled_cur;
for (;*p != '\0'; ++p) { for (; *p != '\0'; ++p) {
if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) { if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) {
break; break;
} }
@ -653,9 +640,9 @@ static bool ParseFloatNumber(State *state) {
// The <seq-id> is a sequence number in base 36, // The <seq-id> is a sequence number in base 36,
// using digits and upper case letters // using digits and upper case letters
static bool ParseSeqId(State *state) { static bool ParseSeqId(State* state) {
const char *p = state->mangled_cur; const char* p = state->mangled_cur;
for (;*p != '\0'; ++p) { for (; *p != '\0'; ++p) {
if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) { if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) {
break; break;
} }
@ -668,9 +655,8 @@ static bool ParseSeqId(State *state) {
} }
// <identifier> ::= <unqualified source code identifier> (of given length) // <identifier> ::= <unqualified source code identifier> (of given length)
static bool ParseIdentifier(State *state, ssize_t length) { static bool ParseIdentifier(State* state, ssize_t length) {
if (length == -1 || if (length == -1 || !AtLeastNumCharsRemaining(state->mangled_cur, length)) {
!AtLeastNumCharsRemaining(state->mangled_cur, length)) {
return false; return false;
} }
if (IdentifierIsAnonymousNamespace(state, length)) { if (IdentifierIsAnonymousNamespace(state, length)) {
@ -687,7 +673,7 @@ static bool ParseIdentifier(State *state, ssize_t length) {
} }
// <abi-tags> ::= <abi-tag> [<abi-tags>] // <abi-tags> ::= <abi-tag> [<abi-tags>]
static bool ParseAbiTags(State *state) { static bool ParseAbiTags(State* state) {
State copy = *state; State copy = *state;
DisableAppend(state); DisableAppend(state);
if (OneOrMore(ParseAbiTag, state)) { if (OneOrMore(ParseAbiTag, state)) {
@ -699,23 +685,21 @@ static bool ParseAbiTags(State *state) {
} }
// <abi-tag> ::= B <source-name> // <abi-tag> ::= B <source-name>
static bool ParseAbiTag(State *state) { static bool ParseAbiTag(State* state) {
return ParseOneCharToken(state, 'B') && ParseSourceName(state); return ParseOneCharToken(state, 'B') && ParseSourceName(state);
} }
// <operator-name> ::= nw, and other two letters cases // <operator-name> ::= nw, and other two letters cases
// ::= cv <type> # (cast) // ::= cv <type> # (cast)
// ::= v <digit> <source-name> # vendor extended operator // ::= v <digit> <source-name> # vendor extended operator
static bool ParseOperatorName(State *state) { static bool ParseOperatorName(State* state) {
if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) { if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) {
return false; return false;
} }
// First check with "cv" (cast) case. // First check with "cv" (cast) case.
State copy = *state; State copy = *state;
if (ParseTwoCharToken(state, "cv") && if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") &&
MaybeAppend(state, "operator ") && EnterNestedName(state) && ParseType(state) &&
EnterNestedName(state) &&
ParseType(state) &&
LeaveNestedName(state, copy.nest_level)) { LeaveNestedName(state, copy.nest_level)) {
return true; return true;
} }
@ -730,12 +714,11 @@ static bool ParseOperatorName(State *state) {
// Other operator names should start with a lower alphabet followed // Other operator names should start with a lower alphabet followed
// by a lower/upper alphabet. // by a lower/upper alphabet.
if (!(IsLower(state->mangled_cur[0]) && if (!(IsLower(state->mangled_cur[0]) && IsAlpha(state->mangled_cur[1]))) {
IsAlpha(state->mangled_cur[1]))) {
return false; return false;
} }
// We may want to perform a binary search if we really need speed. // We may want to perform a binary search if we really need speed.
const AbbrevPair *p; const AbbrevPair* p;
for (p = kOperatorList; p->abbrev != nullptr; ++p) { for (p = kOperatorList; p->abbrev != nullptr; ++p) {
if (state->mangled_cur[0] == p->abbrev[0] && if (state->mangled_cur[0] == p->abbrev[0] &&
state->mangled_cur[1] == p->abbrev[1]) { state->mangled_cur[1] == p->abbrev[1]) {
@ -769,10 +752,9 @@ static bool ParseOperatorName(State *state) {
// //
// Note: we don't care much about them since they don't appear in // Note: we don't care much about them since they don't appear in
// stack traces. The are special data. // stack traces. The are special data.
static bool ParseSpecialName(State *state) { static bool ParseSpecialName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'T') && if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
ParseCharClass(state, "VTIS") &&
ParseType(state)) { ParseType(state)) {
return true; return true;
} }
@ -784,8 +766,7 @@ static bool ParseSpecialName(State *state) {
} }
*state = copy; *state = copy;
if (ParseTwoCharToken(state, "GV") && if (ParseTwoCharToken(state, "GV") && ParseName(state)) {
ParseName(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -831,16 +812,16 @@ static bool ParseSpecialName(State *state) {
// <call-offset> ::= h <nv-offset> _ // <call-offset> ::= h <nv-offset> _
// ::= v <v-offset> _ // ::= v <v-offset> _
static bool ParseCallOffset(State *state) { static bool ParseCallOffset(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'h') && if (ParseOneCharToken(state, 'h') && ParseNVOffset(state) &&
ParseNVOffset(state) && ParseOneCharToken(state, '_')) { ParseOneCharToken(state, '_')) {
return true; return true;
} }
*state = copy; *state = copy;
if (ParseOneCharToken(state, 'v') && if (ParseOneCharToken(state, 'v') && ParseVOffset(state) &&
ParseVOffset(state) && ParseOneCharToken(state, '_')) { ParseOneCharToken(state, '_')) {
return true; return true;
} }
*state = copy; *state = copy;
@ -849,10 +830,10 @@ static bool ParseCallOffset(State *state) {
} }
// <nv-offset> ::= <(offset) number> // <nv-offset> ::= <(offset) number>
static bool ParseNVOffset(State *state) { return ParseNumber(state, nullptr); } static bool ParseNVOffset(State* state) { return ParseNumber(state, nullptr); }
// <v-offset> ::= <(offset) number> _ <(virtual offset) number> // <v-offset> ::= <(offset) number> _ <(virtual offset) number>
static bool ParseVOffset(State *state) { static bool ParseVOffset(State* state) {
State copy = *state; State copy = *state;
if (ParseNumber(state, nullptr) && ParseOneCharToken(state, '_') && if (ParseNumber(state, nullptr) && ParseOneCharToken(state, '_') &&
ParseNumber(state, nullptr)) { ParseNumber(state, nullptr)) {
@ -864,20 +845,18 @@ static bool ParseVOffset(State *state) {
// <ctor-dtor-name> ::= C1 | C2 | C3 // <ctor-dtor-name> ::= C1 | C2 | C3
// ::= D0 | D1 | D2 // ::= D0 | D1 | D2
static bool ParseCtorDtorName(State *state) { static bool ParseCtorDtorName(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'C') && if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "123")) {
ParseCharClass(state, "123")) { const char* const prev_name = state->prev_name;
const char * const prev_name = state->prev_name;
const ssize_t prev_name_length = state->prev_name_length; const ssize_t prev_name_length = state->prev_name_length;
MaybeAppendWithLength(state, prev_name, prev_name_length); MaybeAppendWithLength(state, prev_name, prev_name_length);
return true; return true;
} }
*state = copy; *state = copy;
if (ParseOneCharToken(state, 'D') && if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "012")) {
ParseCharClass(state, "012")) { const char* const prev_name = state->prev_name;
const char * const prev_name = state->prev_name;
const ssize_t prev_name_length = state->prev_name_length; const ssize_t prev_name_length = state->prev_name_length;
MaybeAppend(state, "~"); MaybeAppend(state, "~");
MaybeAppendWithLength(state, prev_name, prev_name_length); MaybeAppendWithLength(state, prev_name, prev_name_length);
@ -907,7 +886,7 @@ static bool ParseCtorDtorName(State *state) {
// # member access (C++0x) // # member access (C++0x)
// ::= DT <expression> E # decltype of an expression (C++0x) // ::= DT <expression> E # decltype of an expression (C++0x)
// //
static bool ParseType(State *state) { static bool ParseType(State* state) {
// We should check CV-qualifers, and PRGC things first. // We should check CV-qualifers, and PRGC things first.
State copy = *state; State copy = *state;
if (ParseCVQualifiers(state) && ParseType(state)) { if (ParseCVQualifiers(state) && ParseType(state)) {
@ -937,17 +916,13 @@ static bool ParseType(State *state) {
} }
*state = copy; *state = copy;
if (ParseBuiltinType(state) || if (ParseBuiltinType(state) || ParseFunctionType(state) ||
ParseFunctionType(state) || ParseClassEnumType(state) || ParseArrayType(state) ||
ParseClassEnumType(state) || ParsePointerToMemberType(state) || ParseSubstitution(state)) {
ParseArrayType(state) ||
ParsePointerToMemberType(state) ||
ParseSubstitution(state)) {
return true; return true;
} }
if (ParseTemplateTemplateParam(state) && if (ParseTemplateTemplateParam(state) && ParseTemplateArgs(state)) {
ParseTemplateArgs(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -963,7 +938,7 @@ static bool ParseType(State *state) {
// <CV-qualifiers> ::= [r] [V] [K] // <CV-qualifiers> ::= [r] [V] [K]
// We don't allow empty <CV-qualifiers> to avoid infinite loop in // We don't allow empty <CV-qualifiers> to avoid infinite loop in
// ParseType(). // ParseType().
static bool ParseCVQualifiers(State *state) { static bool ParseCVQualifiers(State* state) {
int num_cv_qualifiers = 0; int num_cv_qualifiers = 0;
num_cv_qualifiers += ParseOneCharToken(state, 'r'); num_cv_qualifiers += ParseOneCharToken(state, 'r');
num_cv_qualifiers += ParseOneCharToken(state, 'V'); num_cv_qualifiers += ParseOneCharToken(state, 'V');
@ -973,8 +948,8 @@ static bool ParseCVQualifiers(State *state) {
// <builtin-type> ::= v, etc. // <builtin-type> ::= v, etc.
// ::= u <source-name> // ::= u <source-name>
static bool ParseBuiltinType(State *state) { static bool ParseBuiltinType(State* state) {
const AbbrevPair *p; const AbbrevPair* p;
for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) { for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) {
if (state->mangled_cur[0] == p->abbrev[0]) { if (state->mangled_cur[0] == p->abbrev[0]) {
MaybeAppend(state, p->real_name); MaybeAppend(state, p->real_name);
@ -992,11 +967,11 @@ static bool ParseBuiltinType(State *state) {
} }
// <function-type> ::= F [Y] <bare-function-type> E // <function-type> ::= F [Y] <bare-function-type> E
static bool ParseFunctionType(State *state) { static bool ParseFunctionType(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'F') && if (ParseOneCharToken(state, 'F') &&
Optional(ParseOneCharToken(state, 'Y')) && Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) { ParseOneCharToken(state, 'E')) {
return true; return true;
} }
*state = copy; *state = copy;
@ -1004,7 +979,7 @@ static bool ParseFunctionType(State *state) {
} }
// <bare-function-type> ::= <(signature) type>+ // <bare-function-type> ::= <(signature) type>+
static bool ParseBareFunctionType(State *state) { static bool ParseBareFunctionType(State* state) {
State copy = *state; State copy = *state;
DisableAppend(state); DisableAppend(state);
if (OneOrMore(ParseType, state)) { if (OneOrMore(ParseType, state)) {
@ -1017,13 +992,11 @@ static bool ParseBareFunctionType(State *state) {
} }
// <class-enum-type> ::= <name> // <class-enum-type> ::= <name>
static bool ParseClassEnumType(State *state) { static bool ParseClassEnumType(State* state) { return ParseName(state); }
return ParseName(state);
}
// <array-type> ::= A <(positive dimension) number> _ <(element) type> // <array-type> ::= A <(positive dimension) number> _ <(element) type>
// ::= A [<(dimension) expression>] _ <(element) type> // ::= A [<(dimension) expression>] _ <(element) type>
static bool ParseArrayType(State *state) { static bool ParseArrayType(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'A') && ParseNumber(state, nullptr) && if (ParseOneCharToken(state, 'A') && ParseNumber(state, nullptr) &&
ParseOneCharToken(state, '_') && ParseType(state)) { ParseOneCharToken(state, '_') && ParseType(state)) {
@ -1040,10 +1013,9 @@ static bool ParseArrayType(State *state) {
} }
// <pointer-to-member-type> ::= M <(class) type> <(member) type> // <pointer-to-member-type> ::= M <(class) type> <(member) type>
static bool ParsePointerToMemberType(State *state) { static bool ParsePointerToMemberType(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'M') && ParseType(state) && if (ParseOneCharToken(state, 'M') && ParseType(state) && ParseType(state)) {
ParseType(state)) {
return true; return true;
} }
*state = copy; *state = copy;
@ -1052,7 +1024,7 @@ static bool ParsePointerToMemberType(State *state) {
// <template-param> ::= T_ // <template-param> ::= T_
// ::= T <parameter-2 non-negative number> _ // ::= T <parameter-2 non-negative number> _
static bool ParseTemplateParam(State *state) { static bool ParseTemplateParam(State* state) {
if (ParseTwoCharToken(state, "T_")) { if (ParseTwoCharToken(state, "T_")) {
MaybeAppend(state, "?"); // We don't support template substitutions. MaybeAppend(state, "?"); // We don't support template substitutions.
return true; return true;
@ -1068,20 +1040,17 @@ static bool ParseTemplateParam(State *state) {
return false; return false;
} }
// <template-template-param> ::= <template-param> // <template-template-param> ::= <template-param>
// ::= <substitution> // ::= <substitution>
static bool ParseTemplateTemplateParam(State *state) { static bool ParseTemplateTemplateParam(State* state) {
return (ParseTemplateParam(state) || return (ParseTemplateParam(state) || ParseSubstitution(state));
ParseSubstitution(state));
} }
// <template-args> ::= I <template-arg>+ E // <template-args> ::= I <template-arg>+ E
static bool ParseTemplateArgs(State *state) { static bool ParseTemplateArgs(State* state) {
State copy = *state; State copy = *state;
DisableAppend(state); DisableAppend(state);
if (ParseOneCharToken(state, 'I') && if (ParseOneCharToken(state, 'I') && OneOrMore(ParseTemplateArg, state) &&
OneOrMore(ParseTemplateArg, state) &&
ParseOneCharToken(state, 'E')) { ParseOneCharToken(state, 'E')) {
RestoreAppend(state, copy.append); RestoreAppend(state, copy.append);
MaybeAppend(state, "<>"); MaybeAppend(state, "<>");
@ -1096,7 +1065,7 @@ static bool ParseTemplateArgs(State *state) {
// ::= I <template-arg>* E # argument pack // ::= I <template-arg>* E # argument pack
// ::= J <template-arg>* E # argument pack // ::= J <template-arg>* E # argument pack
// ::= X <expression> E // ::= X <expression> E
static bool ParseTemplateArg(State *state) { static bool ParseTemplateArg(State* state) {
// Avoid recursion above max_levels // Avoid recursion above max_levels
constexpr uint32 max_levels = 5; constexpr uint32 max_levels = 5;
@ -1107,15 +1076,13 @@ static bool ParseTemplateArg(State *state) {
State copy = *state; State copy = *state;
if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) && if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) &&
ZeroOrMore(ParseTemplateArg, state) && ZeroOrMore(ParseTemplateArg, state) && ParseOneCharToken(state, 'E')) {
ParseOneCharToken(state, 'E')) {
--state->arg_level; --state->arg_level;
return true; return true;
} }
*state = copy; *state = copy;
if (ParseType(state) || if (ParseType(state) || ParseExprPrimary(state)) {
ParseExprPrimary(state)) {
--state->arg_level; --state->arg_level;
return true; return true;
} }
@ -1139,7 +1106,7 @@ static bool ParseTemplateArg(State *state) {
// ::= st <type> // ::= st <type>
// ::= sr <type> <unqualified-name> <template-args> // ::= sr <type> <unqualified-name> <template-args>
// ::= sr <type> <unqualified-name> // ::= sr <type> <unqualified-name>
static bool ParseExpression(State *state) { static bool ParseExpression(State* state) {
if (ParseTemplateParam(state) || ParseExprPrimary(state)) { if (ParseTemplateParam(state) || ParseExprPrimary(state)) {
return true; return true;
} }
@ -1153,25 +1120,21 @@ static bool ParseExpression(State *state) {
++state->expr_level; ++state->expr_level;
State copy = *state; State copy = *state;
if (ParseOperatorName(state) && if (ParseOperatorName(state) && ParseExpression(state) &&
ParseExpression(state) && ParseExpression(state) && ParseExpression(state)) {
ParseExpression(state) && --state->expr_level;
return true;
}
*state = copy;
if (ParseOperatorName(state) && ParseExpression(state) &&
ParseExpression(state)) { ParseExpression(state)) {
--state->expr_level; --state->expr_level;
return true; return true;
} }
*state = copy; *state = copy;
if (ParseOperatorName(state) && if (ParseOperatorName(state) && ParseExpression(state)) {
ParseExpression(state) &&
ParseExpression(state)) {
--state->expr_level;
return true;
}
*state = copy;
if (ParseOperatorName(state) &&
ParseExpression(state)) {
--state->expr_level; --state->expr_level;
return true; return true;
} }
@ -1184,8 +1147,7 @@ static bool ParseExpression(State *state) {
*state = copy; *state = copy;
if (ParseTwoCharToken(state, "sr") && ParseType(state) && if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
ParseUnqualifiedName(state) && ParseUnqualifiedName(state) && ParseTemplateArgs(state)) {
ParseTemplateArgs(state)) {
--state->expr_level; --state->expr_level;
return true; return true;
} }
@ -1205,7 +1167,7 @@ static bool ParseExpression(State *state) {
// ::= L <mangled-name> E // ::= L <mangled-name> E
// // A bug in g++'s C++ ABI version 2 (-fabi-version=2). // // A bug in g++'s C++ ABI version 2 (-fabi-version=2).
// ::= LZ <encoding> E // ::= LZ <encoding> E
static bool ParseExprPrimary(State *state) { static bool ParseExprPrimary(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, 'L') && ParseType(state) && if (ParseOneCharToken(state, 'L') && ParseType(state) &&
ParseNumber(state, nullptr) && ParseOneCharToken(state, 'E')) { ParseNumber(state, nullptr) && ParseOneCharToken(state, 'E')) {
@ -1214,8 +1176,7 @@ static bool ParseExprPrimary(State *state) {
*state = copy; *state = copy;
if (ParseOneCharToken(state, 'L') && ParseType(state) && if (ParseOneCharToken(state, 'L') && ParseType(state) &&
ParseFloatNumber(state) && ParseFloatNumber(state) && ParseOneCharToken(state, 'E')) {
ParseOneCharToken(state, 'E')) {
return true; return true;
} }
*state = copy; *state = copy;
@ -1238,7 +1199,7 @@ static bool ParseExprPrimary(State *state) {
// <local-name> := Z <(function) encoding> E <(entity) name> // <local-name> := Z <(function) encoding> E <(entity) name>
// [<discriminator>] // [<discriminator>]
// := Z <(function) encoding> E s [<discriminator>] // := Z <(function) encoding> E s [<discriminator>]
static bool ParseLocalName(State *state) { static bool ParseLocalName(State* state) {
// Avoid recursion above max_levels // Avoid recursion above max_levels
constexpr uint32 max_levels = 5; constexpr uint32 max_levels = 5;
if (state->local_level > max_levels) { if (state->local_level > max_levels) {
@ -1265,7 +1226,7 @@ static bool ParseLocalName(State *state) {
} }
// <discriminator> := _ <(non-negative) number> // <discriminator> := _ <(non-negative) number>
static bool ParseDiscriminator(State *state) { static bool ParseDiscriminator(State* state) {
State copy = *state; State copy = *state;
if (ParseOneCharToken(state, '_') && ParseNumber(state, nullptr)) { if (ParseOneCharToken(state, '_') && ParseNumber(state, nullptr)) {
return true; return true;
@ -1277,7 +1238,7 @@ static bool ParseDiscriminator(State *state) {
// <substitution> ::= S_ // <substitution> ::= S_
// ::= S <seq-id> _ // ::= S <seq-id> _
// ::= St, etc. // ::= St, etc.
static bool ParseSubstitution(State *state) { static bool ParseSubstitution(State* state) {
if (ParseTwoCharToken(state, "S_")) { if (ParseTwoCharToken(state, "S_")) {
MaybeAppend(state, "?"); // We don't support substitutions. MaybeAppend(state, "?"); // We don't support substitutions.
return true; return true;
@ -1293,7 +1254,7 @@ static bool ParseSubstitution(State *state) {
// Expand abbreviations like "St" => "std". // Expand abbreviations like "St" => "std".
if (ParseOneCharToken(state, 'S')) { if (ParseOneCharToken(state, 'S')) {
const AbbrevPair *p; const AbbrevPair* p;
for (p = kSubstitutionList; p->abbrev != nullptr; ++p) { for (p = kSubstitutionList; p->abbrev != nullptr; ++p) {
if (state->mangled_cur[0] == p->abbrev[1]) { if (state->mangled_cur[0] == p->abbrev[1]) {
MaybeAppend(state, "std"); MaybeAppend(state, "std");
@ -1312,7 +1273,7 @@ static bool ParseSubstitution(State *state) {
// Parse <mangled-name>, optionally followed by either a function-clone suffix // Parse <mangled-name>, optionally followed by either a function-clone suffix
// or version suffix. Returns true only if all of "mangled_cur" was consumed. // or version suffix. Returns true only if all of "mangled_cur" was consumed.
static bool ParseTopLevelMangledName(State *state) { static bool ParseTopLevelMangledName(State* state) {
if (ParseMangledName(state)) { if (ParseMangledName(state)) {
if (state->mangled_cur[0] != '\0') { if (state->mangled_cur[0] != '\0') {
// Drop trailing function clone suffix, if any. // Drop trailing function clone suffix, if any.
@ -1334,9 +1295,9 @@ static bool ParseTopLevelMangledName(State *state) {
#endif #endif
// The demangler entry point. // The demangler entry point.
bool Demangle(const char *mangled, char *out, size_t out_size) { bool Demangle(const char* mangled, char* out, size_t out_size) {
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
#if defined(HAVE_DBGHELP) # if defined(HAVE_DBGHELP)
// When built with incremental linking, the Windows debugger // When built with incremental linking, the Windows debugger
// library provides a more complicated `Symbol->Name` with the // library provides a more complicated `Symbol->Name` with the
// Incremental Linking Table offset, which looks like // Incremental Linking Table offset, which looks like
@ -1347,23 +1308,23 @@ bool Demangle(const char *mangled, char *out, size_t out_size) {
// //
// Since we may be in a signal handler here, we cannot use `std::string`. // Since we may be in a signal handler here, we cannot use `std::string`.
char buffer[1024]; // Big enough for a sane symbol. char buffer[1024]; // Big enough for a sane symbol.
const char *lparen = strchr(mangled, '('); const char* lparen = strchr(mangled, '(');
if (lparen) { if (lparen) {
// Extract the string `(?...)` // Extract the string `(?...)`
const char *rparen = strchr(lparen, ')'); const char* rparen = strchr(lparen, ')');
size_t length = static_cast<size_t>(rparen - lparen) - 1; size_t length = static_cast<size_t>(rparen - lparen) - 1;
strncpy(buffer, lparen + 1, length); strncpy(buffer, lparen + 1, length);
buffer[length] = '\0'; buffer[length] = '\0';
mangled = buffer; mangled = buffer;
} // Else the symbol wasn't inside a set of parentheses } // Else the symbol wasn't inside a set of parentheses
// We use the ANSI version to ensure the string type is always `char *`. // We use the ANSI version to ensure the string type is always `char *`.
return UnDecorateSymbolName(mangled, out, out_size, UNDNAME_COMPLETE); return UnDecorateSymbolName(mangled, out, out_size, UNDNAME_COMPLETE);
#else # else
(void)mangled; (void)mangled;
(void)out; (void)out;
(void)out_size; (void)out_size;
return false; return false;
#endif # endif
#else #else
State state; State state;
InitState(&state, mangled, out, out_size); InitState(&state, mangled, out, out_size);

View File

@ -78,7 +78,7 @@ namespace google {
// Demangle "mangled". On success, return true and write the // Demangle "mangled". On success, return true and write the
// demangled symbol name to "out". Otherwise, return false. // demangled symbol name to "out". Otherwise, return false.
// "out" is modified even if demangling is unsuccessful. // "out" is modified even if demangling is unsuccessful.
bool GLOG_EXPORT Demangle(const char *mangled, char *out, size_t out_size); bool GLOG_EXPORT Demangle(const char* mangled, char* out, size_t out_size);
} // namespace google } // namespace google

View File

@ -43,7 +43,7 @@
#include "utilities.h" #include "utilities.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
@ -54,7 +54,7 @@ using namespace std;
using namespace google; using namespace google;
// A wrapper function for Demangle() to make the unit test simple. // A wrapper function for Demangle() to make the unit test simple.
static const char *DemangleIt(const char * const mangled) { static const char* DemangleIt(const char* const mangled) {
static char demangled[4096]; static char demangled[4096];
if (Demangle(mangled, demangled, sizeof(demangled))) { if (Demangle(mangled, demangled, sizeof(demangled))) {
return demangled; return demangled;
@ -65,28 +65,25 @@ static const char *DemangleIt(const char * const mangled) {
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
#if defined(HAVE_DBGHELP) && !defined(NDEBUG) # if defined(HAVE_DBGHELP) && !defined(NDEBUG)
TEST(Demangle, Windows) { TEST(Demangle, Windows) {
EXPECT_STREQ( EXPECT_STREQ("public: static void __cdecl Foo::func(int)",
"public: static void __cdecl Foo::func(int)", DemangleIt("?func@Foo@@SAXH@Z"));
DemangleIt("?func@Foo@@SAXH@Z")); EXPECT_STREQ("public: static void __cdecl Foo::func(int)",
EXPECT_STREQ( DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)"));
"public: static void __cdecl Foo::func(int)", EXPECT_STREQ("int __cdecl foobarArray(int * const)",
DemangleIt("@ILT+1105(?func@Foo@@SAXH@Z)")); DemangleIt("?foobarArray@@YAHQAH@Z"));
EXPECT_STREQ(
"int __cdecl foobarArray(int * const)",
DemangleIt("?foobarArray@@YAHQAH@Z"));
} }
#endif # endif
#else #else
// Test corner cases of boundary conditions. // Test corner cases of boundary conditions.
TEST(Demangle, CornerCases) { TEST(Demangle, CornerCases) {
const size_t size = 10; const size_t size = 10;
char tmp[size] = { 0 }; char tmp[size] = {0};
const char *demangled = "foobar()"; const char* demangled = "foobar()";
const char *mangled = "_Z6foobarv"; const char* mangled = "_Z6foobarv";
EXPECT_TRUE(Demangle(mangled, tmp, sizeof(tmp))); EXPECT_TRUE(Demangle(mangled, tmp, sizeof(tmp)));
// sizeof("foobar()") == size - 1 // sizeof("foobar()") == size - 1
EXPECT_STREQ(demangled, tmp); EXPECT_STREQ(demangled, tmp);
@ -147,7 +144,7 @@ TEST(Demangle, FromFile) {
#endif #endif
int main(int argc, char **argv) { int main(int argc, char** argv) {
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
ParseCommandLineFlags(&argc, &argv, true); ParseCommandLineFlags(&argc, &argv, true);
#endif #endif

View File

@ -18,7 +18,7 @@
#include "demangle.h" #include "demangle.h"
extern "C" int LLVMFuzzerTestOneInput(const unsigned char *Data, extern "C" int LLVMFuzzerTestOneInput(const unsigned char* Data,
unsigned Size) { unsigned Size) {
if (Size >= 4095) { if (Size >= 4095) {
return 0; return 0;

View File

@ -51,20 +51,20 @@
using LogSeverity = int; using LogSeverity = int;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3, const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4; NUM_SEVERITIES = 4;
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES #ifndef GLOG_NO_ABBREVIATED_SEVERITIES
# ifdef ERROR # ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail. # error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif # endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING, const int INFO = GLOG_INFO, WARNING = GLOG_WARNING, ERROR = GLOG_ERROR,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL; FATAL = GLOG_FATAL;
#endif #endif
// DFATAL is FATAL in debug mode, ERROR in normal mode // DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef NDEBUG #ifdef NDEBUG
#define DFATAL_LEVEL ERROR # define DFATAL_LEVEL ERROR
#else #else
#define DFATAL_LEVEL FATAL # define DFATAL_LEVEL FATAL
#endif #endif
extern GLOG_EXPORT const char* const LogSeverityNames[NUM_SEVERITIES]; extern GLOG_EXPORT const char* const LogSeverityNames[NUM_SEVERITIES];
@ -89,10 +89,10 @@ extern GLOG_EXPORT const char* const LogSeverityNames[NUM_SEVERITIES];
// //
#ifdef NDEBUG #ifdef NDEBUG
enum { DEBUG_MODE = 0 }; enum { DEBUG_MODE = 0 };
#define IF_DEBUG_MODE(x) # define IF_DEBUG_MODE(x)
#else #else
enum { DEBUG_MODE = 1 }; enum { DEBUG_MODE = 1 };
#define IF_DEBUG_MODE(x) x # define IF_DEBUG_MODE(x) x
#endif #endif
#endif // BASE_LOG_SEVERITY_H__ #endif // BASE_LOG_SEVERITY_H__

View File

@ -50,28 +50,28 @@
#include <vector> #include <vector>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) \ # define GLOG_MSVC_PUSH_DISABLE_WARNING(n) \
__pragma(warning(push)) __pragma(warning(disable : n)) __pragma(warning(push)) __pragma(warning(disable : n))
#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop)) # define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
#else #else
#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) # define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
#define GLOG_MSVC_POP_WARNING() # define GLOG_MSVC_POP_WARNING()
#endif #endif
#include "glog/platform.h" #include "glog/platform.h"
#if defined(__has_attribute) #if defined(__has_attribute)
#if __has_attribute(used) # if __has_attribute(used)
#define GLOG_USED __attribute__((used)) # define GLOG_USED __attribute__((used))
#endif // __has_attribute(used) # endif // __has_attribute(used)
#endif // defined(__has_attribute) #endif // defined(__has_attribute)
#if !defined(GLOG_USED) #if !defined(GLOG_USED)
#define GLOG_USED # define GLOG_USED
#endif // !defined(GLOG_USED) #endif // !defined(GLOG_USED)
#if defined(GLOG_USE_GLOG_EXPORT) #if defined(GLOG_USE_GLOG_EXPORT)
#include "glog/export.h" # include "glog/export.h"
#endif #endif
// We care a lot about number of bits things take up. Unfortunately, // We care a lot about number of bits things take up. Unfortunately,
@ -83,7 +83,7 @@
#include <cstdint> // the normal place uint16_t is defined #include <cstdint> // the normal place uint16_t is defined
#if defined(GLOG_USE_GFLAGS) #if defined(GLOG_USE_GFLAGS)
#include <gflags/gflags.h> # include <gflags/gflags.h>
#endif #endif
#include <atomic> #include <atomic>
@ -158,7 +158,7 @@ typedef void (*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l,
// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including // file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including
// base/logging.h // base/logging.h
#ifndef GOOGLE_STRIP_LOG #ifndef GOOGLE_STRIP_LOG
#define GOOGLE_STRIP_LOG 0 # define GOOGLE_STRIP_LOG 0
#endif #endif
// GCC can be told that a certain branch is not likely to be taken (for // GCC can be told that a certain branch is not likely to be taken (for
@ -167,43 +167,43 @@ typedef void (*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l,
// the absence of better information (ie. -fprofile-arcs). // the absence of better information (ie. -fprofile-arcs).
// //
#if defined(__has_builtin) #if defined(__has_builtin)
#if __has_builtin(__builtin_expect) # if __has_builtin(__builtin_expect)
#define GLOG_BUILTIN_EXPECT_PRESENT # define GLOG_BUILTIN_EXPECT_PRESENT
#endif # endif
#endif #endif
#if !defined(GLOG_BUILTIN_EXPECT_PRESENT) && defined(__GNUG__) #if !defined(GLOG_BUILTIN_EXPECT_PRESENT) && defined(__GNUG__)
// __has_builtin is not available prior to GCC 10 // __has_builtin is not available prior to GCC 10
#define GLOG_BUILTIN_EXPECT_PRESENT # define GLOG_BUILTIN_EXPECT_PRESENT
#endif #endif
#if defined(GLOG_BUILTIN_EXPECT_PRESENT) #if defined(GLOG_BUILTIN_EXPECT_PRESENT)
#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN # ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0)) # define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
#endif # endif
#ifndef GOOGLE_PREDICT_FALSE # ifndef GOOGLE_PREDICT_FALSE
#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) # define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#endif # endif
#ifndef GOOGLE_PREDICT_TRUE # ifndef GOOGLE_PREDICT_TRUE
#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) # define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#endif # endif
#else #else
#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN # ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x # define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
#endif # endif
#ifndef GOOGLE_PREDICT_TRUE # ifndef GOOGLE_PREDICT_TRUE
#define GOOGLE_PREDICT_FALSE(x) x # define GOOGLE_PREDICT_FALSE(x) x
#endif # endif
#ifndef GOOGLE_PREDICT_TRUE # ifndef GOOGLE_PREDICT_TRUE
#define GOOGLE_PREDICT_TRUE(x) x # define GOOGLE_PREDICT_TRUE(x) x
#endif # endif
#endif #endif
@ -370,50 +370,51 @@ typedef void (*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l,
#pragma push_macro("DECLARE_uint32") #pragma push_macro("DECLARE_uint32")
#ifdef DECLARE_VARIABLE #ifdef DECLARE_VARIABLE
#undef DECLARE_VARIABLE # undef DECLARE_VARIABLE
#endif #endif
#ifdef DECLARE_bool #ifdef DECLARE_bool
#undef DECLARE_bool # undef DECLARE_bool
#endif #endif
#ifdef DECLARE_string #ifdef DECLARE_string
#undef DECLARE_string # undef DECLARE_string
#endif #endif
#ifdef DECLARE_int32 #ifdef DECLARE_int32
#undef DECLARE_int32 # undef DECLARE_int32
#endif #endif
#ifdef DECLARE_uint32 #ifdef DECLARE_uint32
#undef DECLARE_uint32 # undef DECLARE_uint32
#endif #endif
#ifndef DECLARE_VARIABLE #ifndef DECLARE_VARIABLE
#define DECLARE_VARIABLE(type, shorttype, name, tn) \ # define DECLARE_VARIABLE(type, shorttype, name, tn) \
namespace fL##shorttype { \ namespace fL##shorttype { \
extern GLOG_EXPORT type FLAGS_##name; \ extern GLOG_EXPORT type FLAGS_##name; \
} \ } \
using fL##shorttype::FLAGS_##name using fL##shorttype::FLAGS_##name
// bool specialization // bool specialization
#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name, bool) # define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name, bool)
// int32 specialization // int32 specialization
#define DECLARE_int32(name) DECLARE_VARIABLE(google::int32, I, name, int32) # define DECLARE_int32(name) DECLARE_VARIABLE(google::int32, I, name, int32)
#if !defined(DECLARE_uint32) # if !defined(DECLARE_uint32)
// uint32 specialization // uint32 specialization
#define DECLARE_uint32(name) DECLARE_VARIABLE(google::uint32, U, name, uint32) # define DECLARE_uint32(name) \
#endif // !defined(DECLARE_uint32) && !defined(GLOG_USE_GFLAGS) DECLARE_VARIABLE(google::uint32, U, name, uint32)
# endif // !defined(DECLARE_uint32) && !defined(GLOG_USE_GFLAGS)
// Special case for string, because we have to specify the namespace // Special case for string, because we have to specify the namespace
// std::string, which doesn't play nicely with our FLAG__namespace hackery. // std::string, which doesn't play nicely with our FLAG__namespace hackery.
#define DECLARE_string(name) \ # define DECLARE_string(name) \
namespace fLS { \ namespace fLS { \
extern GLOG_EXPORT std::string& FLAGS_##name; \ extern GLOG_EXPORT std::string& FLAGS_##name; \
} \ } \
using fLS::FLAGS_##name using fLS::FLAGS_##name
#endif #endif
// Set whether appending a timestamp to the log file name // Set whether appending a timestamp to the log file name
@ -493,58 +494,58 @@ DECLARE_string(logmailer);
// better to have compact code for these operations. // better to have compact code for these operations.
#if GOOGLE_STRIP_LOG == 0 #if GOOGLE_STRIP_LOG == 0
#define COMPACT_GOOGLE_LOG_INFO google::LogMessage(__FILE__, __LINE__) # define COMPACT_GOOGLE_LOG_INFO google::LogMessage(__FILE__, __LINE__)
#define LOG_TO_STRING_INFO(message) \ # define LOG_TO_STRING_INFO(message) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, message) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, message)
#else #else
#define COMPACT_GOOGLE_LOG_INFO google::NullStream() # define COMPACT_GOOGLE_LOG_INFO google::NullStream()
#define LOG_TO_STRING_INFO(message) google::NullStream() # define LOG_TO_STRING_INFO(message) google::NullStream()
#endif #endif
#if GOOGLE_STRIP_LOG <= 1 #if GOOGLE_STRIP_LOG <= 1
#define COMPACT_GOOGLE_LOG_WARNING \ # define COMPACT_GOOGLE_LOG_WARNING \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING) google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING)
#define LOG_TO_STRING_WARNING(message) \ # define LOG_TO_STRING_WARNING(message) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, message) google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, message)
#else #else
#define COMPACT_GOOGLE_LOG_WARNING google::NullStream() # define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
#define LOG_TO_STRING_WARNING(message) google::NullStream() # define LOG_TO_STRING_WARNING(message) google::NullStream()
#endif #endif
#if GOOGLE_STRIP_LOG <= 2 #if GOOGLE_STRIP_LOG <= 2
#define COMPACT_GOOGLE_LOG_ERROR \ # define COMPACT_GOOGLE_LOG_ERROR \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR) google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR)
#define LOG_TO_STRING_ERROR(message) \ # define LOG_TO_STRING_ERROR(message) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, message) google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, message)
#else #else
#define COMPACT_GOOGLE_LOG_ERROR google::NullStream() # define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
#define LOG_TO_STRING_ERROR(message) google::NullStream() # define LOG_TO_STRING_ERROR(message) google::NullStream()
#endif #endif
#if GOOGLE_STRIP_LOG <= 3 #if GOOGLE_STRIP_LOG <= 3
#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal(__FILE__, __LINE__) # define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal(__FILE__, __LINE__)
#define LOG_TO_STRING_FATAL(message) \ # define LOG_TO_STRING_FATAL(message) \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, message) google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, message)
#else #else
#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal() # define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal() # define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
#endif #endif
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
#define DCHECK_IS_ON() 0 # define DCHECK_IS_ON() 0
#else #else
#define DCHECK_IS_ON() 1 # define DCHECK_IS_ON() 1
#endif #endif
// For DFATAL, we want to use LogMessage (as opposed to // For DFATAL, we want to use LogMessage (as opposed to
// LogMessageFatal), to be consistent with the original behavior. // LogMessageFatal), to be consistent with the original behavior.
#if !DCHECK_IS_ON() #if !DCHECK_IS_ON()
#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR # define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
#elif GOOGLE_STRIP_LOG <= 3 #elif GOOGLE_STRIP_LOG <= 3
#define COMPACT_GOOGLE_LOG_DFATAL \ # define COMPACT_GOOGLE_LOG_DFATAL \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL) google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL)
#else #else
#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal() # define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
#endif #endif
#define GOOGLE_LOG_INFO(counter) \ #define GOOGLE_LOG_INFO(counter) \
@ -581,22 +582,22 @@ DECLARE_string(logmailer);
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \
defined(__CYGWIN__) || defined(__CYGWIN32__) defined(__CYGWIN__) || defined(__CYGWIN32__)
// A very useful logging macro to log windows errors: // A very useful logging macro to log windows errors:
#define LOG_SYSRESULT(result) \ # define LOG_SYSRESULT(result) \
if (FAILED(HRESULT_FROM_WIN32(result))) { \ if (FAILED(HRESULT_FROM_WIN32(result))) { \
LPSTR message = nullptr; \ LPSTR message = nullptr; \
LPSTR msg = reinterpret_cast<LPSTR>(&message); \ LPSTR msg = reinterpret_cast<LPSTR>(&message); \
DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \ DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
FORMAT_MESSAGE_FROM_SYSTEM | \ FORMAT_MESSAGE_FROM_SYSTEM | \
FORMAT_MESSAGE_IGNORE_INSERTS, \ FORMAT_MESSAGE_IGNORE_INSERTS, \
0, result, 0, msg, 100, nullptr); \ 0, result, 0, msg, 100, nullptr); \
if (message_length > 0) { \ if (message_length > 0) { \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \ google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
&google::LogMessage::SendToLog) \ &google::LogMessage::SendToLog) \
.stream() \ .stream() \
<< reinterpret_cast<const char*>(message); \ << reinterpret_cast<const char*>(message); \
LocalFree(message); \ LocalFree(message); \
} \ } \
} }
#endif #endif
// We use the preprocessor's merging operator, "##", so that, e.g., // We use the preprocessor's merging operator, "##", so that, e.g.,
@ -781,9 +782,9 @@ GLOG_EXPORT void MakeCheckOpValueString(std::ostream* os,
template <typename T1, typename T2> template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
#if defined(__has_attribute) #if defined(__has_attribute)
#if __has_attribute(used) # if __has_attribute(used)
__attribute__((noinline)) __attribute__((noinline))
#endif # endif
#endif #endif
; ;
@ -866,7 +867,7 @@ DEFINE_CHECK_OP_IMPL(Check_GT, >)
#if defined(STATIC_ANALYSIS) #if defined(STATIC_ANALYSIS)
// Only for static analysis tool to know that it is equivalent to assert // Only for static analysis tool to know that it is equivalent to assert
#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1)op(val2)) # define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1)op(val2))
#elif DCHECK_IS_ON() #elif DCHECK_IS_ON()
// In debug mode, avoid constructing CheckOpStrings if possible, // In debug mode, avoid constructing CheckOpStrings if possible,
// to reduce the overhead of CHECK statements by 2x. // to reduce the overhead of CHECK statements by 2x.
@ -878,27 +879,27 @@ DEFINE_CHECK_OP_IMPL(Check_GT, >)
// file is included). Save the current meaning now and use it // file is included). Save the current meaning now and use it
// in the macro. // in the macro.
typedef std::string _Check_string; typedef std::string _Check_string;
#define CHECK_OP_LOG(name, op, val1, val2, log) \ # define CHECK_OP_LOG(name, op, val1, val2, log) \
while (google::_Check_string* _result = google::Check##name##Impl( \ while (google::_Check_string* _result = google::Check##name##Impl( \
google::GetReferenceableValue(val1), \ google::GetReferenceableValue(val1), \
google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \ google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \
log(__FILE__, __LINE__, google::CheckOpString(_result)).stream() log(__FILE__, __LINE__, google::CheckOpString(_result)).stream()
#else #else
// In optimized mode, use CheckOpString to hint to compiler that // In optimized mode, use CheckOpString to hint to compiler that
// the while condition is unlikely. // the while condition is unlikely.
#define CHECK_OP_LOG(name, op, val1, val2, log) \ # define CHECK_OP_LOG(name, op, val1, val2, log) \
while (google::CheckOpString _result = google::Check##name##Impl( \ while (google::CheckOpString _result = google::Check##name##Impl( \
google::GetReferenceableValue(val1), \ google::GetReferenceableValue(val1), \
google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \ google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \
log(__FILE__, __LINE__, _result).stream() log(__FILE__, __LINE__, _result).stream()
#endif // STATIC_ANALYSIS, DCHECK_IS_ON() #endif // STATIC_ANALYSIS, DCHECK_IS_ON()
#if GOOGLE_STRIP_LOG <= 3 #if GOOGLE_STRIP_LOG <= 3
#define CHECK_OP(name, op, val1, val2) \ # define CHECK_OP(name, op, val1, val2) \
CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal) CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
#else #else
#define CHECK_OP(name, op, val1, val2) \ # define CHECK_OP(name, op, val1, val2) \
CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal) CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal)
#endif // STRIP_LOG <= 3 #endif // STRIP_LOG <= 3
// Equality/Inequality checks - compare two values, and log a FATAL message // Equality/Inequality checks - compare two values, and log a FATAL message
@ -1028,20 +1029,20 @@ DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
#define LOG_PREVIOUS_TIME LOG_EVERY_N_VARNAME(previousTime_, __LINE__) #define LOG_PREVIOUS_TIME LOG_EVERY_N_VARNAME(previousTime_, __LINE__)
#if defined(__has_feature) #if defined(__has_feature)
#if __has_feature(thread_sanitizer) # if __has_feature(thread_sanitizer)
#define GLOG_SANITIZE_THREAD 1 # define GLOG_SANITIZE_THREAD 1
#endif # endif
#endif #endif
#if !defined(GLOG_SANITIZE_THREAD) && defined(__SANITIZE_THREAD__) && \ #if !defined(GLOG_SANITIZE_THREAD) && defined(__SANITIZE_THREAD__) && \
__SANITIZE_THREAD__ __SANITIZE_THREAD__
#define GLOG_SANITIZE_THREAD 1 # define GLOG_SANITIZE_THREAD 1
#endif #endif
#if defined(GLOG_SANITIZE_THREAD) #if defined(GLOG_SANITIZE_THREAD)
#define GLOG_IFDEF_THREAD_SANITIZER(X) X # define GLOG_IFDEF_THREAD_SANITIZER(X) X
#else #else
#define GLOG_IFDEF_THREAD_SANITIZER(X) # define GLOG_IFDEF_THREAD_SANITIZER(X)
#endif #endif
#if defined(GLOG_SANITIZE_THREAD) #if defined(GLOG_SANITIZE_THREAD)
@ -1166,9 +1167,9 @@ enum PRIVATE_Counter { COUNTER };
// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us // substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
// to keep using this syntax, we define this macro to do the same thing // to keep using this syntax, we define this macro to do the same thing
// as COMPACT_GOOGLE_LOG_ERROR. // as COMPACT_GOOGLE_LOG_ERROR.
#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR # define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
#define SYSLOG_0 SYSLOG_ERROR # define SYSLOG_0 SYSLOG_ERROR
#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR # define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
// Needed for LOG_IS_ON(ERROR). // Needed for LOG_IS_ON(ERROR).
const LogSeverity GLOG_0 = GLOG_ERROR; const LogSeverity GLOG_0 = GLOG_ERROR;
#else #else
@ -1176,126 +1177,126 @@ const LogSeverity GLOG_0 = GLOG_ERROR;
// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN. // GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
// For this case, we cannot detect if ERROR is defined before users // For this case, we cannot detect if ERROR is defined before users
// actually use ERROR. Let's make an undefined symbol to warn users. // actually use ERROR. Let's make an undefined symbol to warn users.
#define GLOG_ERROR_MSG \ # define GLOG_ERROR_MSG \
ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
#define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG # define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
#define SYSLOG_0 GLOG_ERROR_MSG # define SYSLOG_0 GLOG_ERROR_MSG
#define LOG_TO_STRING_0 GLOG_ERROR_MSG # define LOG_TO_STRING_0 GLOG_ERROR_MSG
#define GLOG_0 GLOG_ERROR_MSG # define GLOG_0 GLOG_ERROR_MSG
#endif #endif
// Plus some debug-logging macros that get compiled to nothing for production // Plus some debug-logging macros that get compiled to nothing for production
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
#define DLOG(severity) LOG(severity) # define DLOG(severity) LOG(severity)
#define DVLOG(verboselevel) VLOG(verboselevel) # define DVLOG(verboselevel) VLOG(verboselevel)
#define DLOG_IF(severity, condition) LOG_IF(severity, condition) # define DLOG_IF(severity, condition) LOG_IF(severity, condition)
#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n) # define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n)
#define DLOG_IF_EVERY_N(severity, condition, n) \ # define DLOG_IF_EVERY_N(severity, condition, n) \
LOG_IF_EVERY_N(severity, condition, n) LOG_IF_EVERY_N(severity, condition, n)
#define DLOG_FIRST_N(severity, n) LOG_FIRST_N(severity, n) # define DLOG_FIRST_N(severity, n) LOG_FIRST_N(severity, n)
#define DLOG_EVERY_T(severity, T) LOG_EVERY_T(severity, T) # define DLOG_EVERY_T(severity, T) LOG_EVERY_T(severity, T)
#define DLOG_ASSERT(condition) LOG_ASSERT(condition) # define DLOG_ASSERT(condition) LOG_ASSERT(condition)
// debug-only checking. executed if DCHECK_IS_ON(). // debug-only checking. executed if DCHECK_IS_ON().
#define DCHECK(condition) CHECK(condition) # define DCHECK(condition) CHECK(condition)
#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) # define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) # define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) # define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) # define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) # define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) # define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val) # define DCHECK_NOTNULL(val) CHECK_NOTNULL(val)
#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2) # define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2)
#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2) # define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2)
#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2) # define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2)
#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2) # define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2)
#else // !DCHECK_IS_ON() #else // !DCHECK_IS_ON()
#define DLOG(severity) \ # define DLOG(severity) \
static_cast<void>(0), \ static_cast<void>(0), \
true ? (void)0 : google::LogMessageVoidify() & LOG(severity) true ? (void)0 : google::LogMessageVoidify() & LOG(severity)
#define DVLOG(verboselevel) \ # define DVLOG(verboselevel) \
static_cast<void>(0), (true || !VLOG_IS_ON(verboselevel)) \ static_cast<void>(0), (true || !VLOG_IS_ON(verboselevel)) \
? (void)0 \ ? (void)0 \
: google::LogMessageVoidify() & LOG(INFO) : google::LogMessageVoidify() & LOG(INFO)
#define DLOG_IF(severity, condition) \ # define DLOG_IF(severity, condition) \
static_cast<void>(0), (true || !(condition)) \ static_cast<void>(0), (true || !(condition)) \
? (void)0 \ ? (void)0 \
: google::LogMessageVoidify() & LOG(severity) : google::LogMessageVoidify() & LOG(severity)
#define DLOG_EVERY_N(severity, n) \ # define DLOG_EVERY_N(severity, n) \
static_cast<void>(0), \ static_cast<void>(0), \
true ? (void)0 : google::LogMessageVoidify() & LOG(severity) true ? (void)0 : google::LogMessageVoidify() & LOG(severity)
#define DLOG_IF_EVERY_N(severity, condition, n) \ # define DLOG_IF_EVERY_N(severity, condition, n) \
static_cast<void>(0), (true || !(condition)) \ static_cast<void>(0), (true || !(condition)) \
? (void)0 \ ? (void)0 \
: google::LogMessageVoidify() & LOG(severity) : google::LogMessageVoidify() & LOG(severity)
#define DLOG_FIRST_N(severity, n) \ # define DLOG_FIRST_N(severity, n) \
static_cast<void>(0), \ static_cast<void>(0), \
true ? (void)0 : google::LogMessageVoidify() & LOG(severity) true ? (void)0 : google::LogMessageVoidify() & LOG(severity)
#define DLOG_EVERY_T(severity, T) \ # define DLOG_EVERY_T(severity, T) \
static_cast<void>(0), \ static_cast<void>(0), \
true ? (void)0 : google::LogMessageVoidify() & LOG(severity) true ? (void)0 : google::LogMessageVoidify() & LOG(severity)
#define DLOG_ASSERT(condition) \ # define DLOG_ASSERT(condition) \
static_cast<void>(0), true ? (void)0 : LOG_ASSERT(condition) static_cast<void>(0), true ? (void)0 : LOG_ASSERT(condition)
// MSVC warning C4127: conditional expression is constant // MSVC warning C4127: conditional expression is constant
#define DCHECK(condition) \ # define DCHECK(condition) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK(condition) while (false) GLOG_MSVC_POP_WARNING() CHECK(condition)
#define DCHECK_EQ(val1, val2) \ # define DCHECK_EQ(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2) while (false) GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
#define DCHECK_NE(val1, val2) \ # define DCHECK_NE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2) while (false) GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
#define DCHECK_LE(val1, val2) \ # define DCHECK_LE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2) while (false) GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
#define DCHECK_LT(val1, val2) \ # define DCHECK_LT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2) while (false) GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
#define DCHECK_GE(val1, val2) \ # define DCHECK_GE(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2) while (false) GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2) \ # define DCHECK_GT(val1, val2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2) while (false) GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
// You may see warnings in release mode if you don't use the return // You may see warnings in release mode if you don't use the return
// value of DCHECK_NOTNULL. Please just use DCHECK for such cases. // value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
#define DCHECK_NOTNULL(val) (val) # define DCHECK_NOTNULL(val) (val)
#define DCHECK_STREQ(str1, str2) \ # define DCHECK_STREQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2) while (false) GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
#define DCHECK_STRCASEEQ(str1, str2) \ # define DCHECK_STRCASEEQ(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2) while (false) GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
#define DCHECK_STRNE(str1, str2) \ # define DCHECK_STRNE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2) while (false) GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
#define DCHECK_STRCASENE(str1, str2) \ # define DCHECK_STRCASENE(str1, str2) \
GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \ GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
while (false) GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2) while (false) GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
#endif // DCHECK_IS_ON() #endif // DCHECK_IS_ON()

View File

@ -35,26 +35,26 @@
#define GLOG_PLATFORM_H #define GLOG_PLATFORM_H
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#define GLOG_OS_WINDOWS # define GLOG_OS_WINDOWS
#elif defined(__CYGWIN__) || defined(__CYGWIN32__) #elif defined(__CYGWIN__) || defined(__CYGWIN32__)
#define GLOG_OS_CYGWIN # define GLOG_OS_CYGWIN
#elif defined(linux) || defined(__linux) || defined(__linux__) #elif defined(linux) || defined(__linux) || defined(__linux__)
#ifndef GLOG_OS_LINUX # ifndef GLOG_OS_LINUX
#define GLOG_OS_LINUX # define GLOG_OS_LINUX
#endif # endif
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#define GLOG_OS_MACOSX # define GLOG_OS_MACOSX
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
#define GLOG_OS_FREEBSD # define GLOG_OS_FREEBSD
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
#define GLOG_OS_NETBSD # define GLOG_OS_NETBSD
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
#define GLOG_OS_OPENBSD # define GLOG_OS_OPENBSD
#elif defined(__EMSCRIPTEN__) #elif defined(__EMSCRIPTEN__)
#define GLOG_OS_EMSCRIPTEN # define GLOG_OS_EMSCRIPTEN
#else #else
// TODO(hamaji): Add other platforms. // TODO(hamaji): Add other platforms.
#error Platform not supported by glog. Please consider to contribute platform information by submitting a pull request on Github. #error Platform not supported by glog. Please consider to contribute platform information by submitting a pull request on Github.
#endif #endif
#endif // GLOG_PLATFORM_H #endif // GLOG_PLATFORM_H

View File

@ -44,8 +44,8 @@ namespace google {
#include "glog/vlog_is_on.h" #include "glog/vlog_is_on.h"
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros" # pragma GCC diagnostic ignored "-Wvariadic-macros"
#endif #endif
// This is similar to LOG(severity) << format... and VLOG(level) << format.., // This is similar to LOG(severity) << format... and VLOG(level) << format..,
@ -85,46 +85,46 @@ namespace google {
// The following STRIP_LOG testing is performed in the header file so that it's // The following STRIP_LOG testing is performed in the header file so that it's
// possible to completely compile out the logging code and the log messages. // possible to completely compile out the logging code and the log messages.
#if !defined(STRIP_LOG) || STRIP_LOG == 0 #if !defined(STRIP_LOG) || STRIP_LOG == 0
#define RAW_VLOG(verboselevel, ...) \ # define RAW_VLOG(verboselevel, ...) \
do { \ do { \
if (VLOG_IS_ON(verboselevel)) { \ if (VLOG_IS_ON(verboselevel)) { \
RAW_LOG_INFO(__VA_ARGS__); \ RAW_LOG_INFO(__VA_ARGS__); \
} \ } \
} while (0) } while (0)
#else #else
#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__) # define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0 #endif // STRIP_LOG == 0
#if !defined(STRIP_LOG) || STRIP_LOG == 0 #if !defined(STRIP_LOG) || STRIP_LOG == 0
#define RAW_LOG_INFO(...) \ # define RAW_LOG_INFO(...) \
google::RawLog__(google::GLOG_INFO, __FILE__, __LINE__, __VA_ARGS__) google::RawLog__(google::GLOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#else #else
#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__) # define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0 #endif // STRIP_LOG == 0
#if !defined(STRIP_LOG) || STRIP_LOG <= 1 #if !defined(STRIP_LOG) || STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) \ # define RAW_LOG_WARNING(...) \
google::RawLog__(google::GLOG_WARNING, __FILE__, __LINE__, __VA_ARGS__) google::RawLog__(google::GLOG_WARNING, __FILE__, __LINE__, __VA_ARGS__)
#else #else
#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__) # define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1 #endif // STRIP_LOG <= 1
#if !defined(STRIP_LOG) || STRIP_LOG <= 2 #if !defined(STRIP_LOG) || STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) \ # define RAW_LOG_ERROR(...) \
google::RawLog__(google::GLOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) google::RawLog__(google::GLOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#else #else
#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__) # define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2 #endif // STRIP_LOG <= 2
#if !defined(STRIP_LOG) || STRIP_LOG <= 3 #if !defined(STRIP_LOG) || STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) \ # define RAW_LOG_FATAL(...) \
google::RawLog__(google::GLOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) google::RawLog__(google::GLOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
#else #else
#define RAW_LOG_FATAL(...) \ # define RAW_LOG_FATAL(...) \
do { \ do { \
google::RawLogStub__(0, __VA_ARGS__); \ google::RawLogStub__(0, __VA_ARGS__); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} while (0) } while (0)
#endif // STRIP_LOG <= 3 #endif // STRIP_LOG <= 3
// Similar to CHECK(condition) << message, // Similar to CHECK(condition) << message,
@ -142,20 +142,20 @@ namespace google {
// Debug versions of RAW_LOG and RAW_CHECK // Debug versions of RAW_LOG and RAW_CHECK
#ifndef NDEBUG #ifndef NDEBUG
#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__) # define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message) # define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
#else // NDEBUG #else // NDEBUG
#define RAW_DLOG(severity, ...) \ # define RAW_DLOG(severity, ...) \
while (false) RAW_LOG(severity, __VA_ARGS__) while (false) RAW_LOG(severity, __VA_ARGS__)
#define RAW_DCHECK(condition, message) \ # define RAW_DCHECK(condition, message) \
while (false) RAW_CHECK(condition, message) while (false) RAW_CHECK(condition, message)
#endif // NDEBUG #endif // NDEBUG
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
// Stub log function used to work around for unused variable warnings when // Stub log function used to work around for unused variable warnings when
@ -169,9 +169,9 @@ static inline void RawLogStub__(int /* ignored */, ...) {}
GLOG_EXPORT void RawLog__(LogSeverity severity, const char* file, int line, GLOG_EXPORT void RawLog__(LogSeverity severity, const char* file, int line,
const char* format, ...) const char* format, ...)
#if defined(__has_attribute) #if defined(__has_attribute)
#if __has_attribute(used) # if __has_attribute(used)
__attribute__((__format__(__printf__, 4, 5))) __attribute__((__format__(__printf__, 4, 5)))
#endif # endif
#endif #endif
; ;
} // namespace google } // namespace google

View File

@ -72,20 +72,21 @@
// it's either FLAGS_v or an appropriate internal variable // it's either FLAGS_v or an appropriate internal variable
// matching the current source file that represents results of // matching the current source file that represents results of
// parsing of --vmodule flag and/or SetVLOGLevel calls. // parsing of --vmodule flag and/or SetVLOGLevel calls.
#define VLOG_IS_ON(verboselevel) \ # define VLOG_IS_ON(verboselevel) \
__extension__({ \ __extension__({ \
static google::SiteFlag vlocal__ = {nullptr, nullptr, 0, nullptr}; \ static google::SiteFlag vlocal__ = {nullptr, nullptr, 0, nullptr}; \
GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized( \ GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized( \
__FILE__, __LINE__, &vlocal__, sizeof(google::SiteFlag), "")); \ __FILE__, __LINE__, &vlocal__, sizeof(google::SiteFlag), "")); \
google::int32 verbose_level__ = (verboselevel); \ google::int32 verbose_level__ = (verboselevel); \
(vlocal__.level == nullptr \ (vlocal__.level == nullptr \
? google::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, verbose_level__) \ ? google::InitVLOG3__(&vlocal__, &FLAGS_v, __FILE__, \
: *vlocal__.level >= verbose_level__); \ verbose_level__) \
}) : *vlocal__.level >= verbose_level__); \
})
#else #else
// GNU extensions not available, so we do not support --vmodule. // GNU extensions not available, so we do not support --vmodule.
// Dynamic value of FLAGS_v always controls the logging level. // Dynamic value of FLAGS_v always controls the logging level.
#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel)) # define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
#endif #endif
// Set VLOG(_IS_ON) level for module_pattern to log_level. // Set VLOG(_IS_ON) level for module_pattern to log_level.

View File

@ -31,7 +31,7 @@
// (based on googletest: http://code.google.com/p/googletest/) // (based on googletest: http://code.google.com/p/googletest/)
#ifdef GOOGLETEST_H__ #ifdef GOOGLETEST_H__
#error You must not include this file twice. # error You must not include this file twice.
#endif #endif
#define GOOGLETEST_H__ #define GOOGLETEST_H__
@ -53,15 +53,15 @@
#include "utilities.h" #include "utilities.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#include "base/commandlineflags.h" #include "base/commandlineflags.h"
#if __cplusplus < 201103L && !defined(_MSC_VER) #if __cplusplus < 201103L && !defined(_MSC_VER)
#define GOOGLE_GLOG_THROW_BAD_ALLOC throw (std::bad_alloc) # define GOOGLE_GLOG_THROW_BAD_ALLOC throw(std::bad_alloc)
#else #else
#define GOOGLE_GLOG_THROW_BAD_ALLOC # define GOOGLE_GLOG_THROW_BAD_ALLOC
#endif #endif
using std::map; using std::map;
@ -95,7 +95,7 @@ static inline string GetTempDir() {
// (e.g., glog/vsproject/logging_unittest). // (e.g., glog/vsproject/logging_unittest).
static const char TEST_SRC_DIR[] = "../.."; static const char TEST_SRC_DIR[] = "../..";
#elif !defined(TEST_SRC_DIR) #elif !defined(TEST_SRC_DIR)
# warning TEST_SRC_DIR should be defined in config.h # warning TEST_SRC_DIR should be defined in config.h
static const char TEST_SRC_DIR[] = "."; static const char TEST_SRC_DIR[] = ".";
#endif #endif
@ -112,10 +112,10 @@ DEFINE_int32(benchmark_iters, 100000, "Number of iterations per benchmark");
#endif #endif
#ifdef HAVE_LIB_GTEST #ifdef HAVE_LIB_GTEST
# include <gtest/gtest.h> # include <gtest/gtest.h>
// Use our ASSERT_DEATH implementation. // Use our ASSERT_DEATH implementation.
# undef ASSERT_DEATH # undef ASSERT_DEATH
# undef ASSERT_DEBUG_DEATH # undef ASSERT_DEBUG_DEATH
using testing::InitGoogleTest; using testing::InitGoogleTest;
#else #else
@ -127,81 +127,83 @@ void InitGoogleTest(int*, char**) {}
// The following is some bare-bones testing infrastructure // The following is some bare-bones testing infrastructure
#define EXPECT_NEAR(val1, val2, abs_error) \ # define EXPECT_NEAR(val1, val2, abs_error) \
do { \ do { \
if (abs(val1 - val2) > abs_error) { \ if (abs(val1 - val2) > abs_error) { \
fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, #abs_error, \ fprintf(stderr, "Check failed: %s within %s of %s\n", #val1, \
#val2); \ #abs_error, #val2); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#define EXPECT_TRUE(cond) \ # define EXPECT_TRUE(cond) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
fprintf(stderr, "Check failed: %s\n", #cond); \ fprintf(stderr, "Check failed: %s\n", #cond); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond)) # define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
#define EXPECT_OP(op, val1, val2) \ # define EXPECT_OP(op, val1, val2) \
do { \ do { \
if (!((val1) op (val2))) { \ if (!((val1)op(val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \ fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2) # define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2) # define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2) # define EXPECT_GT(val1, val2) EXPECT_OP(>, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2) # define EXPECT_LT(val1, val2) EXPECT_OP(<, val1, val2)
#define EXPECT_NAN(arg) \ # define EXPECT_NAN(arg) \
do { \ do { \
if (!isnan(arg)) { \ if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \ fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#define EXPECT_INF(arg) \ # define EXPECT_INF(arg) \
do { \ do { \
if (!isinf(arg)) { \ if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \ fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#define EXPECT_DOUBLE_EQ(val1, val2) \ # define EXPECT_DOUBLE_EQ(val1, val2) \
do { \ do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \ if (((val1) < (val2)-0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \ fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#define EXPECT_STREQ(val1, val2) \ # define EXPECT_STREQ(val1, val2) \
do { \ do { \
if (strcmp((val1), (val2)) != 0) { \ if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \ fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
vector<void (*)()> g_testlist; // the tests to run vector<void (*)()> g_testlist; // the tests to run
#define TEST(a, b) \ # define TEST(a, b) \
struct Test_##a##_##b { \ struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \ Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { FlagSaver fs; RunTest(); } \ static void Run() { \
static void RunTest(); \ FlagSaver fs; \
}; \ RunTest(); \
static Test_##a##_##b g_test_##a##_##b; \ } \
void Test_##a##_##b::RunTest() static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
static inline int RUN_ALL_TESTS() { static inline int RUN_ALL_TESTS() {
vector<void (*)()>::const_iterator it; vector<void (*)()>::const_iterator it;
@ -228,33 +230,33 @@ static inline void CalledAbort() {
#ifdef GLOG_OS_WINDOWS #ifdef GLOG_OS_WINDOWS
// TODO(hamaji): Death test somehow doesn't work in Windows. // TODO(hamaji): Death test somehow doesn't work in Windows.
#define ASSERT_DEATH(fn, msg) # define ASSERT_DEATH(fn, msg)
#else #else
#define ASSERT_DEATH(fn, msg) \ # define ASSERT_DEATH(fn, msg) \
do { \ do { \
g_called_abort = false; \ g_called_abort = false; \
/* in logging.cc */ \ /* in logging.cc */ \
void (*original_logging_fail_func)() = g_logging_fail_func; \ void (*original_logging_fail_func)() = g_logging_fail_func; \
g_logging_fail_func = &CalledAbort; \ g_logging_fail_func = &CalledAbort; \
if (!setjmp(g_jmp_buf)) fn; \ if (!setjmp(g_jmp_buf)) fn; \
/* set back to their default */ \ /* set back to their default */ \
g_logging_fail_func = original_logging_fail_func; \ g_logging_fail_func = original_logging_fail_func; \
if (!g_called_abort) { \ if (!g_called_abort) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \ fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)
#endif #endif
#ifdef NDEBUG #ifdef NDEBUG
#define ASSERT_DEBUG_DEATH(fn, msg) # define ASSERT_DEBUG_DEATH(fn, msg)
#else #else
#define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg) # define ASSERT_DEBUG_DEATH(fn, msg) ASSERT_DEATH(fn, msg)
#endif // NDEBUG #endif // NDEBUG
// Benchmark tools. // Benchmark tools.
#define BENCHMARK(n) static BenchmarkRegisterer __benchmark_ ## n (#n, &n); #define BENCHMARK(n) static BenchmarkRegisterer __benchmark_##n(#n, &n);
map<string, void (*)(int)> g_benchlist; // the benchmarks to run map<string, void (*)(int)> g_benchlist; // the benchmarks to run
@ -278,13 +280,13 @@ static inline void RunSpecifiedBenchmarks() {
double elapsed_ns = (static_cast<double>(clock()) - start) / double elapsed_ns = (static_cast<double>(clock()) - start) /
CLOCKS_PER_SEC * 1000 * 1000 * 1000; CLOCKS_PER_SEC * 1000 * 1000 * 1000;
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat=" # pragma GCC diagnostic ignored "-Wformat="
#endif #endif
printf("%s\t%8.2lf\t%10d\n", iter.first.c_str(), elapsed_ns / iter_cnt, printf("%s\t%8.2lf\t%10d\n", iter.first.c_str(), elapsed_ns / iter_cnt,
iter_cnt); iter_cnt);
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
} }
puts(""); puts("");
@ -317,8 +319,7 @@ class CapturedStream {
CHECK(uncaptured_fd_ != -1); CHECK(uncaptured_fd_ != -1);
// Open file to save stream to // Open file to save stream to
int cap_fd = open(filename_.c_str(), int cap_fd = open(filename_.c_str(), O_CREAT | O_TRUNC | O_WRONLY,
O_CREAT | O_TRUNC | O_WRONLY,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
CHECK(cap_fd != -1); CHECK(cap_fd != -1);
@ -337,18 +338,18 @@ class CapturedStream {
} }
} }
const string & filename() const { return filename_; } const string& filename() const { return filename_; }
private: private:
int fd_; // file descriptor being captured int fd_; // file descriptor being captured
int uncaptured_fd_{-1}; // where the stream was originally being sent to int uncaptured_fd_{-1}; // where the stream was originally being sent to
string filename_; // file where stream is being saved string filename_; // file where stream is being saved
}; };
static CapturedStream * s_captured_streams[STDERR_FILENO+1]; static CapturedStream* s_captured_streams[STDERR_FILENO + 1];
// Redirect a file descriptor to a file. // Redirect a file descriptor to a file.
// fd - Should be STDOUT_FILENO or STDERR_FILENO // fd - Should be STDOUT_FILENO or STDERR_FILENO
// filename - File where output should be stored // filename - File where output should be stored
static inline void CaptureTestOutput(int fd, const string & filename) { static inline void CaptureTestOutput(int fd, const string& filename) {
CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO)); CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO));
CHECK(s_captured_streams[fd] == nullptr); CHECK(s_captured_streams[fd] == nullptr);
s_captured_streams[fd] = new CapturedStream(fd, filename); s_captured_streams[fd] = new CapturedStream(fd, filename);
@ -360,14 +361,14 @@ static inline void CaptureTestStderr() {
CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err"); CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err");
} }
// Return the size (in bytes) of a file // Return the size (in bytes) of a file
static inline size_t GetFileSize(FILE * file) { static inline size_t GetFileSize(FILE* file) {
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file)); return static_cast<size_t>(ftell(file));
} }
// Read the entire content of a file as a string // Read the entire content of a file as a string
static inline string ReadEntireFile(FILE * file) { static inline string ReadEntireFile(FILE* file) {
const size_t file_size = GetFileSize(file); const size_t file_size = GetFileSize(file);
char * const buffer = new char[file_size]; char* const buffer = new char[file_size];
size_t bytes_last_read = 0; // # of bytes read in the last fread() size_t bytes_last_read = 0; // # of bytes read in the last fread()
size_t bytes_read = 0; // # of bytes read so far size_t bytes_read = 0; // # of bytes read so far
@ -377,11 +378,12 @@ static inline string ReadEntireFile(FILE * file) {
// Keep reading the file until we cannot read further or the // Keep reading the file until we cannot read further or the
// pre-determined file size is reached. // pre-determined file size is reached.
do { do {
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); bytes_last_read =
fread(buffer + bytes_read, 1, file_size - bytes_read, file);
bytes_read += bytes_last_read; bytes_read += bytes_last_read;
} while (bytes_last_read > 0 && bytes_read < file_size); } while (bytes_last_read > 0 && bytes_read < file_size);
const string content = string(buffer, buffer+bytes_read); const string content = string(buffer, buffer + bytes_read);
delete[] buffer; delete[] buffer;
return content; return content;
@ -390,15 +392,14 @@ static inline string ReadEntireFile(FILE * file) {
// fd is STDERR_FILENO) as a string // fd is STDERR_FILENO) as a string
static inline string GetCapturedTestOutput(int fd) { static inline string GetCapturedTestOutput(int fd) {
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO); CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO);
CapturedStream * const cap = s_captured_streams[fd]; CapturedStream* const cap = s_captured_streams[fd];
CHECK(cap) CHECK(cap) << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
<< ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
// Make sure everything is flushed. // Make sure everything is flushed.
cap->StopCapture(); cap->StopCapture();
// Read the captured file. // Read the captured file.
FILE * const file = fopen(cap->filename().c_str(), "r"); FILE* const file = fopen(cap->filename().c_str(), "r");
const string content = ReadEntireFile(file); const string content = ReadEntireFile(file);
fclose(file); fclose(file);
@ -421,7 +422,7 @@ static inline bool IsLoggingPrefix(const string& s) {
} }
if (!strchr("IWEF", s[0])) return false; if (!strchr("IWEF", s[0])) return false;
for (size_t i = 1; i <= 8; ++i) { for (size_t i = 1; i <= 8; ++i) {
if (!isdigit(s[i]) && s[i] != "YEARDATE"[i-1]) return false; if (!isdigit(s[i]) && s[i] != "YEARDATE"[i - 1]) return false;
} }
return true; return true;
} }
@ -461,16 +462,15 @@ static inline string MungeLine(const string& line) {
} }
size_t index = thread_lineinfo.find(':'); size_t index = thread_lineinfo.find(':');
CHECK_NE(string::npos, index); CHECK_NE(string::npos, index);
thread_lineinfo = thread_lineinfo.substr(0, index+1) + "LINE]"; thread_lineinfo = thread_lineinfo.substr(0, index + 1) + "LINE]";
string rest; string rest;
std::getline(iss, rest); std::getline(iss, rest);
return (before + logcode_date[0] + "YEARDATE TIME__ " + thread_lineinfo + return (before + logcode_date[0] + "YEARDATE TIME__ " + thread_lineinfo +
MungeLine(rest)); MungeLine(rest));
} }
static inline void StringReplace(string* str, static inline void StringReplace(string* str, const string& oldsub,
const string& oldsub, const string& newsub) {
const string& newsub) {
size_t pos = str->find(oldsub); size_t pos = str->find(oldsub);
if (pos != string::npos) { if (pos != string::npos) {
str->replace(pos, oldsub.size(), newsub); str->replace(pos, oldsub.size(), newsub);
@ -589,9 +589,7 @@ class Thread {
handle_ = CreateThread(nullptr, 0, &Thread::InvokeThreadW, this, 0, &th_); handle_ = CreateThread(nullptr, 0, &Thread::InvokeThreadW, this, 0, &th_);
CHECK(handle_) << "CreateThread"; CHECK(handle_) << "CreateThread";
} }
void Join() { void Join() { WaitForSingleObject(handle_, INFINITE); }
WaitForSingleObject(handle_, INFINITE);
}
#elif defined(HAVE_PTHREAD) #elif defined(HAVE_PTHREAD)
void Start() { pthread_create(&th_, nullptr, &Thread::InvokeThread, this); } void Start() { pthread_create(&th_, nullptr, &Thread::InvokeThread, this); }
void Join() { pthread_join(th_, nullptr); } void Join() { pthread_join(th_, nullptr); }
@ -623,12 +621,12 @@ class Thread {
static inline void SleepForMilliseconds(unsigned t) { static inline void SleepForMilliseconds(unsigned t) {
#ifndef GLOG_OS_WINDOWS #ifndef GLOG_OS_WINDOWS
# if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L # if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L
const struct timespec req = {0, t * 1000 * 1000}; const struct timespec req = {0, t * 1000 * 1000};
nanosleep(&req, nullptr); nanosleep(&req, nullptr);
# else # else
usleep(t * 1000); usleep(t * 1000);
# endif # endif
#else #else
Sleep(t); Sleep(t);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -29,19 +29,19 @@
// //
// Author: Ray Sidney // Author: Ray Sidney
#include <fcntl.h>
#include "config.h" #include "config.h"
#include "utilities.h" #include "utilities.h"
#include <fcntl.h>
#ifdef HAVE_GLOB_H #ifdef HAVE_GLOB_H
# include <glob.h> # include <glob.h>
#endif #endif
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#ifdef HAVE_SYS_WAIT_H #ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h> # include <sys/wait.h>
#endif #endif
#include <cstdio> #include <cstdio>
@ -63,13 +63,14 @@
DECLARE_string(log_backtrace_at); // logging.cc DECLARE_string(log_backtrace_at); // logging.cc
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
#ifdef HAVE_LIB_GMOCK #ifdef HAVE_LIB_GMOCK
#include <gmock/gmock.h> # include <gmock/gmock.h>
#include "mock-log.h"
# include "mock-log.h"
// Introduce several symbols from gmock. // Introduce several symbols from gmock.
using google::glog_testing::ScopedMockLog; using google::glog_testing::ScopedMockLog;
using testing::_; using testing::_;
@ -132,7 +133,8 @@ static void BM_Check1(int n) {
} }
BENCHMARK(BM_Check1) BENCHMARK(BM_Check1)
static void CheckFailure(int a, int b, const char* file, int line, const char* msg); static void CheckFailure(int a, int b, const char* file, int line,
const char* msg);
static void BM_Check3(int n) { static void BM_Check3(int n) {
while (n-- > 0) { while (n-- > 0) {
if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x"); if (n < x) CheckFailure(n, x, __FILE__, __LINE__, "n < x");
@ -165,8 +167,7 @@ static void BM_Check2(int n) {
BENCHMARK(BM_Check2) BENCHMARK(BM_Check2)
static void CheckFailure(int, int, const char* /* file */, int /* line */, static void CheckFailure(int, int, const char* /* file */, int /* line */,
const char* /* msg */) { const char* /* msg */) {}
}
static void BM_logspeed(int n) { static void BM_logspeed(int n) {
while (n-- > 0) { while (n-- > 0) {
@ -182,31 +183,24 @@ static void BM_vlog(int n) {
} }
BENCHMARK(BM_vlog) BENCHMARK(BM_vlog)
// Dynamically generate a prefix using the default format and write it to the stream. // Dynamically generate a prefix using the default format and write it to the
void PrefixAttacher(std::ostream &s, const LogMessageInfo &l, void* data) { // stream.
void PrefixAttacher(std::ostream& s, const LogMessageInfo& l, void* data) {
// Assert that `data` contains the expected contents before producing the // Assert that `data` contains the expected contents before producing the
// prefix (otherwise causing the tests to fail): // prefix (otherwise causing the tests to fail):
if (data == nullptr || *static_cast<string*>(data) != "good data") { if (data == nullptr || *static_cast<string*>(data) != "good data") {
return; return;
} }
s << l.severity[0] s << l.severity[0] << setw(4) << 1900 + l.time.year() << setw(2)
<< setw(4) << 1900 + l.time.year() << 1 + l.time.month() << setw(2) << l.time.day() << ' ' << setw(2)
<< setw(2) << 1 + l.time.month() << l.time.hour() << ':' << setw(2) << l.time.min() << ':' << setw(2)
<< setw(2) << l.time.day() << l.time.sec() << "." << setw(6) << l.time.usec() << ' ' << setfill(' ')
<< ' ' << setw(5) << l.thread_id << setfill('0') << ' ' << l.filename << ':'
<< setw(2) << l.time.hour() << ':' << l.line_number << "]";
<< setw(2) << l.time.min() << ':'
<< setw(2) << l.time.sec() << "."
<< setw(6) << l.time.usec()
<< ' '
<< setfill(' ') << setw(5)
<< l.thread_id << setfill('0')
<< ' '
<< l.filename << ':' << l.line_number << "]";
} }
int main(int argc, char **argv) { int main(int argc, char** argv) {
FLAGS_colorlogtostderr = false; FLAGS_colorlogtostderr = false;
FLAGS_timestamp_in_logfile_name = true; FLAGS_timestamp_in_logfile_name = true;
@ -216,8 +210,8 @@ int main(int argc, char **argv) {
// Test some basics before InitGoogleLogging: // Test some basics before InitGoogleLogging:
CaptureTestStderr(); CaptureTestStderr();
LogWithLevels(FLAGS_v, FLAGS_stderrthreshold, LogWithLevels(FLAGS_v, FLAGS_stderrthreshold, FLAGS_logtostderr,
FLAGS_logtostderr, FLAGS_alsologtostderr); FLAGS_alsologtostderr);
LogWithLevels(0, 0, false, false); // simulate "before global c-tors" LogWithLevels(0, 0, false, false); // simulate "before global c-tors"
const string early_stderr = GetCapturedTestStderr(); const string early_stderr = GetCapturedTestStderr();
@ -226,7 +220,8 @@ int main(int argc, char **argv) {
// Setting a custom prefix generator (it will use the default format so that // Setting a custom prefix generator (it will use the default format so that
// the golden outputs can be reused): // the golden outputs can be reused):
string prefix_attacher_data = "good data"; string prefix_attacher_data = "good data";
InitGoogleLogging(argv[0], &PrefixAttacher, static_cast<void*>(&prefix_attacher_data)); InitGoogleLogging(argv[0], &PrefixAttacher,
static_cast<void*>(&prefix_attacher_data));
EXPECT_TRUE(IsGoogleLoggingInitialized()); EXPECT_TRUE(IsGoogleLoggingInitialized());
@ -249,7 +244,8 @@ int main(int argc, char **argv) {
CaptureTestStderr(); CaptureTestStderr();
// re-emit early_stderr // re-emit early_stderr
LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << early_stderr; LogMessage("dummy", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
<< early_stderr;
TestLogging(true); TestLogging(true);
TestRawLogging(); TestRawLogging();
@ -301,12 +297,12 @@ int main(int argc, char **argv) {
} }
void TestLogging(bool check_counts) { void TestLogging(bool check_counts) {
int64 base_num_infos = LogMessage::num_messages(GLOG_INFO); int64 base_num_infos = LogMessage::num_messages(GLOG_INFO);
int64 base_num_warning = LogMessage::num_messages(GLOG_WARNING); int64 base_num_warning = LogMessage::num_messages(GLOG_WARNING);
int64 base_num_errors = LogMessage::num_messages(GLOG_ERROR); int64 base_num_errors = LogMessage::num_messages(GLOG_ERROR);
LOG(INFO) << string("foo ") << "bar " << 10 << ' ' << 3.4; LOG(INFO) << string("foo ") << "bar " << 10 << ' ' << 3.4;
for ( int i = 0; i < 10; ++i ) { for (int i = 0; i < 10; ++i) {
int old_errno = errno; int old_errno = errno;
errno = i; errno = i;
PLOG_EVERY_N(ERROR, 2) << "Plog every 2, iteration " << COUNTER; PLOG_EVERY_N(ERROR, 2) << "Plog every 2, iteration " << COUNTER;
@ -330,7 +326,7 @@ void TestLogging(bool check_counts) {
const char const_s[] = "const array"; const char const_s[] = "const array";
LOG(INFO) << const_s; LOG(INFO) << const_s;
int j = 1000; int j = 1000;
LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " " LOG(ERROR) << string("foo") << ' ' << j << ' ' << setw(10) << j << " "
<< setw(1) << hex << j; << setw(1) << hex << j;
LOG(INFO) << "foo " << std::setw(10) << 1.0; LOG(INFO) << "foo " << std::setw(10) << 1.0;
@ -341,32 +337,27 @@ void TestLogging(bool check_counts) {
LOG(ERROR) << "inner"; LOG(ERROR) << "inner";
} }
LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix"; LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream()
<< "no prefix";
if (check_counts) { if (check_counts) {
CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO)); CHECK_EQ(base_num_infos + 15, LogMessage::num_messages(GLOG_INFO));
CHECK_EQ(base_num_warning + 3, LogMessage::num_messages(GLOG_WARNING)); CHECK_EQ(base_num_warning + 3, LogMessage::num_messages(GLOG_WARNING));
CHECK_EQ(base_num_errors + 17, LogMessage::num_messages(GLOG_ERROR)); CHECK_EQ(base_num_errors + 17, LogMessage::num_messages(GLOG_ERROR));
} }
} }
static void NoAllocNewHook() { static void NoAllocNewHook() { LOG(FATAL) << "unexpected new"; }
LOG(FATAL) << "unexpected new";
}
struct NewHook { struct NewHook {
NewHook() { NewHook() { g_new_hook = &NoAllocNewHook; }
g_new_hook = &NoAllocNewHook;
}
~NewHook() { g_new_hook = nullptr; } ~NewHook() { g_new_hook = nullptr; }
}; };
TEST(DeathNoAllocNewHook, logging) { TEST(DeathNoAllocNewHook, logging) {
// tests that NewHook used below works // tests that NewHook used below works
NewHook new_hook; NewHook new_hook;
ASSERT_DEATH({ ASSERT_DEATH({ new int; }, "unexpected new");
new int;
}, "unexpected new");
} }
void TestRawLogging() { void TestRawLogging() {
@ -425,8 +416,8 @@ void TestRawLogging() {
void LogWithLevels(int v, int severity, bool err, bool alsoerr) { void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
RAW_LOG(INFO, RAW_LOG(INFO,
"Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d", "Test: v=%d stderrthreshold=%d logtostderr=%d alsologtostderr=%d", v,
v, severity, err, alsoerr); severity, err, alsoerr);
FlagSaver saver; FlagSaver saver;
@ -463,28 +454,48 @@ void LogWithLevels(int v, int severity, bool err, bool alsoerr) {
LOG_IF(ERROR, false) << "don't log_if error"; LOG_IF(ERROR, false) << "don't log_if error";
int c; int c;
c = 1; VLOG_IF(100, c -= 2) << "vlog_if 100 expr"; EXPECT_EQ(c, -1); c = 1;
c = 1; VLOG_IF(0, c -= 2) << "vlog_if 0 expr"; EXPECT_EQ(c, -1); VLOG_IF(100, c -= 2) << "vlog_if 100 expr";
c = 1; LOG_IF(INFO, c -= 2) << "log_if info expr"; EXPECT_EQ(c, -1); EXPECT_EQ(c, -1);
c = 1; LOG_IF(ERROR, c -= 2) << "log_if error expr"; EXPECT_EQ(c, -1); c = 1;
c = 2; VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr"; EXPECT_EQ(c, 0); VLOG_IF(0, c -= 2) << "vlog_if 0 expr";
c = 2; LOG_IF(ERROR, c -= 2) << "don't log_if error expr"; EXPECT_EQ(c, 0); EXPECT_EQ(c, -1);
c = 1;
LOG_IF(INFO, c -= 2) << "log_if info expr";
EXPECT_EQ(c, -1);
c = 1;
LOG_IF(ERROR, c -= 2) << "log_if error expr";
EXPECT_EQ(c, -1);
c = 2;
VLOG_IF(0, c -= 2) << "don't vlog_if 0 expr";
EXPECT_EQ(c, 0);
c = 2;
LOG_IF(ERROR, c -= 2) << "don't log_if error expr";
EXPECT_EQ(c, 0);
c = 3; LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr"; c = 3;
LOG_IF_EVERY_N(INFO, c -= 4, 1) << "log_if info every 1 expr";
EXPECT_EQ(c, -1); EXPECT_EQ(c, -1);
c = 3; LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr"; c = 3;
LOG_IF_EVERY_N(ERROR, c -= 4, 1) << "log_if error every 1 expr";
EXPECT_EQ(c, -1); EXPECT_EQ(c, -1);
c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr"; c = 4;
LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if info every 3 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
c = 4; LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr"; c = 4;
LOG_IF_EVERY_N(ERROR, c -= 4, 3) << "don't log_if error every 3 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
c = 5; VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr"; c = 5;
VLOG_IF_EVERY_N(0, c -= 4, 1) << "vlog_if 0 every 1 expr";
EXPECT_EQ(c, 1); EXPECT_EQ(c, 1);
c = 5; VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr"; c = 5;
VLOG_IF_EVERY_N(100, c -= 4, 3) << "vlog_if 100 every 3 expr";
EXPECT_EQ(c, 1); EXPECT_EQ(c, 1);
c = 6; VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr"; c = 6;
VLOG_IF_EVERY_N(0, c -= 6, 1) << "don't vlog_if 0 every 1 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
c = 6; VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr"; c = 6;
VLOG_IF_EVERY_N(100, c -= 6, 3) << "don't vlog_if 100 every 1 expr";
EXPECT_EQ(c, 0); EXPECT_EQ(c, 0);
} }
@ -523,19 +534,24 @@ TEST(DeathRawCHECK, logging) {
ASSERT_DEATH(RAW_CHECK(false, "failure 1"), ASSERT_DEATH(RAW_CHECK(false, "failure 1"),
"RAW: Check false failed: failure 1"); "RAW: Check false failed: failure 1");
ASSERT_DEBUG_DEATH(RAW_DCHECK(1 == 2, "failure 2"), ASSERT_DEBUG_DEATH(RAW_DCHECK(1 == 2, "failure 2"),
"RAW: Check 1 == 2 failed: failure 2"); "RAW: Check 1 == 2 failed: failure 2");
} }
void TestLogString() { void TestLogString() {
vector<string> errors; vector<string> errors;
vector<string>* no_errors = nullptr; vector<string>* no_errors = nullptr;
LOG_STRING(INFO, &errors) << "LOG_STRING: " << "collected info"; LOG_STRING(INFO, &errors) << "LOG_STRING: "
LOG_STRING(WARNING, &errors) << "LOG_STRING: " << "collected warning"; << "collected info";
LOG_STRING(ERROR, &errors) << "LOG_STRING: " << "collected error"; LOG_STRING(WARNING, &errors) << "LOG_STRING: "
<< "collected warning";
LOG_STRING(ERROR, &errors) << "LOG_STRING: "
<< "collected error";
LOG_STRING(INFO, no_errors) << "LOG_STRING: " << "reported info"; LOG_STRING(INFO, no_errors) << "LOG_STRING: "
LOG_STRING(WARNING, no_errors) << "LOG_STRING: " << "reported warning"; << "reported info";
LOG_STRING(WARNING, no_errors) << "LOG_STRING: "
<< "reported warning";
LOG_STRING(ERROR, nullptr) << "LOG_STRING: " LOG_STRING(ERROR, nullptr) << "LOG_STRING: "
<< "reported error"; << "reported error";
@ -548,15 +564,20 @@ void TestLogToString() {
string error; string error;
string* no_error = nullptr; string* no_error = nullptr;
LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: " << "collected info"; LOG_TO_STRING(INFO, &error) << "LOG_TO_STRING: "
<< "collected info";
LOG(INFO) << "Captured by LOG_TO_STRING: " << error; LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: " << "collected warning"; LOG_TO_STRING(WARNING, &error) << "LOG_TO_STRING: "
<< "collected warning";
LOG(INFO) << "Captured by LOG_TO_STRING: " << error; LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: " << "collected error"; LOG_TO_STRING(ERROR, &error) << "LOG_TO_STRING: "
<< "collected error";
LOG(INFO) << "Captured by LOG_TO_STRING: " << error; LOG(INFO) << "Captured by LOG_TO_STRING: " << error;
LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: " << "reported info"; LOG_TO_STRING(INFO, no_error) << "LOG_TO_STRING: "
LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: " << "reported warning"; << "reported info";
LOG_TO_STRING(WARNING, no_error) << "LOG_TO_STRING: "
<< "reported warning";
LOG_TO_STRING(ERROR, nullptr) << "LOG_TO_STRING: " LOG_TO_STRING(ERROR, nullptr) << "LOG_TO_STRING: "
<< "reported error"; << "reported error";
} }
@ -568,8 +589,8 @@ class TestLogSinkImpl : public LogSink {
const char* base_filename, int line, const char* base_filename, int line,
const LogMessageTime& logmsgtime, const char* message, const LogMessageTime& logmsgtime, const char* message,
size_t message_len) override { size_t message_len) override {
errors.push_back( errors.push_back(ToString(severity, base_filename, line, logmsgtime,
ToString(severity, base_filename, line, logmsgtime, message, message_len)); message, message_len));
} }
}; };
@ -577,26 +598,36 @@ void TestLogSink() {
TestLogSinkImpl sink; TestLogSinkImpl sink;
LogSink* no_sink = nullptr; LogSink* no_sink = nullptr;
LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: " << "collected info"; LOG_TO_SINK(&sink, INFO) << "LOG_TO_SINK: "
LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: " << "collected warning"; << "collected info";
LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: " << "collected error"; LOG_TO_SINK(&sink, WARNING) << "LOG_TO_SINK: "
<< "collected warning";
LOG_TO_SINK(&sink, ERROR) << "LOG_TO_SINK: "
<< "collected error";
LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: " << "reported info"; LOG_TO_SINK(no_sink, INFO) << "LOG_TO_SINK: "
LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: " << "reported warning"; << "reported info";
LOG_TO_SINK(no_sink, WARNING) << "LOG_TO_SINK: "
<< "reported warning";
LOG_TO_SINK(nullptr, ERROR) << "LOG_TO_SINK: " LOG_TO_SINK(nullptr, ERROR) << "LOG_TO_SINK: "
<< "reported error"; << "reported error";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, INFO)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected info"; << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "collected info";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, WARNING)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected warning"; << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "collected warning";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(&sink, ERROR)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "collected error"; << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "collected error";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, INFO)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed info"; << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "thrashed info";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(no_sink, WARNING)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "thrashed warning"; << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "thrashed warning";
LOG_TO_SINK_BUT_NOT_TO_LOGFILE(nullptr, ERROR) LOG_TO_SINK_BUT_NOT_TO_LOGFILE(nullptr, ERROR)
<< "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: " << "LOG_TO_SINK_BUT_NOT_TO_LOGFILE: "
<< "thrashed error"; << "thrashed error";
@ -608,10 +639,7 @@ void TestLogSink() {
} }
// For testing using CHECK*() on anonymous enums. // For testing using CHECK*() on anonymous enums.
enum { enum { CASE_A, CASE_B };
CASE_A,
CASE_B
};
void TestCHECK() { void TestCHECK() {
// Tests using CHECK*() on int values. // Tests using CHECK*() on int values.
@ -641,9 +669,9 @@ void TestCHECK() {
void TestDCHECK() { void TestDCHECK() {
#if defined(NDEBUG) #if defined(NDEBUG)
DCHECK( 1 == 2 ) << " DCHECK's shouldn't be compiled in normal mode"; DCHECK(1 == 2) << " DCHECK's shouldn't be compiled in normal mode";
#endif #endif
DCHECK( 1 == 1 ); DCHECK(1 == 1);
DCHECK_EQ(1, 1); DCHECK_EQ(1, 1);
DCHECK_NE(1, 2); DCHECK_NE(1, 2);
DCHECK_GE(1, 1); DCHECK_GE(1, 1);
@ -668,9 +696,8 @@ void TestSTREQ() {
CHECK_STRNE("this", nullptr); CHECK_STRNE("this", nullptr);
CHECK_STRCASENE("this", "that"); CHECK_STRCASENE("this", "that");
CHECK_STRCASENE(nullptr, "that"); CHECK_STRCASENE(nullptr, "that");
CHECK_STREQ((string("a")+"b").c_str(), "ab"); CHECK_STREQ((string("a") + "b").c_str(), "ab");
CHECK_STREQ(string("test").c_str(), CHECK_STREQ(string("test").c_str(), (string("te") + string("st")).c_str());
(string("te") + string("st")).c_str());
} }
TEST(DeathSTREQ, logging) { TEST(DeathSTREQ, logging) {
@ -680,18 +707,18 @@ TEST(DeathSTREQ, logging) {
ASSERT_DEATH(CHECK_STRCASEEQ("this", "siht"), ""); ASSERT_DEATH(CHECK_STRCASEEQ("this", "siht"), "");
ASSERT_DEATH(CHECK_STRNE(nullptr, nullptr), ""); ASSERT_DEATH(CHECK_STRNE(nullptr, nullptr), "");
ASSERT_DEATH(CHECK_STRNE("this", "this"), ""); ASSERT_DEATH(CHECK_STRNE("this", "this"), "");
ASSERT_DEATH(CHECK_STREQ((string("a")+"b").c_str(), "abc"), ""); ASSERT_DEATH(CHECK_STREQ((string("a") + "b").c_str(), "abc"), "");
} }
TEST(CheckNOTNULL, Simple) { TEST(CheckNOTNULL, Simple) {
int64 t; int64 t;
void *ptr = static_cast<void *>(&t); void* ptr = static_cast<void*>(&t);
void *ref = CHECK_NOTNULL(ptr); void* ref = CHECK_NOTNULL(ptr);
EXPECT_EQ(ptr, ref); EXPECT_EQ(ptr, ref);
CHECK_NOTNULL(reinterpret_cast<char *>(ptr)); CHECK_NOTNULL(reinterpret_cast<char*>(ptr));
CHECK_NOTNULL(reinterpret_cast<unsigned char *>(ptr)); CHECK_NOTNULL(reinterpret_cast<unsigned char*>(ptr));
CHECK_NOTNULL(reinterpret_cast<int *>(ptr)); CHECK_NOTNULL(reinterpret_cast<int*>(ptr));
CHECK_NOTNULL(reinterpret_cast<int64 *>(ptr)); CHECK_NOTNULL(reinterpret_cast<int64*>(ptr));
} }
TEST(DeathCheckNN, Simple) { TEST(DeathCheckNN, Simple) {
@ -728,7 +755,7 @@ static void GetFiles(const string& pattern, vector<string>* files) {
LOG_SYSRESULT(GetLastError()); LOG_SYSRESULT(GetLastError());
} }
#else #else
# error There is no way to do glob. # error There is no way to do glob.
#endif #endif
} }
@ -741,8 +768,9 @@ static void DeleteFiles(const string& pattern) {
} }
} }
//check string is in file (or is *NOT*, depending on optional checkInFileOrNot) // check string is in file (or is *NOT*, depending on optional checkInFileOrNot)
static void CheckFile(const string& name, const string& expected_string, const bool checkInFileOrNot = true) { static void CheckFile(const string& name, const string& expected_string,
const bool checkInFileOrNot = true) {
vector<string> files; vector<string> files;
GetFiles(name + "*", &files); GetFiles(name + "*", &files);
CHECK_EQ(files.size(), 1UL); CHECK_EQ(files.size(), 1UL);
@ -760,7 +788,8 @@ static void CheckFile(const string& name, const string& expected_string, const b
} }
} }
fclose(file); fclose(file);
LOG(FATAL) << "Did " << (checkInFileOrNot? "not " : "") << "find " << expected_string << " in " << files[0]; LOG(FATAL) << "Did " << (checkInFileOrNot ? "not " : "") << "find "
<< expected_string << " in " << files[0];
} }
static void TestBasename() { static void TestBasename() {
@ -780,8 +809,11 @@ static void TestBasename() {
} }
static void TestBasenameAppendWhenNoTimestamp() { static void TestBasenameAppendWhenNoTimestamp() {
fprintf(stderr, "==== Test setting log file basename without timestamp and appending properly\n"); fprintf(stderr,
const string dest = FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp"; "==== Test setting log file basename without timestamp and appending "
"properly\n");
const string dest =
FLAGS_test_tmpdir + "/logging_test_basename_append_when_no_timestamp";
DeleteFiles(dest + "*"); DeleteFiles(dest + "*");
ofstream out(dest.c_str()); ofstream out(dest.c_str());
@ -790,13 +822,13 @@ static void TestBasenameAppendWhenNoTimestamp() {
CheckFile(dest, "test preexisting content"); CheckFile(dest, "test preexisting content");
FLAGS_timestamp_in_logfile_name=false; FLAGS_timestamp_in_logfile_name = false;
SetLogDestination(GLOG_INFO, dest.c_str()); SetLogDestination(GLOG_INFO, dest.c_str());
LOG(INFO) << "message to new base, appending to preexisting file"; LOG(INFO) << "message to new base, appending to preexisting file";
FlushLogFiles(GLOG_INFO); FlushLogFiles(GLOG_INFO);
FLAGS_timestamp_in_logfile_name=true; FLAGS_timestamp_in_logfile_name = true;
//if the logging overwrites the file instead of appending it will fail. // if the logging overwrites the file instead of appending it will fail.
CheckFile(dest, "test preexisting content"); CheckFile(dest, "test preexisting content");
CheckFile(dest, "message to new base, appending to preexisting file"); CheckFile(dest, "message to new base, appending to preexisting file");
@ -806,14 +838,18 @@ static void TestBasenameAppendWhenNoTimestamp() {
} }
static void TestTwoProcessesWrite() { static void TestTwoProcessesWrite() {
// test only implemented for platforms with fork & wait; the actual implementation relies on flock // test only implemented for platforms with fork & wait; the actual
// implementation relies on flock
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL) #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL)
fprintf(stderr, "==== Test setting log file basename and two processes writing - second should fail\n"); fprintf(stderr,
const string dest = FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing"; "==== Test setting log file basename and two processes writing - "
"second should fail\n");
const string dest =
FLAGS_test_tmpdir + "/logging_test_basename_two_processes_writing";
DeleteFiles(dest + "*"); DeleteFiles(dest + "*");
//make both processes write into the same file (easier test) // make both processes write into the same file (easier test)
FLAGS_timestamp_in_logfile_name=false; FLAGS_timestamp_in_logfile_name = false;
SetLogDestination(GLOG_INFO, dest.c_str()); SetLogDestination(GLOG_INFO, dest.c_str());
LOG(INFO) << "message to new base, parent"; LOG(INFO) << "message to new base, parent";
FlushLogFiles(GLOG_INFO); FlushLogFiles(GLOG_INFO);
@ -821,16 +857,20 @@ static void TestTwoProcessesWrite() {
pid_t pid = fork(); pid_t pid = fork();
CHECK_ERR(pid); CHECK_ERR(pid);
if (pid == 0) { if (pid == 0) {
LOG(INFO) << "message to new base, child - should only appear on STDERR not on the file"; LOG(INFO) << "message to new base, child - should only appear on STDERR "
ShutdownGoogleLogging(); //for children proc "not on the file";
ShutdownGoogleLogging(); // for children proc
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (pid > 0) { } else if (pid > 0) {
wait(nullptr); wait(nullptr);
} }
FLAGS_timestamp_in_logfile_name=true; FLAGS_timestamp_in_logfile_name = true;
CheckFile(dest, "message to new base, parent"); CheckFile(dest, "message to new base, parent");
CheckFile(dest, "message to new base, child - should only appear on STDERR not on the file", false); CheckFile(dest,
"message to new base, child - should only appear on STDERR not on "
"the file",
false);
// Release // Release
LogToStderr(); LogToStderr();
@ -924,7 +964,7 @@ static void TestErrno() {
CHECK_EQ(errno, ENOENT); CHECK_EQ(errno, ENOENT);
} }
static void TestOneTruncate(const char *path, uint64 limit, uint64 keep, static void TestOneTruncate(const char* path, uint64 limit, uint64 keep,
size_t dsize, size_t ksize, size_t expect) { size_t dsize, size_t ksize, size_t expect) {
int fd; int fd;
CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600)); CHECK_ERR(fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0600));
@ -992,33 +1032,31 @@ static void TestTruncate() {
// MacOSX 10.4 doesn't fail in this case. // MacOSX 10.4 doesn't fail in this case.
// Windows doesn't have symlink. // Windows doesn't have symlink.
// Let's just ignore this test for these cases. // Let's just ignore this test for these cases.
#if !defined(GLOG_OS_MACOSX) && !defined(GLOG_OS_WINDOWS) # if !defined(GLOG_OS_MACOSX) && !defined(GLOG_OS_WINDOWS)
// Through a symlink should fail to truncate // Through a symlink should fail to truncate
string linkname = path + ".link"; string linkname = path + ".link";
unlink(linkname.c_str()); unlink(linkname.c_str());
CHECK_ERR(symlink(path.c_str(), linkname.c_str())); CHECK_ERR(symlink(path.c_str(), linkname.c_str()));
TestOneTruncate(linkname.c_str(), 10, 10, 0, 30, 30); TestOneTruncate(linkname.c_str(), 10, 10, 0, 30, 30);
#endif # endif
// The /proc/self path makes sense only for linux. // The /proc/self path makes sense only for linux.
#if defined(GLOG_OS_LINUX) # if defined(GLOG_OS_LINUX)
// Through an open fd symlink should work // Through an open fd symlink should work
int fd; int fd;
CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY)); CHECK_ERR(fd = open(path.c_str(), O_APPEND | O_WRONLY));
char fdpath[64]; char fdpath[64];
std::snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd); std::snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd);
TestOneTruncate(fdpath, 10, 10, 10, 10, 10); TestOneTruncate(fdpath, 10, 10, 10, 10, 10);
#endif # endif
#endif #endif
} }
struct RecordDeletionLogger : public base::Logger { struct RecordDeletionLogger : public base::Logger {
RecordDeletionLogger(bool* set_on_destruction, RecordDeletionLogger(bool* set_on_destruction, base::Logger* wrapped_logger)
base::Logger* wrapped_logger) : : set_on_destruction_(set_on_destruction),
set_on_destruction_(set_on_destruction), wrapped_logger_(wrapped_logger) {
wrapped_logger_(wrapped_logger)
{
*set_on_destruction_ = false; *set_on_destruction_ = false;
} }
~RecordDeletionLogger() override { *set_on_destruction_ = true; } ~RecordDeletionLogger() override { *set_on_destruction_ = true; }
@ -1074,9 +1112,9 @@ std::ostream& operator<<(std::ostream& stream, LogTimeRecorder& t) {
} }
// get elapsed time in nanoseconds // get elapsed time in nanoseconds
int64 elapsedTime_ns(const std::chrono::steady_clock::time_point& begin, int64 elapsedTime_ns(const std::chrono::steady_clock::time_point& begin,
const std::chrono::steady_clock::time_point& end) { const std::chrono::steady_clock::time_point& end) {
return std::chrono::duration_cast<std::chrono::nanoseconds>((end - begin)) return std::chrono::duration_cast<std::chrono::nanoseconds>((end - begin))
.count(); .count();
} }
static void TestLogPeriodically() { static void TestLogPeriodically() {
@ -1087,16 +1125,16 @@ static void TestLogPeriodically() {
constexpr double LOG_PERIOD_SEC = LogTimes::LOG_PERIOD_NS * 1e-9; constexpr double LOG_PERIOD_SEC = LogTimes::LOG_PERIOD_NS * 1e-9;
while (timeLogger.m_streamTimes < LogTimes::MAX_CALLS) { while (timeLogger.m_streamTimes < LogTimes::MAX_CALLS) {
LOG_EVERY_T(INFO, LOG_PERIOD_SEC) LOG_EVERY_T(INFO, LOG_PERIOD_SEC)
<< timeLogger << "Timed Message #" << timeLogger.m_streamTimes; << timeLogger << "Timed Message #" << timeLogger.m_streamTimes;
} }
// Calculate time between each call in nanoseconds for higher resolution to // Calculate time between each call in nanoseconds for higher resolution to
// minimize error. // minimize error.
int64 nsBetweenCalls[LogTimes::MAX_CALLS - 1]; int64 nsBetweenCalls[LogTimes::MAX_CALLS - 1];
for (size_t i = 1; i < LogTimes::MAX_CALLS; ++i) { for (size_t i = 1; i < LogTimes::MAX_CALLS; ++i) {
nsBetweenCalls[i - 1] = elapsedTime_ns( nsBetweenCalls[i - 1] = elapsedTime_ns(timeLogger.m_callTimes[i - 1],
timeLogger.m_callTimes[i - 1], timeLogger.m_callTimes[i]); timeLogger.m_callTimes[i]);
} }
for (long time_ns : nsBetweenCalls) { for (long time_ns : nsBetweenCalls) {
@ -1107,17 +1145,18 @@ static void TestLogPeriodically() {
namespace google { namespace google {
namespace glog_internal_namespace_ { namespace glog_internal_namespace_ {
extern // in logging.cc extern // in logging.cc
bool SafeFNMatch_(const char* pattern, size_t patt_len, bool
const char* str, size_t str_len); SafeFNMatch_(const char* pattern, size_t patt_len, const char* str,
} // namespace glog_internal_namespace_ size_t str_len);
} // namespace glog_internal_namespace_
using glog_internal_namespace_::SafeFNMatch_; using glog_internal_namespace_::SafeFNMatch_;
} // namespace google } // namespace google
static bool WrapSafeFNMatch(string pattern, string str) { static bool WrapSafeFNMatch(string pattern, string str) {
pattern += "abc"; pattern += "abc";
str += "defgh"; str += "defgh";
return SafeFNMatch_(pattern.data(), pattern.size() - 3, return SafeFNMatch_(pattern.data(), pattern.size() - 3, str.data(),
str.data(), str.size() - 5); str.size() - 5);
} }
TEST(SafeFNMatch, logging) { TEST(SafeFNMatch, logging) {
@ -1184,7 +1223,6 @@ class TestLogSinkWriter : public Thread {
} }
private: private:
// helpers --------------- // helpers ---------------
// For creating a "Condition". // For creating a "Condition".
@ -1239,7 +1277,6 @@ class TestLogSinkWriter : public Thread {
// (that other thread can than use LOG() itself), // (that other thread can than use LOG() itself),
class TestWaitingLogSink : public LogSink { class TestWaitingLogSink : public LogSink {
public: public:
TestWaitingLogSink() { TestWaitingLogSink() {
tid_ = pthread_self(); // for thread-specific behavior tid_ = pthread_self(); // for thread-specific behavior
AddLogSink(this); AddLogSink(this);
@ -1260,18 +1297,17 @@ class TestWaitingLogSink : public LogSink {
// Note: Something like ThreadLocalLogSink is a better choice // Note: Something like ThreadLocalLogSink is a better choice
// to do thread-specific LogSink logic for real. // to do thread-specific LogSink logic for real.
if (pthread_equal(tid_, pthread_self())) { if (pthread_equal(tid_, pthread_self())) {
writer_.Buffer(ToString(severity, base_filename, line, writer_.Buffer(ToString(severity, base_filename, line, logmsgtime,
logmsgtime, message, message_len)); message, message_len));
} }
} }
void WaitTillSent() override { void WaitTillSent() override {
// Wait for Writer thread if we are the original logging thread. // Wait for Writer thread if we are the original logging thread.
if (pthread_equal(tid_, pthread_self())) writer_.Wait(); if (pthread_equal(tid_, pthread_self())) writer_.Wait();
} }
private: private:
pthread_t tid_; pthread_t tid_;
TestLogSinkWriter writer_; TestLogSinkWriter writer_;
}; };
@ -1282,7 +1318,8 @@ static void TestLogSinkWaitTillSent() {
// Clear global_messages here to make sure that this test case can be // Clear global_messages here to make sure that this test case can be
// reentered // reentered
global_messages.clear(); global_messages.clear();
{ TestWaitingLogSink sink; {
TestWaitingLogSink sink;
// Sleeps give the sink threads time to do all their work, // Sleeps give the sink threads time to do all their work,
// so that we get a reliable log capture to compare to the golden file. // so that we get a reliable log capture to compare to the golden file.
LOG(INFO) << "Message 1"; LOG(INFO) << "Message 1";
@ -1300,15 +1337,16 @@ static void TestLogSinkWaitTillSent() {
TEST(Strerror, logging) { TEST(Strerror, logging) {
int errcode = EINTR; int errcode = EINTR;
char *msg = strdup(strerror(errcode)); char* msg = strdup(strerror(errcode));
const size_t buf_size = strlen(msg) + 1; const size_t buf_size = strlen(msg) + 1;
char *buf = new char[buf_size]; char* buf = new char[buf_size];
CHECK_EQ(posix_strerror_r(errcode, nullptr, 0), -1); CHECK_EQ(posix_strerror_r(errcode, nullptr, 0), -1);
buf[0] = 'A'; buf[0] = 'A';
CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1); CHECK_EQ(posix_strerror_r(errcode, buf, 0), -1);
CHECK_EQ(buf[0], 'A'); CHECK_EQ(buf[0], 'A');
CHECK_EQ(posix_strerror_r(errcode, nullptr, buf_size), -1); CHECK_EQ(posix_strerror_r(errcode, nullptr, buf_size), -1);
#if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || defined(GLOG_OS_OPENBSD) #if defined(GLOG_OS_MACOSX) || defined(GLOG_OS_FREEBSD) || \
defined(GLOG_OS_OPENBSD)
// MacOSX or FreeBSD considers this case is an error since there is // MacOSX or FreeBSD considers this case is an error since there is
// no enough space. // no enough space.
CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1); CHECK_EQ(posix_strerror_r(errcode, buf, 1), -1);
@ -1338,12 +1376,12 @@ static void MyCheck(bool a, bool b) {
TEST(DVLog, Basic) { TEST(DVLog, Basic) {
ScopedMockLog log; ScopedMockLog log;
#if defined(NDEBUG) # if defined(NDEBUG)
// We are expecting that nothing is logged. // We are expecting that nothing is logged.
EXPECT_CALL(log, Log(_, _, _)).Times(0); EXPECT_CALL(log, Log(_, _, _)).Times(0);
#else # else
EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "debug log")); EXPECT_CALL(log, Log(GLOG_INFO, __FILE__, "debug log"));
#endif # endif
FLAGS_v = 1; FLAGS_v = 1;
DVLOG(1) << "debug log"; DVLOG(1) << "debug log";
@ -1385,15 +1423,15 @@ TEST(TestExitOnDFatal, ToBeOrNotToBe) {
// We don't die. // We don't die.
{ {
ScopedMockLog log; ScopedMockLog log;
//EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); // EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
// LOG(DFATAL) has severity FATAL if debugging, but is // LOG(DFATAL) has severity FATAL if debugging, but is
// downgraded to ERROR if not debugging. // downgraded to ERROR if not debugging.
const LogSeverity severity = const LogSeverity severity =
#if defined(NDEBUG) # if defined(NDEBUG)
GLOG_ERROR; GLOG_ERROR;
#else # else
GLOG_FATAL; GLOG_FATAL;
#endif # endif
EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal")); EXPECT_CALL(log, Log(severity, __FILE__, "This should not be fatal"));
LOG(DFATAL) << "This should not be fatal"; LOG(DFATAL) << "This should not be fatal";
} }
@ -1402,20 +1440,19 @@ TEST(TestExitOnDFatal, ToBeOrNotToBe) {
base::internal::SetExitOnDFatal(true); base::internal::SetExitOnDFatal(true);
EXPECT_TRUE(base::internal::GetExitOnDFatal()); EXPECT_TRUE(base::internal::GetExitOnDFatal());
#ifdef GTEST_HAS_DEATH_TEST # ifdef GTEST_HAS_DEATH_TEST
// Death comes on little cats' feet. // Death comes on little cats' feet.
EXPECT_DEBUG_DEATH({ EXPECT_DEBUG_DEATH({ LOG(DFATAL) << "This should be fatal in debug mode"; },
LOG(DFATAL) << "This should be fatal in debug mode"; "This should be fatal in debug mode");
}, "This should be fatal in debug mode"); # endif
#endif
} }
#ifdef HAVE_STACKTRACE # ifdef HAVE_STACKTRACE
static void BacktraceAtHelper() { static void BacktraceAtHelper() {
LOG(INFO) << "Not me"; LOG(INFO) << "Not me";
// The vertical spacing of the next 3 lines is significant. // The vertical spacing of the next 3 lines is significant.
LOG(INFO) << "Backtrace me"; LOG(INFO) << "Backtrace me";
} }
static int kBacktraceAtLine = __LINE__ - 2; // The line of the LOG(INFO) above static int kBacktraceAtLine = __LINE__ - 2; // The line of the LOG(INFO) above
@ -1443,19 +1480,19 @@ TEST(LogBacktraceAt, DoesBacktraceAtRightLineWhenEnabled) {
// the name of the containing function, followed by the log message. // the name of the containing function, followed by the log message.
// We use HasSubstr()s instead of ContainsRegex() for environments // We use HasSubstr()s instead of ContainsRegex() for environments
// which don't have regexp. // which don't have regexp.
EXPECT_CALL(log, Log(_, _, AllOf(HasSubstr("stacktrace:"), EXPECT_CALL(
HasSubstr("BacktraceAtHelper"), log, Log(_, _,
HasSubstr("main"), AllOf(HasSubstr("stacktrace:"), HasSubstr("BacktraceAtHelper"),
HasSubstr("Backtrace me")))); HasSubstr("main"), HasSubstr("Backtrace me"))));
// Other LOGs should not include a backtrace. // Other LOGs should not include a backtrace.
EXPECT_CALL(log, Log(_, _, "Not me")); EXPECT_CALL(log, Log(_, _, "Not me"));
BacktraceAtHelper(); BacktraceAtHelper();
} }
#endif // HAVE_STACKTRACE # endif // HAVE_STACKTRACE
#endif // HAVE_LIB_GMOCK #endif // HAVE_LIB_GMOCK
struct UserDefinedClass { struct UserDefinedClass {
bool operator==(const UserDefinedClass&) const { return true; } bool operator==(const UserDefinedClass&) const { return true; }
@ -1480,7 +1517,8 @@ TEST(UserDefinedClass, logging) {
TEST(LogMsgTime, gmtoff) { TEST(LogMsgTime, gmtoff) {
/* /*
* Unit test for GMT offset API * Unit test for GMT offset API
* TODO: To properly test this API, we need a platform independent way to set time-zone. * TODO: To properly test this API, we need a platform independent way to set
* time-zone.
* */ * */
google::LogMessage log_obj(__FILE__, __LINE__); google::LogMessage log_obj(__FILE__, __LINE__);
@ -1488,21 +1526,23 @@ TEST(LogMsgTime, gmtoff) {
// GMT offset ranges from UTC-12:00 to UTC+14:00 // GMT offset ranges from UTC-12:00 to UTC+14:00
const long utc_min_offset = -43200; const long utc_min_offset = -43200;
const long utc_max_offset = 50400; const long utc_max_offset = 50400;
EXPECT_TRUE( (nGmtOff >= utc_min_offset) && (nGmtOff <= utc_max_offset) ); EXPECT_TRUE((nGmtOff >= utc_min_offset) && (nGmtOff <= utc_max_offset));
} }
TEST(EmailLogging, ValidAddress) { TEST(EmailLogging, ValidAddress) {
FlagSaver saver; FlagSaver saver;
FLAGS_logmailer = "/usr/bin/true"; FLAGS_logmailer = "/usr/bin/true";
EXPECT_TRUE(SendEmail("example@example.com", "Example subject", "Example body")); EXPECT_TRUE(
SendEmail("example@example.com", "Example subject", "Example body"));
} }
TEST(EmailLogging, MultipleAddresses) { TEST(EmailLogging, MultipleAddresses) {
FlagSaver saver; FlagSaver saver;
FLAGS_logmailer = "/usr/bin/true"; FLAGS_logmailer = "/usr/bin/true";
EXPECT_TRUE(SendEmail("example@example.com,foo@bar.com", "Example subject", "Example body")); EXPECT_TRUE(SendEmail("example@example.com,foo@bar.com", "Example subject",
"Example body"));
} }
TEST(EmailLogging, InvalidAddress) { TEST(EmailLogging, InvalidAddress) {
@ -1516,5 +1556,6 @@ TEST(EmailLogging, MaliciousAddress) {
FlagSaver saver; FlagSaver saver;
FLAGS_logmailer = "/usr/bin/true"; FLAGS_logmailer = "/usr/bin/true";
EXPECT_FALSE(SendEmail("!/bin/true@example.com", "Example subject", "Example body")); EXPECT_FALSE(
SendEmail("!/bin/true@example.com", "Example subject", "Example body"));
} }

View File

@ -33,11 +33,11 @@
#include "mock-log.h" #include "mock-log.h"
#include <string>
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <string>
namespace { namespace {
using google::GLOG_ERROR; using google::GLOG_ERROR;
@ -57,8 +57,7 @@ TEST(ScopedMockLogTest, InterceptsLog) {
InSequence s; InSequence s;
EXPECT_CALL(log, EXPECT_CALL(log,
Log(GLOG_WARNING, EndsWith("mock-log_unittest.cc"), "Fishy.")); Log(GLOG_WARNING, EndsWith("mock-log_unittest.cc"), "Fishy."));
EXPECT_CALL(log, Log(GLOG_INFO, _, "Working...")) EXPECT_CALL(log, Log(GLOG_INFO, _, "Working...")).Times(2);
.Times(2);
EXPECT_CALL(log, Log(GLOG_ERROR, _, "Bad!!")); EXPECT_CALL(log, Log(GLOG_ERROR, _, "Bad!!"));
LOG(WARNING) << "Fishy."; LOG(WARNING) << "Fishy.";
@ -67,13 +66,9 @@ TEST(ScopedMockLogTest, InterceptsLog) {
LOG(ERROR) << "Bad!!"; LOG(ERROR) << "Bad!!";
} }
void LogBranch() { void LogBranch() { LOG(INFO) << "Logging a branch..."; }
LOG(INFO) << "Logging a branch...";
}
void LogTree() { void LogTree() { LOG(INFO) << "Logging the whole tree..."; }
LOG(INFO) << "Logging the whole tree...";
}
void LogForest() { void LogForest() {
LOG(INFO) << "Logging the entire forest."; LOG(INFO) << "Logging the entire forest.";
@ -99,7 +94,7 @@ TEST(ScopedMockLogTest, LogDuringIntercept) {
} // namespace } // namespace
int main(int argc, char **argv) { int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
testing::InitGoogleMock(&argc, argv); testing::InitGoogleMock(&argc, argv);

View File

@ -1,6 +1,3 @@
#include "glog/logging.h" #include "glog/logging.h"
int main(int /*argc*/, char** argv) int main(int /*argc*/, char** argv) { google::InitGoogleLogging(argv[0]); }
{
google::InitGoogleLogging(argv[0]);
}

View File

@ -37,7 +37,7 @@
#include "utilities.h" #include "utilities.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> // for close() and write() # include <unistd.h> // for close() and write()
#endif #endif
#include <fcntl.h> // for open() #include <fcntl.h> // for open()
@ -49,37 +49,37 @@
#include "glog/raw_logging.h" #include "glog/raw_logging.h"
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
# include "stacktrace.h" # include "stacktrace.h"
#endif #endif
#if defined(HAVE_SYSCALL_H) #if defined(HAVE_SYSCALL_H)
#include <syscall.h> // for syscall() # include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H) #elif defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h> // for syscall() # include <sys/syscall.h> // for syscall()
#endif #endif
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \ #if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \
(!(defined(GLOG_OS_MACOSX)) && !(defined(GLOG_OS_OPENBSD))) && \ (!(defined(GLOG_OS_MACOSX)) && !(defined(GLOG_OS_OPENBSD))) && \
!defined(GLOG_OS_EMSCRIPTEN) !defined(GLOG_OS_EMSCRIPTEN)
#define safe_write(fd, s, len) syscall(SYS_write, fd, s, len) # define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else #else
// Not so safe, but what can you do? // Not so safe, but what can you do?
#define safe_write(fd, s, len) write(fd, s, len) # define safe_write(fd, s, len) write(fd, s, len)
#endif #endif
namespace google { namespace google {
#if defined(__GNUC__) #if defined(__GNUC__)
#define GLOG_ATTRIBUTE_FORMAT(archetype, stringIndex, firstToCheck) \ # define GLOG_ATTRIBUTE_FORMAT(archetype, stringIndex, firstToCheck) \
__attribute__((format(archetype, stringIndex, firstToCheck))) __attribute__((format(archetype, stringIndex, firstToCheck)))
#define GLOG_ATTRIBUTE_FORMAT_ARG(stringIndex) \ # define GLOG_ATTRIBUTE_FORMAT_ARG(stringIndex) \
__attribute__((format_arg(stringIndex))) __attribute__((format_arg(stringIndex)))
#else #else
#define GLOG_ATTRIBUTE_FORMAT(archetype, stringIndex, firstToCheck) # define GLOG_ATTRIBUTE_FORMAT(archetype, stringIndex, firstToCheck)
#define GLOG_ATTRIBUTE_FORMAT_ARG(stringIndex) # define GLOG_ATTRIBUTE_FORMAT_ARG(stringIndex)
#endif #endif
// CAVEAT: std::vsnprintf called from *DoRawLog below has some (exotic) code // CAVEAT: std::vsnprintf called from *DoRawLog below has some (exotic) code
@ -103,15 +103,15 @@ static bool DoRawLog(char** buf, size_t* size, const char* format, ...) {
} }
// Helper for RawLog__ below. // Helper for RawLog__ below.
inline static bool VADoRawLog(char** buf, size_t* size, inline static bool VADoRawLog(char** buf, size_t* size, const char* format,
const char* format, va_list ap) { va_list ap) {
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral" # pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif #endif
int n = std::vsnprintf(*buf, *size, format, ap); int n = std::vsnprintf(*buf, *size, format, ap);
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
if (n < 0 || static_cast<size_t>(n) > *size) return false; if (n < 0 || static_cast<size_t>(n) > *size) return false;
*size -= static_cast<size_t>(n); *size -= static_cast<size_t>(n);
@ -122,7 +122,7 @@ inline static bool VADoRawLog(char** buf, size_t* size,
static const int kLogBufSize = 3000; static const int kLogBufSize = 3000;
static bool crashed = false; static bool crashed = false;
static CrashReason crash_reason; static CrashReason crash_reason;
static char crash_buf[kLogBufSize + 1] = { 0 }; // Will end in '\0' static char crash_buf[kLogBufSize + 1] = {0}; // Will end in '\0'
GLOG_ATTRIBUTE_FORMAT(printf, 4, 5) GLOG_ATTRIBUTE_FORMAT(printf, 4, 5)
void RawLog__(LogSeverity severity, const char* file, int line, void RawLog__(LogSeverity severity, const char* file, int line,
@ -139,9 +139,8 @@ void RawLog__(LogSeverity severity, const char* file, int line,
// NOTE: this format should match the specification in base/logging.h // NOTE: this format should match the specification in base/logging.h
DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ", DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %5u %s:%d] RAW: ",
LogSeverityNames[severity][0], LogSeverityNames[severity][0], static_cast<unsigned int>(GetTID()),
static_cast<unsigned int>(GetTID()), const_basename(const_cast<char*>(file)), line);
const_basename(const_cast<char *>(file)), line);
// Record the position and size of the buffer after the prefix // Record the position and size of the buffer after the prefix
const char* msg_start = buf; const char* msg_start = buf;
@ -161,7 +160,7 @@ void RawLog__(LogSeverity severity, const char* file, int line,
// libc (to side-step any libc interception). // libc (to side-step any libc interception).
// We write just once to avoid races with other invocations of RawLog__. // We write just once to avoid races with other invocations of RawLog__.
safe_write(STDERR_FILENO, buffer, strlen(buffer)); safe_write(STDERR_FILENO, buffer, strlen(buffer));
if (severity == GLOG_FATAL) { if (severity == GLOG_FATAL) {
if (!sync_val_compare_and_swap(&crashed, false, true)) { if (!sync_val_compare_and_swap(&crashed, false, true)) {
crash_reason.filename = file; crash_reason.filename = file;
crash_reason.line_number = line; crash_reason.line_number = line;

View File

@ -41,13 +41,13 @@
#include "utilities.h" #include "utilities.h"
#ifdef HAVE_UCONTEXT_H #ifdef HAVE_UCONTEXT_H
# include <ucontext.h> # include <ucontext.h>
#endif #endif
#ifdef HAVE_SYS_UCONTEXT_H #ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h> # include <sys/ucontext.h>
#endif #endif
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> # include <unistd.h>
#endif #endif
namespace google { namespace google {
@ -61,16 +61,14 @@ namespace {
// The list should be synced with the comment in signalhandler.h. // The list should be synced with the comment in signalhandler.h.
const struct { const struct {
int number; int number;
const char *name; const char* name;
} kFailureSignals[] = { } kFailureSignals[] = {
{ SIGSEGV, "SIGSEGV" }, {SIGSEGV, "SIGSEGV"}, {SIGILL, "SIGILL"},
{ SIGILL, "SIGILL" }, {SIGFPE, "SIGFPE"}, {SIGABRT, "SIGABRT"},
{ SIGFPE, "SIGFPE" },
{ SIGABRT, "SIGABRT" },
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
{ SIGBUS, "SIGBUS" }, {SIGBUS, "SIGBUS"},
#endif #endif
{ SIGTERM, "SIGTERM" }, {SIGTERM, "SIGTERM"},
}; };
static bool kFailureSignalHandlerInstalled = false; static bool kFailureSignalHandlerInstalled = false;
@ -78,14 +76,15 @@ static bool kFailureSignalHandlerInstalled = false;
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
// Returns the program counter from signal context, nullptr if unknown. // Returns the program counter from signal context, nullptr if unknown.
void* GetPC(void* ucontext_in_void) { void* GetPC(void* ucontext_in_void) {
#if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT) # if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && \
defined(PC_FROM_UCONTEXT)
if (ucontext_in_void != nullptr) { if (ucontext_in_void != nullptr) {
ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void); ucontext_t* context = reinterpret_cast<ucontext_t*>(ucontext_in_void);
return (void*)context->PC_FROM_UCONTEXT; return (void*)context->PC_FROM_UCONTEXT;
} }
#else # else
(void)ucontext_in_void; (void)ucontext_in_void;
#endif # endif
return nullptr; return nullptr;
} }
#endif #endif
@ -94,14 +93,13 @@ void* GetPC(void* ucontext_in_void) {
// as it's not async signal safe. // as it's not async signal safe.
class MinimalFormatter { class MinimalFormatter {
public: public:
MinimalFormatter(char *buffer, size_t size) MinimalFormatter(char* buffer, size_t size)
: buffer_(buffer), : buffer_(buffer), cursor_(buffer), end_(buffer + size) {}
cursor_(buffer),
end_(buffer + size) {
}
// Returns the number of bytes written in the buffer. // Returns the number of bytes written in the buffer.
std::size_t num_bytes_written() const { return static_cast<std::size_t>(cursor_ - buffer_); } std::size_t num_bytes_written() const {
return static_cast<std::size_t>(cursor_ - buffer_);
}
// Appends string from "str" and updates the internal cursor. // Appends string from "str" and updates the internal cursor.
void AppendString(const char* str) { void AppendString(const char* str) {
@ -147,9 +145,9 @@ class MinimalFormatter {
} }
private: private:
char *buffer_; char* buffer_;
char *cursor_; char* cursor_;
const char * const end_; const char* const end_;
}; };
// Writes the given data with the size to the standard error. // Writes the given data with the size to the standard error.
@ -181,7 +179,7 @@ void DumpTimeInfo() {
#if defined(HAVE_STACKTRACE) && defined(HAVE_SIGACTION) #if defined(HAVE_STACKTRACE) && defined(HAVE_SIGACTION)
// Dumps information about the signal to STDERR. // Dumps information about the signal to STDERR.
void DumpSignalInfo(int signal_number, siginfo_t *siginfo) { void DumpSignalInfo(int signal_number, siginfo_t* siginfo) {
// Get the signal name. // Get the signal name.
const char* signal_name = nullptr; const char* signal_name = nullptr;
for (auto kFailureSignal : kFailureSignals) { for (auto kFailureSignal : kFailureSignals) {
@ -217,11 +215,11 @@ void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
reinterpret_cast<uint64>(reinterpret_cast<const char*>(id)), 16); reinterpret_cast<uint64>(reinterpret_cast<const char*>(id)), 16);
formatter.AppendString(") "); formatter.AppendString(") ");
// Only linux has the PID of the signal sender in si_pid. // Only linux has the PID of the signal sender in si_pid.
#ifdef GLOG_OS_LINUX # ifdef GLOG_OS_LINUX
formatter.AppendString("from PID "); formatter.AppendString("from PID ");
formatter.AppendUint64(static_cast<uint64>(siginfo->si_pid), 10); formatter.AppendUint64(static_cast<uint64>(siginfo->si_pid), 10);
formatter.AppendString("; "); formatter.AppendString("; ");
#endif # endif
formatter.AppendString("stack trace: ***\n"); formatter.AppendString("stack trace: ***\n");
g_failure_writer(buf, formatter.num_bytes_written()); g_failure_writer(buf, formatter.num_bytes_written());
} }
@ -231,12 +229,12 @@ void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
// Dumps information about the stack frame to STDERR. // Dumps information about the stack frame to STDERR.
void DumpStackFrameInfo(const char* prefix, void* pc) { void DumpStackFrameInfo(const char* prefix, void* pc) {
// Get the symbol name. // Get the symbol name.
const char *symbol = "(unknown)"; const char* symbol = "(unknown)";
char symbolized[1024]; // Big enough for a sane symbol. char symbolized[1024]; // Big enough for a sane symbol.
// Symbolizes the previous address of pc because pc may be in the // Symbolizes the previous address of pc because pc may be in the
// next function. // next function.
if (Symbolize(reinterpret_cast<char *>(pc) - 1, if (Symbolize(reinterpret_cast<char*>(pc) - 1, symbolized,
symbolized, sizeof(symbolized))) { sizeof(symbolized))) {
symbol = symbolized; symbol = symbolized;
} }
@ -279,9 +277,8 @@ static pthread_t* g_entered_thread_id_pointer = nullptr;
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
void FailureSignalHandler(int signal_number) void FailureSignalHandler(int signal_number)
#else #else
void FailureSignalHandler(int signal_number, void FailureSignalHandler(int signal_number, siginfo_t* signal_info,
siginfo_t *signal_info, void* ucontext)
void *ucontext)
#endif #endif
{ {
// First check if we've already entered the function. We use an atomic // First check if we've already entered the function. We use an atomic
@ -324,20 +321,20 @@ void FailureSignalHandler(int signal_number,
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
// Get the program counter from ucontext. // Get the program counter from ucontext.
void *pc = GetPC(ucontext); void* pc = GetPC(ucontext);
DumpStackFrameInfo("PC: ", pc); DumpStackFrameInfo("PC: ", pc);
#endif #endif
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
// Get the stack traces. // Get the stack traces.
void *stack[32]; void* stack[32];
// +1 to exclude this function. // +1 to exclude this function.
const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1); const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
# ifdef HAVE_SIGACTION # ifdef HAVE_SIGACTION
DumpSignalInfo(signal_number, signal_info); DumpSignalInfo(signal_number, signal_info);
#elif !defined(GLOG_OS_WINDOWS) # elif !defined(GLOG_OS_WINDOWS)
(void)signal_info; (void)signal_info;
# endif # endif
// Dump the stack traces. // Dump the stack traces.
for (int i = 0; i < depth; ++i) { for (int i = 0; i < depth; ++i) {
DumpStackFrameInfo(" ", stack[i]); DumpStackFrameInfo(" ", stack[i]);
@ -400,8 +397,7 @@ void InstallFailureSignalHandler() {
kFailureSignalHandlerInstalled = true; kFailureSignalHandlerInstalled = true;
#elif defined(GLOG_OS_WINDOWS) #elif defined(GLOG_OS_WINDOWS)
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) { for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler), CHECK_NE(signal(kFailureSignals[i].number, &FailureSignalHandler), SIG_ERR);
SIG_ERR);
} }
kFailureSignalHandlerInstalled = true; kFailureSignalHandlerInstalled = true;
#endif // HAVE_SIGACTION #endif // HAVE_SIGACTION

View File

@ -35,7 +35,7 @@
#include "utilities.h" #include "utilities.h"
#if defined(HAVE_PTHREAD) #if defined(HAVE_PTHREAD)
# include <pthread.h> # include <pthread.h>
#endif #endif
#include <csignal> #include <csignal>
#include <cstdio> #include <cstdio>
@ -45,7 +45,7 @@
#include "glog/logging.h" #include "glog/logging.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
@ -72,12 +72,12 @@ static void WriteToStdout(const char* data, size_t size) {
} }
} }
int main(int argc, char **argv) { int main(int argc, char** argv) {
#if defined(HAVE_STACKTRACE) && defined(HAVE_SYMBOLIZE) #if defined(HAVE_STACKTRACE) && defined(HAVE_SYMBOLIZE)
InitGoogleLogging(argv[0]); InitGoogleLogging(argv[0]);
#ifdef GLOG_USE_GFLAGS # ifdef GLOG_USE_GFLAGS
ParseCommandLineFlags(&argc, &argv, true); ParseCommandLineFlags(&argc, &argv, true);
#endif # endif
InstallFailureSignalHandler(); InstallFailureSignalHandler();
const std::string command = argc > 1 ? argv[1] : "none"; const std::string command = argc > 1 ? argv[1] : "none";
if (command == "segv") { if (command == "segv") {
@ -85,26 +85,27 @@ int main(int argc, char **argv) {
LOG(INFO) << "create the log file"; LOG(INFO) << "create the log file";
LOG(INFO) << "a message before segv"; LOG(INFO) << "a message before segv";
// We assume 0xDEAD is not writable. // We assume 0xDEAD is not writable.
int *a = (int*)0xDEAD; int* a = (int*)0xDEAD;
*a = 0; *a = 0;
} else if (command == "loop") { } else if (command == "loop") {
fprintf(stderr, "looping\n"); fprintf(stderr, "looping\n");
while (true); while (true)
;
} else if (command == "die_in_thread") { } else if (command == "die_in_thread") {
#if defined(HAVE_PTHREAD) # if defined(HAVE_PTHREAD)
pthread_t thread; pthread_t thread;
pthread_create(&thread, nullptr, &DieInThread, nullptr); pthread_create(&thread, nullptr, &DieInThread, nullptr);
pthread_join(thread, nullptr); pthread_join(thread, nullptr);
#else # else
fprintf(stderr, "no pthread\n"); fprintf(stderr, "no pthread\n");
return 1; return 1;
#endif # endif
} else if (command == "dump_to_stdout") { } else if (command == "dump_to_stdout") {
InstallFailureWriter(WriteToStdout); InstallFailureWriter(WriteToStdout);
abort(); abort();
} else if (command == "installed") { } else if (command == "installed") {
fprintf(stderr, "signal handler installed: %s\n", fprintf(stderr, "signal handler installed: %s\n",
IsFailureSignalHandlerInstalled() ? "true" : "false"); IsFailureSignalHandlerInstalled() ? "true" : "false");
} else { } else {
// Tell the shell script // Tell the shell script
puts("OK"); puts("OK");

View File

@ -42,7 +42,7 @@ namespace google {
// If you change this function, also change GetStackFrames below. // If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) { int GetStackTrace(void** result, int max_depth, int skip_count) {
static const int kStackLength = 64; static const int kStackLength = 64;
void * stack[kStackLength]; void* stack[kStackLength];
int size; int size;
size = backtrace(stack, kStackLength); size = backtrace(stack, kStackLength);

View File

@ -51,11 +51,11 @@ namespace google {
// cases, we return 0 to indicate the situation. // cases, we return 0 to indicate the situation.
// We can use the GCC __thread syntax here since libunwind is not supported on // We can use the GCC __thread syntax here since libunwind is not supported on
// Windows. // Windows.
static __thread bool g_tl_entered; // Initialized to false. static __thread bool g_tl_entered; // Initialized to false.
// If you change this function, also change GetStackFrames below. // If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) { int GetStackTrace(void** result, int max_depth, int skip_count) {
void *ip; void* ip;
int n = 0; int n = 0;
unw_cursor_t cursor; unw_cursor_t cursor;
unw_context_t uc; unw_context_t uc;
@ -67,11 +67,11 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
unw_getcontext(&uc); unw_getcontext(&uc);
RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed"); RAW_CHECK(unw_init_local(&cursor, &uc) >= 0, "unw_init_local failed");
skip_count++; // Do not include the "GetStackTrace" frame skip_count++; // Do not include the "GetStackTrace" frame
while (n < max_depth) { while (n < max_depth) {
int ret = int ret =
unw_get_reg(&cursor, UNW_REG_IP, reinterpret_cast<unw_word_t *>(&ip)); unw_get_reg(&cursor, UNW_REG_IP, reinterpret_cast<unw_word_t*>(&ip));
if (ret < 0) { if (ret < 0) {
break; break;
} }

View File

@ -46,9 +46,9 @@ namespace google {
// stackframe, or return nullptr if no stackframe can be found. Perform sanity // stackframe, or return nullptr if no stackframe can be found. Perform sanity
// checks (the strictness of which is controlled by the boolean parameter // checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. // "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING> template <bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) { static void** NextStackFrame(void** old_sp) {
void **new_sp = static_cast<void **>(*old_sp); void** new_sp = static_cast<void**>(*old_sp);
// Check that the transition from frame pointer old_sp to frame // Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus // pointer new_sp isn't clearly bogus
@ -68,7 +68,7 @@ static void **NextStackFrame(void **old_sp) {
return nullptr; return nullptr;
} }
} }
if ((uintptr_t)new_sp & (sizeof(void *) - 1)) return nullptr; if ((uintptr_t)new_sp & (sizeof(void*) - 1)) return nullptr;
return new_sp; return new_sp;
} }
@ -78,15 +78,15 @@ void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
// If you change this function, also change GetStackFrames below. // If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) { int GetStackTrace(void** result, int max_depth, int skip_count) {
void **sp; void** sp;
// Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther) // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
// and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a // and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
// different asm syntax. I don't know quite the best way to discriminate // different asm syntax. I don't know quite the best way to discriminate
// systems using the old as from the new one; I've gone with __APPLE__. // systems using the old as from the new one; I've gone with __APPLE__.
#ifdef __APPLE__ #ifdef __APPLE__
__asm__ volatile ("mr %0,r1" : "=r" (sp)); __asm__ volatile("mr %0,r1" : "=r"(sp));
#else #else
__asm__ volatile ("mr %0,1" : "=r" (sp)); __asm__ volatile("mr %0,1" : "=r"(sp));
#endif #endif
// On PowerPC, the "Link Register" or "Link Record" (LR), is a stack // On PowerPC, the "Link Register" or "Link Record" (LR), is a stack
@ -111,17 +111,18 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
// linux ppc64), it's in sp[2]. For SYSV (used by linux ppc), // linux ppc64), it's in sp[2]. For SYSV (used by linux ppc),
// it's in sp[1]. // it's in sp[1].
#if defined(_CALL_AIX) || defined(_CALL_DARWIN) #if defined(_CALL_AIX) || defined(_CALL_DARWIN)
result[n++] = *(sp+2); result[n++] = *(sp + 2);
#elif defined(_CALL_SYSV) #elif defined(_CALL_SYSV)
result[n++] = *(sp+1); result[n++] = *(sp + 1);
#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__)) #elif defined(__APPLE__) || \
((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc. // This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp+2); result[n++] = *(sp + 2);
#elif defined(__linux) || defined(__OpenBSD__) #elif defined(__linux) || defined(__OpenBSD__)
// This check is in case the compiler doesn't define _CALL_SYSV. // This check is in case the compiler doesn't define _CALL_SYSV.
result[n++] = *(sp+1); result[n++] = *(sp + 1);
#else #else
#error Need to specify the PPC ABI for your architecture. # error Need to specify the PPC ABI for your architecture.
#endif #endif
} }
// Use strict unwinding rules. // Use strict unwinding rules.

View File

@ -38,7 +38,7 @@
#include "utilities.h" #include "utilities.h"
#ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS #ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS
# include <execinfo.h> # include <execinfo.h>
#endif #endif
using namespace google; using namespace google;
@ -59,68 +59,74 @@ struct AddressRange {
// Expected function [start,end] range. // Expected function [start,end] range.
AddressRange expected_range[BACKTRACE_STEPS]; AddressRange expected_range[BACKTRACE_STEPS];
#if __GNUC__ # if __GNUC__
// Using GCC extension: address of a label can be taken with '&&label'. // Using GCC extension: address of a label can be taken with '&&label'.
// Start should be a label somewhere before recursive call, end somewhere // Start should be a label somewhere before recursive call, end somewhere
// after it. // after it.
#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \ # define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
do { \ do { \
(prange)->start = &&start_label; \ (prange)->start = &&start_label; \
(prange)->end = &&end_label; \ (prange)->end = &&end_label; \
CHECK_LT((prange)->start, (prange)->end); \ CHECK_LT((prange)->start, (prange)->end); \
} while (0) } while (0)
// This macro expands into "unmovable" code (opaque to GCC), and that // This macro expands into "unmovable" code (opaque to GCC), and that
// prevents GCC from moving a_label up or down in the code. // prevents GCC from moving a_label up or down in the code.
// Without it, there is no code following the 'end' label, and GCC // Without it, there is no code following the 'end' label, and GCC
// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before // (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
// the recursive call. // the recursive call.
#define DECLARE_ADDRESS_LABEL(a_label) \ # define DECLARE_ADDRESS_LABEL(a_label) \
a_label: do { __asm__ __volatile__(""); } while (0) a_label: \
do { \
__asm__ __volatile__(""); \
} while (0)
// Gcc 4.4.0 may split function into multiple chunks, and the chunk // Gcc 4.4.0 may split function into multiple chunks, and the chunk
// performing recursive call may end up later in the code then the return // performing recursive call may end up later in the code then the return
// instruction (this actually happens with FDO). // instruction (this actually happens with FDO).
// Adjust function range from __builtin_return_address. // Adjust function range from __builtin_return_address.
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \ # define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
do { \ do { \
void *ra = __builtin_return_address(0); \ void* ra = __builtin_return_address(0); \
CHECK_LT((prange)->start, ra); \ CHECK_LT((prange)->start, ra); \
if (ra > (prange)->end) { \ if (ra > (prange)->end) { \
printf("Adjusting range from %p..%p to %p..%p\n", \ printf("Adjusting range from %p..%p to %p..%p\n", (prange)->start, \
(prange)->start, (prange)->end, \ (prange)->end, (prange)->start, ra); \
(prange)->start, ra); \ (prange)->end = ra; \
(prange)->end = ra; \ } \
} \ } while (0)
} while (0) # else
#else
// Assume the Check* functions below are not longer than 256 bytes. // Assume the Check* functions below are not longer than 256 bytes.
#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \ # define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
do { \ do { \
(prange)->start = reinterpret_cast<const void *>(&fn); \ (prange)->start = reinterpret_cast<const void*>(&fn); \
(prange)->end = reinterpret_cast<const char *>(&fn) + 256; \ (prange)->end = reinterpret_cast<const char*>(&fn) + 256; \
} while (0) } while (0)
#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0) # define DECLARE_ADDRESS_LABEL(a_label) \
#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0) do { \
#endif // __GNUC__ } while (0)
# define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
do { \
} while (0)
# endif // __GNUC__
//-----------------------------------------------------------------------// //-----------------------------------------------------------------------//
static void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range) static void CheckRetAddrIsInFunction(void* ret_addr,
{ const AddressRange& range) {
CHECK_GE(ret_addr, range.start); CHECK_GE(ret_addr, range.start);
CHECK_LE(ret_addr, range.end); CHECK_LE(ret_addr, range.end);
} }
//-----------------------------------------------------------------------// //-----------------------------------------------------------------------//
#if defined(__clang__) # if defined(__clang__)
#pragma clang diagnostic push # pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-label-as-value" # pragma clang diagnostic ignored "-Wgnu-label-as-value"
#endif # endif
void ATTRIBUTE_NOINLINE CheckStackTrace(int); void ATTRIBUTE_NOINLINE CheckStackTrace(int);
static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() { static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() {
const int STACK_LEN = 10; const int STACK_LEN = 10;
void *stack[STACK_LEN]; void* stack[STACK_LEN];
int size; int size;
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]); ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
@ -132,8 +138,8 @@ static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() {
CHECK_LE(size, STACK_LEN); CHECK_LE(size, STACK_LEN);
if (true) { if (true) {
#ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS # ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS
char **strings = backtrace_symbols(stack, size); char** strings = backtrace_symbols(stack, size);
printf("Obtained %d stack frames.\n", size); printf("Obtained %d stack frames.\n", size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
printf("%s %p\n", strings[i], stack[i]); printf("%s %p\n", strings[i], stack[i]);
@ -146,11 +152,11 @@ static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() {
printf("CheckStackTrace() addr: %p\n", p.p2); printf("CheckStackTrace() addr: %p\n", p.p2);
free(strings); free(strings);
#endif # endif
} }
for (int i = 0; i < BACKTRACE_STEPS; i++) { for (int i = 0; i < BACKTRACE_STEPS; i++) {
printf("Backtrace %d: expected: %p..%p actual: %p ... ", printf("Backtrace %d: expected: %p..%p actual: %p ... ", i,
i, expected_range[i].start, expected_range[i].end, stack[i]); expected_range[i].start, expected_range[i].end, stack[i]);
fflush(stdout); fflush(stdout);
CheckRetAddrIsInFunction(stack[i], expected_range[i]); CheckRetAddrIsInFunction(stack[i], expected_range[i]);
printf("OK\n"); printf("OK\n");
@ -198,7 +204,7 @@ static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
DECLARE_ADDRESS_LABEL(end); DECLARE_ADDRESS_LABEL(end);
} }
#ifndef __GNUC__ # ifndef __GNUC__
// On non-GNU environment, we use the address of `CheckStackTrace` to // On non-GNU environment, we use the address of `CheckStackTrace` to
// guess the address range of this function. This guess is wrong for // guess the address range of this function. This guess is wrong for
// non-static function on Windows. This is probably because // non-static function on Windows. This is probably because
@ -206,8 +212,9 @@ static void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
// not the actual address of `CheckStackTrace`. // not the actual address of `CheckStackTrace`.
// See https://github.com/google/glog/issues/421 for the detail. // See https://github.com/google/glog/issues/421 for the detail.
static static
#endif # endif
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) { void ATTRIBUTE_NOINLINE
CheckStackTrace(int i) {
INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]); INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
DECLARE_ADDRESS_LABEL(start); DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--) { for (int j = i; j >= 0; j--) {
@ -216,13 +223,13 @@ void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
DECLARE_ADDRESS_LABEL(end); DECLARE_ADDRESS_LABEL(end);
} }
#if defined(__clang__) # if defined(__clang__)
#pragma clang diagnostic pop # pragma clang diagnostic pop
#endif # endif
//-----------------------------------------------------------------------// //-----------------------------------------------------------------------//
int main(int, char ** argv) { int main(int, char** argv) {
FLAGS_logtostderr = true; FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]); InitGoogleLogging(argv[0]);
@ -235,12 +242,12 @@ int main(int, char ** argv) {
#else #else
int main() { int main() {
#ifdef GLOG_BAZEL_BUILD # ifdef GLOG_BAZEL_BUILD
printf("HAVE_STACKTRACE is expected to be defined in Bazel tests\n"); printf("HAVE_STACKTRACE is expected to be defined in Bazel tests\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
#endif // GLOG_BAZEL_BUILD # endif // GLOG_BAZEL_BUILD
printf("PASS (no stacktrace support)\n"); printf("PASS (no stacktrace support)\n");
return 0; return 0;
} }
#endif // HAVE_STACKTRACE #endif // HAVE_STACKTRACE

View File

@ -38,41 +38,41 @@
namespace google { namespace google {
struct trace_arg_t { struct trace_arg_t {
void **result; void** result;
int max_depth; int max_depth;
int skip_count; int skip_count;
int count; int count;
}; };
// Workaround for the malloc() in _Unwind_Backtrace() issue. // Workaround for the malloc() in _Unwind_Backtrace() issue.
static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context */*uc*/, void */*opq*/) { static _Unwind_Reason_Code nop_backtrace(struct _Unwind_Context* /*uc*/,
void* /*opq*/) {
return _URC_NO_REASON; return _URC_NO_REASON;
} }
// This code is not considered ready to run until // This code is not considered ready to run until
// static initializers run so that we are guaranteed // static initializers run so that we are guaranteed
// that any malloc-related initialization is done. // that any malloc-related initialization is done.
static bool ready_to_run = false; static bool ready_to_run = false;
class StackTraceInit { class StackTraceInit {
public: public:
StackTraceInit() { StackTraceInit() {
// Extra call to force initialization // Extra call to force initialization
_Unwind_Backtrace(nop_backtrace, nullptr); _Unwind_Backtrace(nop_backtrace, nullptr);
ready_to_run = true; ready_to_run = true;
} }
}; };
static StackTraceInit module_initializer; // Force initialization static StackTraceInit module_initializer; // Force initialization
static _Unwind_Reason_Code GetOneFrame(struct _Unwind_Context *uc, void *opq) { static _Unwind_Reason_Code GetOneFrame(struct _Unwind_Context* uc, void* opq) {
auto *targ = static_cast<trace_arg_t *>(opq); auto* targ = static_cast<trace_arg_t*>(opq);
if (targ->skip_count > 0) { if (targ->skip_count > 0) {
targ->skip_count--; targ->skip_count--;
} else { } else {
targ->result[targ->count++] = reinterpret_cast<void *>(_Unwind_GetIP(uc)); targ->result[targ->count++] = reinterpret_cast<void*>(_Unwind_GetIP(uc));
} }
if (targ->count == targ->max_depth) { if (targ->count == targ->max_depth) {
return _URC_END_OF_STACK; return _URC_END_OF_STACK;
@ -89,7 +89,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
trace_arg_t targ; trace_arg_t targ;
skip_count += 1; // Do not include the "GetStackTrace" frame skip_count += 1; // Do not include the "GetStackTrace" frame
targ.result = result; targ.result = result;
targ.max_depth = max_depth; targ.max_depth = max_depth;

View File

@ -31,10 +31,11 @@
// //
// Windows implementation - just use CaptureStackBackTrace // Windows implementation - just use CaptureStackBackTrace
#include <dbghelp.h>
#include "config.h" #include "config.h"
#include "port.h" #include "port.h"
#include "stacktrace.h" #include "stacktrace.h"
#include <dbghelp.h>
namespace google { namespace google {

View File

@ -31,11 +31,11 @@
#include <cstdint> // for uintptr_t #include <cstdint> // for uintptr_t
#include "utilities.h" // for OS_* macros #include "utilities.h" // for OS_* macros
#if !defined(GLOG_OS_WINDOWS) #if !defined(GLOG_OS_WINDOWS)
#include <unistd.h> # include <sys/mman.h>
#include <sys/mman.h> # include <unistd.h>
#endif #endif
#include <cstdio> // for nullptr #include <cstdio> // for nullptr
@ -48,9 +48,9 @@ namespace google {
// stackframe, or return nullptr if no stackframe can be found. Perform sanity // stackframe, or return nullptr if no stackframe can be found. Perform sanity
// checks (the strictness of which is controlled by the boolean parameter // checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned. // "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING> template <bool STRICT_UNWINDING>
static void **NextStackFrame(void **old_sp) { static void** NextStackFrame(void** old_sp) {
void **new_sp = static_cast<void **>(*old_sp); void** new_sp = static_cast<void**>(*old_sp);
// Check that the transition from frame pointer old_sp to frame // Check that the transition from frame pointer old_sp to frame
// pointer new_sp isn't clearly bogus // pointer new_sp isn't clearly bogus
@ -75,7 +75,7 @@ static void **NextStackFrame(void **old_sp) {
return nullptr; return nullptr;
} }
} }
if (reinterpret_cast<uintptr_t>(new_sp) & (sizeof(void *) - 1)) { if (reinterpret_cast<uintptr_t>(new_sp) & (sizeof(void*) - 1)) {
return nullptr; return nullptr;
} }
#ifdef __i386__ #ifdef __i386__
@ -92,9 +92,9 @@ static void **NextStackFrame(void **old_sp) {
// Note: NextStackFrame<false>() is only called while the program // Note: NextStackFrame<false>() is only called while the program
// is already on its last leg, so it's ok to be slow here. // is already on its last leg, so it's ok to be slow here.
static int page_size = getpagesize(); static int page_size = getpagesize();
void *new_sp_aligned = void* new_sp_aligned =
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(new_sp) & reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_sp) &
static_cast<uintptr_t>(~(page_size - 1))); static_cast<uintptr_t>(~(page_size - 1)));
if (msync(new_sp_aligned, static_cast<size_t>(page_size), MS_ASYNC) == -1) { if (msync(new_sp_aligned, static_cast<size_t>(page_size), MS_ASYNC) == -1) {
return nullptr; return nullptr;
} }
@ -105,12 +105,12 @@ static void **NextStackFrame(void **old_sp) {
// If you change this function, also change GetStackFrames below. // If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) { int GetStackTrace(void** result, int max_depth, int skip_count) {
void **sp; void** sp;
#ifdef __GNUC__ #ifdef __GNUC__
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402 # if __GNUC__ * 100 + __GNUC_MINOR__ >= 402
#define USE_BUILTIN_FRAME_ADDRESS # define USE_BUILTIN_FRAME_ADDRESS
#endif # endif
#endif #endif
#ifdef USE_BUILTIN_FRAME_ADDRESS #ifdef USE_BUILTIN_FRAME_ADDRESS
@ -121,7 +121,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
// sp[1] caller address // sp[1] caller address
// sp[2] first argument // sp[2] first argument
// ... // ...
sp = (void **)&result - 2; sp = (void**)&result - 2;
#elif defined(__x86_64__) #elif defined(__x86_64__)
// __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8 // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8
unsigned long rbp; unsigned long rbp;
@ -132,10 +132,10 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
// would be (before this __asm__ instruction) to call Noop() defined as // would be (before this __asm__ instruction) to call Noop() defined as
// static void Noop() __attribute__ ((noinline)); // prevent inlining // static void Noop() __attribute__ ((noinline)); // prevent inlining
// static void Noop() { asm(""); } // prevent optimizing-away // static void Noop() { asm(""); } // prevent optimizing-away
__asm__ volatile ("mov %%rbp, %0" : "=r" (rbp)); __asm__ volatile("mov %%rbp, %0" : "=r"(rbp));
// Arguments are passed in registers on x86-64, so we can't just // Arguments are passed in registers on x86-64, so we can't just
// offset from &result // offset from &result
sp = (void **) rbp; sp = (void**)rbp;
#endif #endif
int n = 0; int n = 0;
@ -148,7 +148,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
if (skip_count > 0) { if (skip_count > 0) {
skip_count--; skip_count--;
} else { } else {
result[n++] = *(sp+1); result[n++] = *(sp + 1);
} }
// Use strict unwinding rules. // Use strict unwinding rules.
sp = NextStackFrame<true>(sp); sp = NextStackFrame<true>(sp);

View File

@ -62,14 +62,14 @@ static void TestSTLLogging() {
{ {
// Test a sorted pair associative container. // Test a sorted pair associative container.
map< int, string > m; map<int, string> m;
m[20] = "twenty"; m[20] = "twenty";
m[10] = "ten"; m[10] = "ten";
m[30] = "thirty"; m[30] = "thirty";
ostringstream ss; ostringstream ss;
ss << m; ss << m;
EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)"); EXPECT_EQ(ss.str(), "(10, ten) (20, twenty) (30, thirty)");
map< int, string > copied_m(m); map<int, string> copied_m(m);
CHECK_EQ(m, copied_m); // This must compile. CHECK_EQ(m, copied_m); // This must compile.
} }
@ -95,14 +95,14 @@ static void TestSTLLogging() {
{ {
// Test a sorted pair associative container. // Test a sorted pair associative container.
// Use a non-default comparison functor. // Use a non-default comparison functor.
map<int, string, greater<> > m; map<int, string, greater<>> m;
m[20] = "twenty"; m[20] = "twenty";
m[10] = "ten"; m[10] = "ten";
m[30] = "thirty"; m[30] = "thirty";
ostringstream ss; ostringstream ss;
ss << m; ss << m;
EXPECT_EQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)"); EXPECT_EQ(ss.str(), "(30, thirty) (20, twenty) (10, ten)");
map<int, string, greater<> > copied_m(m); map<int, string, greater<>> copied_m(m);
CHECK_EQ(m, copied_m); // This must compile. CHECK_EQ(m, copied_m); // This must compile.
} }
} }

View File

@ -57,13 +57,13 @@ int CheckNoReturn(bool b) {
} }
struct A {}; struct A {};
std::ostream &operator<<(std::ostream &str, const A &) { return str; } std::ostream& operator<<(std::ostream& str, const A&) { return str; }
namespace { namespace {
void handle_abort(int /*code*/) { std::exit(EXIT_FAILURE); } void handle_abort(int /*code*/) { std::exit(EXIT_FAILURE); }
} // namespace } // namespace
int main(int, char *argv[]) { int main(int, char* argv[]) {
#if defined(_MSC_VER) #if defined(_MSC_VER)
// Avoid presenting an interactive dialog that will cause the test to time // Avoid presenting an interactive dialog that will cause the test to time
// out. // out.

View File

@ -49,20 +49,19 @@
// macro to add platform specific defines (e.g. GLOG_OS_OPENBSD). // macro to add platform specific defines (e.g. GLOG_OS_OPENBSD).
#ifdef GLOG_BUILD_CONFIG_INCLUDE #ifdef GLOG_BUILD_CONFIG_INCLUDE
#include GLOG_BUILD_CONFIG_INCLUDE # include GLOG_BUILD_CONFIG_INCLUDE
#endif // GLOG_BUILD_CONFIG_INCLUDE #endif // GLOG_BUILD_CONFIG_INCLUDE
#include "utilities.h" #include "utilities.h"
#if defined(HAVE_SYMBOLIZE) #if defined(HAVE_SYMBOLIZE)
#include <cstring> # include <algorithm>
# include <cstring>
# include <limits>
#include <algorithm> # include "demangle.h"
#include <limits> # include "symbolize.h"
#include "symbolize.h"
#include "demangle.h"
namespace google { namespace google {
@ -76,7 +75,7 @@ static int AssertFail() {
return 0; // Should not reach. return 0; // Should not reach.
} }
#define SAFE_ASSERT(expr) ((expr) ? 0 : AssertFail()) # define SAFE_ASSERT(expr) ((expr) ? 0 : AssertFail())
static SymbolizeCallback g_symbolize_callback = nullptr; static SymbolizeCallback g_symbolize_callback = nullptr;
void InstallSymbolizeCallback(SymbolizeCallback callback) { void InstallSymbolizeCallback(SymbolizeCallback callback) {
@ -94,7 +93,7 @@ void InstallSymbolizeOpenObjectFileCallback(
// where the input symbol is demangled in-place. // where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not // To keep stack consumption low, we would like this function to not
// get inlined. // get inlined.
static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size) { static ATTRIBUTE_NOINLINE void DemangleInplace(char* out, size_t out_size) {
char demangled[256]; // Big enough for sane demangled symbols. char demangled[256]; // Big enough for sane demangled symbols.
if (Demangle(out, demangled, sizeof(demangled))) { if (Demangle(out, demangled, sizeof(demangled))) {
// Demangling succeeded. Copy to out if the space allows. // Demangling succeeded. Copy to out if the space allows.
@ -108,35 +107,37 @@ static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size) {
} // namespace google } // namespace google
#if defined(__ELF__) # if defined(__ELF__)
#if defined(HAVE_DLFCN_H) # if defined(HAVE_DLFCN_H)
#include <dlfcn.h> # include <dlfcn.h>
#endif # endif
#if defined(GLOG_OS_OPENBSD) # if defined(GLOG_OS_OPENBSD)
#include <sys/exec_elf.h> # include <sys/exec_elf.h>
#else # else
#include <elf.h> # include <elf.h>
#endif # endif
#include <fcntl.h> # include <fcntl.h>
#include <sys/stat.h> # include <sys/stat.h>
#include <sys/types.h> # include <sys/types.h>
#include <unistd.h> # include <unistd.h>
#include <cerrno> # include <cerrno>
#include <climits> # include <climits>
#include <cstddef> # include <cstddef>
#include <cstdint> # include <cstdint>
#include <cstdio> # include <cstdio>
#include <cstdlib> # include <cstdlib>
#include <cstring> # include <cstring>
#include "config.h" # include "config.h"
#include "glog/raw_logging.h" # include "glog/raw_logging.h"
#include "symbolize.h" # include "symbolize.h"
// Re-runs fn until it doesn't cause EINTR. // Re-runs fn until it doesn't cause EINTR.
#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) # define NO_INTR(fn) \
do { \
} while ((fn) < 0 && errno == EINTR)
namespace google { namespace google {
@ -144,11 +145,12 @@ namespace google {
// descriptor "fd" into the buffer starting at "buf" while handling short reads // descriptor "fd" into the buffer starting at "buf" while handling short reads
// and EINTR. On success, return the number of bytes read. Otherwise, return // and EINTR. On success, return the number of bytes read. Otherwise, return
// -1. // -1.
static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count, static ssize_t ReadFromOffset(const int fd, void* buf, const size_t count,
const size_t offset) { const size_t offset) {
SAFE_ASSERT(fd >= 0); SAFE_ASSERT(fd >= 0);
SAFE_ASSERT(count <= static_cast<size_t>(std::numeric_limits<ssize_t>::max())); SAFE_ASSERT(count <=
char *buf0 = reinterpret_cast<char *>(buf); static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
char* buf0 = reinterpret_cast<char*>(buf);
size_t num_bytes = 0; size_t num_bytes = 0;
while (num_bytes < count) { while (num_bytes < count) {
ssize_t len; ssize_t len;
@ -170,8 +172,8 @@ static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count,
// pointed by "fd" into the buffer starting at "buf" while handling // pointed by "fd" into the buffer starting at "buf" while handling
// short reads and EINTR. On success, return true. Otherwise, return // short reads and EINTR. On success, return true. Otherwise, return
// false. // false.
static bool ReadFromOffsetExact(const int fd, void *buf, static bool ReadFromOffsetExact(const int fd, void* buf, const size_t count,
const size_t count, const size_t offset) { const size_t offset) {
ssize_t len = ReadFromOffset(fd, buf, count, offset); ssize_t len = ReadFromOffset(fd, buf, count, offset);
return static_cast<size_t>(len) == count; return static_cast<size_t>(len) == count;
} }
@ -193,9 +195,11 @@ static int FileGetElfType(const int fd) {
// and return true. Otherwise, return false. // and return true. Otherwise, return false.
// To keep stack consumption low, we would like this function to not get // To keep stack consumption low, we would like this function to not get
// inlined. // inlined.
static ATTRIBUTE_NOINLINE bool static ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(const int fd,
GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const size_t sh_offset, ElfW(Half) sh_num,
ElfW(Word) type, ElfW(Shdr) *out) { const size_t sh_offset,
ElfW(Word) type,
ElfW(Shdr) * out) {
// Read at most 16 section headers at a time to save read calls. // Read at most 16 section headers at a time to save read calls.
ElfW(Shdr) buf[16]; ElfW(Shdr) buf[16];
for (size_t i = 0; i < sh_num;) { for (size_t i = 0; i < sh_num;) {
@ -226,8 +230,8 @@ GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const size_t sh_offset,
const int kMaxSectionNameLen = 64; const int kMaxSectionNameLen = 64;
// name_len should include terminating '\0'. // name_len should include terminating '\0'.
bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, bool GetSectionHeaderByName(int fd, const char* name, size_t name_len,
ElfW(Shdr) *out) { ElfW(Shdr) * out) {
ElfW(Ehdr) elf_header; ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
return false; return false;
@ -242,8 +246,8 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
} }
for (size_t i = 0; i < elf_header.e_shnum; ++i) { for (size_t i = 0; i < elf_header.e_shnum; ++i) {
size_t section_header_offset = (elf_header.e_shoff + size_t section_header_offset =
elf_header.e_shentsize * i); (elf_header.e_shoff + elf_header.e_shentsize * i);
if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) { if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
return false; return false;
} }
@ -277,10 +281,11 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
// to out. Otherwise, return false. // to out. Otherwise, return false.
// To keep stack consumption low, we would like this function to not get // To keep stack consumption low, we would like this function to not get
// inlined. // inlined.
static ATTRIBUTE_NOINLINE bool static ATTRIBUTE_NOINLINE bool FindSymbol(uint64_t pc, const int fd, char* out,
FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size, size_t out_size,
uint64_t symbol_offset, const ElfW(Shdr) *strtab, uint64_t symbol_offset,
const ElfW(Shdr) *symtab) { const ElfW(Shdr) * strtab,
const ElfW(Shdr) * symtab) {
if (symtab == nullptr) { if (symtab == nullptr) {
return false; return false;
} }
@ -291,11 +296,11 @@ FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size,
// If we are reading Elf64_Sym's, we want to limit this array to // If we are reading Elf64_Sym's, we want to limit this array to
// 32 elements (to keep stack consumption low), otherwise we can // 32 elements (to keep stack consumption low), otherwise we can
// have a 64 element Elf32_Sym array. // have a 64 element Elf32_Sym array.
#if defined(__WORDSIZE) && __WORDSIZE == 64 # if defined(__WORDSIZE) && __WORDSIZE == 64
const size_t NUM_SYMBOLS = 32U; const size_t NUM_SYMBOLS = 32U;
#else # else
const size_t NUM_SYMBOLS = 64U; const size_t NUM_SYMBOLS = 64U;
#endif # endif
// Read at most NUM_SYMBOLS symbols at once to save read() calls. // Read at most NUM_SYMBOLS symbols at once to save read() calls.
ElfW(Sym) buf[NUM_SYMBOLS]; ElfW(Sym) buf[NUM_SYMBOLS];
@ -331,11 +336,8 @@ FindSymbol(uint64_t pc, const int fd, char *out, size_t out_size,
// both regular and dynamic symbol tables if necessary. On success, // both regular and dynamic symbol tables if necessary. On success,
// write the symbol name to "out" and return true. Otherwise, return // write the symbol name to "out" and return true. Otherwise, return
// false. // false.
static bool GetSymbolFromObjectFile(const int fd, static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, char* out,
uint64_t pc, size_t out_size, uint64_t base_address) {
char* out,
size_t out_size,
uint64_t base_address) {
// Read the ELF header. // Read the ELF header.
ElfW(Ehdr) elf_header; ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
@ -347,8 +349,9 @@ static bool GetSymbolFromObjectFile(const int fd,
// Consult a regular symbol table first. // Consult a regular symbol table first.
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
SHT_SYMTAB, &symtab)) { SHT_SYMTAB, &symtab)) {
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + if (!ReadFromOffsetExact(
symtab.sh_link * sizeof(symtab))) { fd, &strtab, sizeof(strtab),
elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
return false; return false;
} }
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) { if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
@ -359,8 +362,9 @@ static bool GetSymbolFromObjectFile(const int fd,
// If the symbol is not found, then consult a dynamic symbol table. // If the symbol is not found, then consult a dynamic symbol table.
if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, if (GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff,
SHT_DYNSYM, &symtab)) { SHT_DYNSYM, &symtab)) {
if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + if (!ReadFromOffsetExact(
symtab.sh_link * sizeof(symtab))) { fd, &strtab, sizeof(strtab),
elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
return false; return false;
} }
if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) { if (FindSymbol(pc, fd, out, out_size, base_address, &strtab, &symtab)) {
@ -385,8 +389,8 @@ struct FileDescriptor {
int get() { return fd_; } int get() { return fd_; }
private: private:
FileDescriptor(const FileDescriptor &) = delete; FileDescriptor(const FileDescriptor&) = delete;
void operator=(const FileDescriptor &) = delete; void operator=(const FileDescriptor&) = delete;
}; };
// Helper class for reading lines from file. // Helper class for reading lines from file.
@ -396,7 +400,7 @@ struct FileDescriptor {
// and std::snprintf(). // and std::snprintf().
class LineReader { class LineReader {
public: public:
explicit LineReader(int fd, char *buf, size_t buf_len, size_t offset) explicit LineReader(int fd, char* buf, size_t buf_len, size_t offset)
: fd_(fd), : fd_(fd),
buf_(buf), buf_(buf),
buf_len_(buf_len), buf_len_(buf_len),
@ -410,7 +414,7 @@ class LineReader {
// //
// Note: if the last line doesn't end with '\n', the line will be // Note: if the last line doesn't end with '\n', the line will be
// dropped. It's an intentional behavior to make the code simple. // dropped. It's an intentional behavior to make the code simple.
bool ReadLine(const char **bol, const char **eol) { bool ReadLine(const char** bol, const char** eol) {
if (BufferIsEmpty()) { // First time. if (BufferIsEmpty()) { // First time.
const ssize_t num_bytes = ReadFromOffset(fd_, buf_, buf_len_, offset_); const ssize_t num_bytes = ReadFromOffset(fd_, buf_, buf_len_, offset_);
if (num_bytes <= 0) { // EOF or error. if (num_bytes <= 0) { // EOF or error.
@ -420,14 +424,14 @@ class LineReader {
eod_ = buf_ + num_bytes; eod_ = buf_ + num_bytes;
bol_ = buf_; bol_ = buf_;
} else { } else {
bol_ = eol_ + 1; // Advance to the next line in the buffer. bol_ = eol_ + 1; // Advance to the next line in the buffer.
SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_". SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
if (!HasCompleteLine()) { if (!HasCompleteLine()) {
const auto incomplete_line_length = static_cast<size_t>(eod_ - bol_); const auto incomplete_line_length = static_cast<size_t>(eod_ - bol_);
// Move the trailing incomplete line to the beginning. // Move the trailing incomplete line to the beginning.
memmove(buf_, bol_, incomplete_line_length); memmove(buf_, bol_, incomplete_line_length);
// Read text from file and append it. // Read text from file and append it.
char * const append_pos = buf_ + incomplete_line_length; char* const append_pos = buf_ + incomplete_line_length;
const size_t capacity_left = buf_len_ - incomplete_line_length; const size_t capacity_left = buf_len_ - incomplete_line_length;
const ssize_t num_bytes = const ssize_t num_bytes =
ReadFromOffset(fd_, append_pos, capacity_left, offset_); ReadFromOffset(fd_, append_pos, capacity_left, offset_);
@ -451,57 +455,53 @@ class LineReader {
} }
// Beginning of line. // Beginning of line.
const char *bol() { const char* bol() { return bol_; }
return bol_;
}
// End of line. // End of line.
const char *eol() { const char* eol() { return eol_; }
return eol_;
}
private: private:
LineReader(const LineReader &) = delete; LineReader(const LineReader&) = delete;
void operator=(const LineReader &) = delete; void operator=(const LineReader&) = delete;
char *FindLineFeed() { char* FindLineFeed() {
return reinterpret_cast<char *>(memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_))); return reinterpret_cast<char*>(
memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_)));
} }
bool BufferIsEmpty() { bool BufferIsEmpty() { return buf_ == eod_; }
return buf_ == eod_;
}
bool HasCompleteLine() { bool HasCompleteLine() {
return !BufferIsEmpty() && FindLineFeed() != nullptr; return !BufferIsEmpty() && FindLineFeed() != nullptr;
} }
const int fd_; const int fd_;
char * const buf_; char* const buf_;
const size_t buf_len_; const size_t buf_len_;
size_t offset_; size_t offset_;
char *bol_; char* bol_;
char *eol_; char* eol_;
const char *eod_; // End of data in "buf_". const char* eod_; // End of data in "buf_".
}; };
} // namespace } // namespace
// Place the hex number read from "start" into "*hex". The pointer to // Place the hex number read from "start" into "*hex". The pointer to
// the first non-hex character or "end" is returned. // the first non-hex character or "end" is returned.
static char *GetHex(const char *start, const char *end, uint64_t *hex) { static char* GetHex(const char* start, const char* end, uint64_t* hex) {
*hex = 0; *hex = 0;
const char *p; const char* p;
for (p = start; p < end; ++p) { for (p = start; p < end; ++p) {
int ch = *p; int ch = *p;
if ((ch >= '0' && ch <= '9') || if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { (ch >= 'a' && ch <= 'f')) {
*hex = (*hex << 4U) | (ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U); *hex = (*hex << 4U) |
(ch < 'A' ? static_cast<uint64_t>(ch - '0') : (ch & 0xF) + 9U);
} else { // Encountered the first non-hex character. } else { // Encountered the first non-hex character.
break; break;
} }
} }
SAFE_ASSERT(p <= end); SAFE_ASSERT(p <= end);
return const_cast<char *>(p); return const_cast<char*>(p);
} }
// Searches for the object file (from /proc/self/maps) that contains // Searches for the object file (from /proc/self/maps) that contains
@ -512,12 +512,9 @@ static char *GetHex(const char *start, const char *end, uint64_t *hex) {
// file is opened successfully, returns the file descriptor. Otherwise, // file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer // returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator). // (including the null-terminator).
static ATTRIBUTE_NOINLINE int static ATTRIBUTE_NOINLINE int OpenObjectFileContainingPcAndGetStartAddress(
OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, uint64_t pc, uint64_t& start_address, uint64_t& base_address,
uint64_t &start_address, char* out_file_name, size_t out_file_name_size) {
uint64_t &base_address,
char *out_file_name,
size_t out_file_name_size) {
int object_fd; int object_fd;
int maps_fd; int maps_fd;
@ -539,8 +536,8 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
char buf[1024]; // Big enough for line of sane /proc/self/maps char buf[1024]; // Big enough for line of sane /proc/self/maps
LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf), 0); LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf), 0);
while (true) { while (true) {
const char *cursor; const char* cursor;
const char *eol; const char* eol;
if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line. if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line.
return -1; return -1;
} }
@ -568,7 +565,7 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
++cursor; // Skip ' '. ++cursor; // Skip ' '.
// Read flags. Skip flags until we encounter a space or eol. // Read flags. Skip flags until we encounter a space or eol.
const char * const flags_start = cursor; const char* const flags_start = cursor;
while (cursor < eol && *cursor != ' ') { while (cursor < eol && *cursor != ' ') {
++cursor; ++cursor;
} }
@ -620,7 +617,7 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
continue; // We skip this map. PC isn't in this map. continue; // We skip this map. PC isn't in this map.
} }
// Check flags. We are only interested in "r*x" maps. // Check flags. We are only interested in "r*x" maps.
if (flags_start[0] != 'r' || flags_start[2] != 'x') { if (flags_start[0] != 'r' || flags_start[2] != 'x') {
continue; // We skip this map. continue; // We skip this map.
} }
@ -672,7 +669,8 @@ OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc,
// "sz" bytes. Output will be truncated as needed, and a NUL character is always // "sz" bytes. Output will be truncated as needed, and a NUL character is always
// appended. // appended.
// NOTE: code from sandbox/linux/seccomp-bpf/demo.cc. // NOTE: code from sandbox/linux/seccomp-bpf/demo.cc.
static char *itoa_r(uintptr_t i, char *buf, size_t sz, unsigned base, size_t padding) { static char* itoa_r(uintptr_t i, char* buf, size_t sz, unsigned base,
size_t padding) {
// Make sure we can write at least one NUL byte. // Make sure we can write at least one NUL byte.
size_t n = 1; size_t n = 1;
if (n > sz) { if (n > sz) {
@ -684,11 +682,11 @@ static char *itoa_r(uintptr_t i, char *buf, size_t sz, unsigned base, size_t pad
return nullptr; return nullptr;
} }
char *start = buf; char* start = buf;
// Loop until we have converted the entire number. Output at least one // Loop until we have converted the entire number. Output at least one
// character (i.e. '0'). // character (i.e. '0').
char *ptr = start; char* ptr = start;
do { do {
// Make sure there is still enough space left in our output buffer. // Make sure there is still enough space left in our output buffer.
if (++n > sz) { if (++n > sz) {
@ -749,7 +747,7 @@ static void SafeAppendHexNumber(uint64_t value, char* dest, size_t dest_size) {
// and "out" is used as its output. // and "out" is used as its output.
// To keep stack consumption low, we would like this function to not // To keep stack consumption low, we would like this function to not
// get inlined. // get inlined.
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
size_t out_size) { size_t out_size) {
auto pc0 = reinterpret_cast<uintptr_t>(pc); auto pc0 = reinterpret_cast<uintptr_t>(pc);
uint64_t start_address = 0; uint64_t start_address = 0;
@ -763,24 +761,21 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
SafeAppendString("(", out, out_size); SafeAppendString("(", out, out_size);
if (g_symbolize_open_object_file_callback) { if (g_symbolize_open_object_file_callback) {
object_fd = g_symbolize_open_object_file_callback(pc0, start_address, object_fd = g_symbolize_open_object_file_callback(
base_address, out + 1, pc0, start_address, base_address, out + 1, out_size - 1);
out_size - 1);
} else { } else {
object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, start_address, object_fd = OpenObjectFileContainingPcAndGetStartAddress(
base_address, pc0, start_address, base_address, out + 1, out_size - 1);
out + 1,
out_size - 1);
} }
FileDescriptor wrapped_object_fd(object_fd); FileDescriptor wrapped_object_fd(object_fd);
#if defined(PRINT_UNSYMBOLIZED_STACK_TRACES) # if defined(PRINT_UNSYMBOLIZED_STACK_TRACES)
{ {
#else # else
// Check whether a file name was returned. // Check whether a file name was returned.
if (object_fd < 0) { if (object_fd < 0) {
#endif # endif
if (out[1]) { if (out[1]) {
// The object file containing PC was determined successfully however the // The object file containing PC was determined successfully however the
// object file was not opened successfully. This is still considered // object file was not opened successfully. This is still considered
@ -804,16 +799,15 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
// Note: relocation (and much of the rest of this code) will be // Note: relocation (and much of the rest of this code) will be
// wrong for prelinked shared libraries and PIE executables. // wrong for prelinked shared libraries and PIE executables.
uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0; uint64_t relocation = (elf_type == ET_DYN) ? start_address : 0;
int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), pc,
pc, out, out_size, out, out_size, relocation);
relocation);
if (num_bytes_written > 0) { if (num_bytes_written > 0) {
out += static_cast<size_t>(num_bytes_written); out += static_cast<size_t>(num_bytes_written);
out_size -= static_cast<size_t>(num_bytes_written); out_size -= static_cast<size_t>(num_bytes_written);
} }
} }
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, out, out_size,
out, out_size, base_address)) { base_address)) {
if (out[1] && !g_symbolize_callback) { if (out[1] && !g_symbolize_callback) {
// The object file containing PC was opened successfully however the // The object file containing PC was opened successfully however the
// symbol was not found. The object may have been stripped. This is still // symbol was not found. The object may have been stripped. This is still
@ -835,14 +829,15 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
} // namespace google } // namespace google
#elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) # elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
#include <dlfcn.h> # include <dlfcn.h>
#include <cstring>
# include <cstring>
namespace google { namespace google {
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
size_t out_size) { size_t out_size) {
Dl_info info; Dl_info info;
if (dladdr(pc, &info)) { if (dladdr(pc, &info)) {
@ -860,19 +855,19 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
} // namespace google } // namespace google
#elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) # elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
#include <windows.h> # include <dbghelp.h>
#include <dbghelp.h> # include <windows.h>
#ifdef _MSC_VER # ifdef _MSC_VER
#pragma comment(lib, "dbghelp") # pragma comment(lib, "dbghelp")
#endif # endif
namespace google { namespace google {
class SymInitializer { class SymInitializer {
public: public:
HANDLE process; HANDLE process;
bool ready; bool ready;
SymInitializer() : process(nullptr), ready(false) { SymInitializer() : process(nullptr), ready(false) {
@ -891,12 +886,13 @@ public:
SymCleanup(process); SymCleanup(process);
// We do not need to close `HANDLE process` because it's a "pseudo handle." // We do not need to close `HANDLE process` because it's a "pseudo handle."
} }
private:
private:
SymInitializer(const SymInitializer&); SymInitializer(const SymInitializer&);
SymInitializer& operator=(const SymInitializer&); SymInitializer& operator=(const SymInitializer&);
}; };
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
size_t out_size) { size_t out_size) {
const static SymInitializer symInitializer; const static SymInitializer symInitializer;
if (!symInitializer.ready) { if (!symInitializer.ready) {
@ -905,13 +901,13 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
// Resolve symbol information from address. // Resolve symbol information from address.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx
char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(buf); SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buf);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME; symbol->MaxNameLen = MAX_SYM_NAME;
// We use the ANSI version to ensure the string type is always `char *`. // We use the ANSI version to ensure the string type is always `char *`.
// This could break if a symbol has Unicode in it. // This could break if a symbol has Unicode in it.
BOOL ret = SymFromAddr(symInitializer.process, BOOL ret = SymFromAddr(symInitializer.process, reinterpret_cast<DWORD64>(pc),
reinterpret_cast<DWORD64>(pc), 0, symbol); 0, symbol);
if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) { if (ret == 1 && static_cast<ssize_t>(symbol->NameLen) < out_size) {
// `NameLen` does not include the null terminating character. // `NameLen` does not include the null terminating character.
strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1); strncpy(out, symbol->Name, static_cast<size_t>(symbol->NameLen) + 1);
@ -925,23 +921,23 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
} // namespace google } // namespace google
#else # else
# error BUG: HAVE_SYMBOLIZE was wrongly set # error BUG: HAVE_SYMBOLIZE was wrongly set
#endif # endif
namespace google { namespace google {
bool Symbolize(void *pc, char *out, size_t out_size) { bool Symbolize(void* pc, char* out, size_t out_size) {
return SymbolizeAndDemangle(pc, out, out_size); return SymbolizeAndDemangle(pc, out, out_size);
} }
} // namespace google } // namespace google
#else /* HAVE_SYMBOLIZE */ #else /* HAVE_SYMBOLIZE */
#include <cassert> # include <cassert>
#include "config.h" # include "config.h"
namespace google { namespace google {

View File

@ -60,48 +60,48 @@
#ifdef HAVE_SYMBOLIZE #ifdef HAVE_SYMBOLIZE
#if defined(__ELF__) // defined by gcc # if defined(__ELF__) // defined by gcc
#if defined(__OpenBSD__) # if defined(__OpenBSD__)
#include <sys/exec_elf.h> # include <sys/exec_elf.h>
#else # else
#include <elf.h> # include <elf.h>
#endif # endif
#if !defined(ANDROID) # if !defined(ANDROID)
#include <link.h> // For ElfW() macro. # include <link.h> // For ElfW() macro.
#endif # endif
// For systems where SIZEOF_VOID_P is not defined, determine it // For systems where SIZEOF_VOID_P is not defined, determine it
// based on __LP64__ (defined by gcc on 64-bit systems) // based on __LP64__ (defined by gcc on 64-bit systems)
#if !defined(SIZEOF_VOID_P) # if !defined(SIZEOF_VOID_P)
# if defined(__LP64__) # if defined(__LP64__)
# define SIZEOF_VOID_P 8 # define SIZEOF_VOID_P 8
# else # else
# define SIZEOF_VOID_P 4 # define SIZEOF_VOID_P 4
# endif # endif
#endif # endif
// If there is no ElfW macro, let's define it by ourself. // If there is no ElfW macro, let's define it by ourself.
#ifndef ElfW # ifndef ElfW
# if SIZEOF_VOID_P == 4 # if SIZEOF_VOID_P == 4
# define ElfW(type) Elf32_##type # define ElfW(type) Elf32_##type
# elif SIZEOF_VOID_P == 8 # elif SIZEOF_VOID_P == 8
# define ElfW(type) Elf64_##type # define ElfW(type) Elf64_##type
# else # else
# error "Unknown sizeof(void *)" # error "Unknown sizeof(void *)"
# endif # endif
#endif # endif
namespace google { namespace google {
// Gets the section header for the given name, if it exists. Returns true on // Gets the section header for the given name, if it exists. Returns true on
// success. Otherwise, returns false. // success. Otherwise, returns false.
bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, bool GetSectionHeaderByName(int fd, const char* name, size_t name_len,
ElfW(Shdr) *out); ElfW(Shdr) * out);
} // namespace google } // namespace google
#endif /* __ELF__ */ # endif /* __ELF__ */
namespace google { namespace google {
@ -116,7 +116,7 @@ namespace google {
// counter "pc". The callback function should write output to "out" // counter "pc". The callback function should write output to "out"
// and return the size of the output written. On error, the callback // and return the size of the output written. On error, the callback
// function should return -1. // function should return -1.
using SymbolizeCallback = int (*)(int, void *, char *, size_t, uint64_t); using SymbolizeCallback = int (*)(int, void*, char*, size_t, uint64_t);
GLOG_EXPORT GLOG_EXPORT
void InstallSymbolizeCallback(SymbolizeCallback callback); void InstallSymbolizeCallback(SymbolizeCallback callback);
@ -130,8 +130,8 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
// file is opened successfully, returns the file descriptor. Otherwise, // file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer // returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator). // (including the null-terminator).
using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t &, using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&,
uint64_t &, char *, size_t); char*, size_t);
void InstallSymbolizeOpenObjectFileCallback( void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback); SymbolizeOpenObjectFileCallback callback);

View File

@ -42,7 +42,7 @@
#include "utilities.h" #include "utilities.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
@ -52,17 +52,17 @@ using namespace google;
// Avoid compile error due to "cast between pointer-to-function and // Avoid compile error due to "cast between pointer-to-function and
// pointer-to-object is an extension" warnings. // pointer-to-object is an extension" warnings.
#if defined(__GNUG__) #if defined(__GNUG__)
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" # pragma GCC diagnostic ignored "-Wpedantic"
#endif #endif
#if defined(HAVE_STACKTRACE) #if defined(HAVE_STACKTRACE)
#define always_inline # define always_inline
#if defined(__ELF__) || defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) # if defined(__ELF__) || defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
// A wrapper function for Symbolize() to make the unit test simple. // A wrapper function for Symbolize() to make the unit test simple.
static const char *TrySymbolize(void *pc) { static const char* TrySymbolize(void* pc) {
static char symbol[4096]; static char symbol[4096];
if (Symbolize(pc, symbol, sizeof(symbol))) { if (Symbolize(pc, symbol, sizeof(symbol))) {
return symbol; return symbol;
@ -70,24 +70,25 @@ static const char *TrySymbolize(void *pc) {
return nullptr; return nullptr;
} }
} }
#endif # endif
# if defined(__ELF__) # if defined(__ELF__)
// This unit tests make sense only with GCC. // This unit tests make sense only with GCC.
// Uses lots of GCC specific features. // Uses lots of GCC specific features.
#if defined(__GNUC__) && !defined(__OPENCC__) # if defined(__GNUC__) && !defined(__OPENCC__)
# if __GNUC__ >= 4 # if __GNUC__ >= 4
# define TEST_WITH_MODERN_GCC # define TEST_WITH_MODERN_GCC
# if defined(__i386__) && __i386__ // always_inline isn't supported for x86_64 with GCC 4.1.0. # if defined(__i386__) && __i386__ // always_inline isn't supported for
# undef always_inline // x86_64 with GCC 4.1.0.
# define always_inline __attribute__((always_inline)) # undef always_inline
# define HAVE_ALWAYS_INLINE # define always_inline __attribute__((always_inline))
# endif // __i386__ # define HAVE_ALWAYS_INLINE
# else # endif // __i386__
# endif // __GNUC__ >= 4 # else
# define TEST_WITH_LABEL_ADDRESSES # endif // __GNUC__ >= 4
#endif # define TEST_WITH_LABEL_ADDRESSES
# endif
// Make them C linkage to avoid mangled names. // Make them C linkage to avoid mangled names.
extern "C" { extern "C" {
@ -112,18 +113,18 @@ TEST(Symbolize, Symbolize) {
// reinterpret_cast<void *>(&func). // reinterpret_cast<void *>(&func).
// Compilers should give us pointers to them. // Compilers should give us pointers to them.
EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func))); EXPECT_STREQ("nonstatic_func", TrySymbolize((void*)(&nonstatic_func)));
// The name of an internal linkage symbol is not specified; allow either a // The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here. // mangled or an unmangled name here.
const char *static_func_symbol = const char* static_func_symbol =
TrySymbolize(reinterpret_cast<void *>(&static_func)); TrySymbolize(reinterpret_cast<void*>(&static_func));
#if !defined(_MSC_VER) || !defined(NDEBUG) # if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(nullptr != static_func_symbol); CHECK(nullptr != static_func_symbol);
EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 || EXPECT_TRUE(strcmp("static_func", static_func_symbol) == 0 ||
strcmp("static_func()", static_func_symbol) == 0); strcmp("static_func()", static_func_symbol) == 0);
#endif # endif
EXPECT_TRUE(nullptr == TrySymbolize(nullptr)); EXPECT_TRUE(nullptr == TrySymbolize(nullptr));
} }
@ -141,14 +142,14 @@ void ATTRIBUTE_NOINLINE Foo::func(int x) {
// With a modern GCC, Symbolize() should return demangled symbol // With a modern GCC, Symbolize() should return demangled symbol
// names. Function parameters should be omitted. // names. Function parameters should be omitted.
#ifdef TEST_WITH_MODERN_GCC # ifdef TEST_WITH_MODERN_GCC
TEST(Symbolize, SymbolizeWithDemangling) { TEST(Symbolize, SymbolizeWithDemangling) {
Foo::func(100); Foo::func(100);
#if !defined(_MSC_VER) || !defined(NDEBUG) # if !defined(_MSC_VER) || !defined(NDEBUG)
EXPECT_STREQ("Foo::func()", TrySymbolize((void *)(&Foo::func))); EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func)));
#endif # endif
} }
#endif # endif
// Tests that verify that Symbolize footprint is within some limit. // Tests that verify that Symbolize footprint is within some limit.
@ -167,9 +168,9 @@ TEST(Symbolize, SymbolizeWithDemangling) {
// calls Symbolize. The difference between the stack consumption of these // calls Symbolize. The difference between the stack consumption of these
// two signals handlers should give us the Symbolize stack foorprint. // two signals handlers should give us the Symbolize stack foorprint.
static void *g_pc_to_symbolize; static void* g_pc_to_symbolize;
static char g_symbolize_buffer[4096]; static char g_symbolize_buffer[4096];
static char *g_symbolize_result; static char* g_symbolize_result;
static void EmptySignalHandler(int /*signo*/) {} static void EmptySignalHandler(int /*signo*/) {}
@ -188,7 +189,7 @@ const char kAlternateStackFillValue = 0x55;
// These helper functions look at the alternate stack buffer, and figure // These helper functions look at the alternate stack buffer, and figure
// out what portion of this buffer has been touched - this is the stack // out what portion of this buffer has been touched - this is the stack
// consumption of the signal handler running on this alternate stack. // consumption of the signal handler running on this alternate stack.
static ATTRIBUTE_NOINLINE bool StackGrowsDown(int *x) { static ATTRIBUTE_NOINLINE bool StackGrowsDown(int* x) {
int y; int y;
return &y < x; return &y < x;
} }
@ -210,11 +211,10 @@ static int GetStackConsumption(const char* alt_stack) {
return -1; return -1;
} }
#ifdef HAVE_SIGALTSTACK # ifdef HAVE_SIGALTSTACK
// Call Symbolize and figure out the stack footprint of this call. // Call Symbolize and figure out the stack footprint of this call.
static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) { static const char* SymbolizeStackConsumption(void* pc, int* stack_consumed) {
g_pc_to_symbolize = pc; g_pc_to_symbolize = pc;
// The alt-signal-stack cannot be heap allocated because there is a // The alt-signal-stack cannot be heap allocated because there is a
@ -282,19 +282,19 @@ static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {
return g_symbolize_result; return g_symbolize_result;
} }
#ifdef __ppc64__ # ifdef __ppc64__
// Symbolize stack consumption should be within 4kB. // Symbolize stack consumption should be within 4kB.
const int kStackConsumptionUpperLimit = 4096; const int kStackConsumptionUpperLimit = 4096;
#else # else
// Symbolize stack consumption should be within 2kB. // Symbolize stack consumption should be within 2kB.
const int kStackConsumptionUpperLimit = 2048; const int kStackConsumptionUpperLimit = 2048;
#endif # endif
TEST(Symbolize, SymbolizeStackConsumption) { TEST(Symbolize, SymbolizeStackConsumption) {
int stack_consumed; int stack_consumed;
const char* symbol; const char* symbol;
symbol = SymbolizeStackConsumption(reinterpret_cast<void *>(&nonstatic_func), symbol = SymbolizeStackConsumption(reinterpret_cast<void*>(&nonstatic_func),
&stack_consumed); &stack_consumed);
EXPECT_STREQ("nonstatic_func", symbol); EXPECT_STREQ("nonstatic_func", symbol);
EXPECT_GT(stack_consumed, 0); EXPECT_GT(stack_consumed, 0);
@ -302,7 +302,7 @@ TEST(Symbolize, SymbolizeStackConsumption) {
// The name of an internal linkage symbol is not specified; allow either a // The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here. // mangled or an unmangled name here.
symbol = SymbolizeStackConsumption(reinterpret_cast<void *>(&static_func), symbol = SymbolizeStackConsumption(reinterpret_cast<void*>(&static_func),
&stack_consumed); &stack_consumed);
CHECK(nullptr != symbol); CHECK(nullptr != symbol);
EXPECT_TRUE(strcmp("static_func", symbol) == 0 || EXPECT_TRUE(strcmp("static_func", symbol) == 0 ||
@ -311,91 +311,91 @@ TEST(Symbolize, SymbolizeStackConsumption) {
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
} }
#ifdef TEST_WITH_MODERN_GCC # ifdef TEST_WITH_MODERN_GCC
TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) { TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
Foo::func(100); Foo::func(100);
int stack_consumed; int stack_consumed;
const char* symbol; const char* symbol;
symbol = SymbolizeStackConsumption(reinterpret_cast<void *>(&Foo::func), symbol = SymbolizeStackConsumption(reinterpret_cast<void*>(&Foo::func),
&stack_consumed); &stack_consumed);
EXPECT_STREQ("Foo::func()", symbol); EXPECT_STREQ("Foo::func()", symbol);
EXPECT_GT(stack_consumed, 0); EXPECT_GT(stack_consumed, 0);
EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
} }
#endif # endif
#endif // HAVE_SIGALTSTACK # endif // HAVE_SIGALTSTACK
// x86 specific tests. Uses some inline assembler. // x86 specific tests. Uses some inline assembler.
extern "C" { extern "C" {
inline void* always_inline inline_func() { inline void* always_inline inline_func() {
void *pc = nullptr; void* pc = nullptr;
#ifdef TEST_WITH_LABEL_ADDRESSES # ifdef TEST_WITH_LABEL_ADDRESSES
pc = &&curr_pc; pc = &&curr_pc;
curr_pc: curr_pc:
#endif # endif
return pc; return pc;
} }
void* ATTRIBUTE_NOINLINE non_inline_func(); void* ATTRIBUTE_NOINLINE non_inline_func();
void* ATTRIBUTE_NOINLINE non_inline_func() { void* ATTRIBUTE_NOINLINE non_inline_func() {
void *pc = nullptr; void* pc = nullptr;
#ifdef TEST_WITH_LABEL_ADDRESSES # ifdef TEST_WITH_LABEL_ADDRESSES
pc = &&curr_pc; pc = &&curr_pc;
curr_pc: curr_pc:
#endif # endif
return pc; return pc;
} }
static void ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() { static void ATTRIBUTE_NOINLINE TestWithPCInsideNonInlineFunction() {
#if defined(TEST_WITH_LABEL_ADDRESSES) && defined(HAVE_ATTRIBUTE_NOINLINE) # if defined(TEST_WITH_LABEL_ADDRESSES) && defined(HAVE_ATTRIBUTE_NOINLINE)
void *pc = non_inline_func(); void* pc = non_inline_func();
const char *symbol = TrySymbolize(pc); const char* symbol = TrySymbolize(pc);
#if !defined(_MSC_VER) || !defined(NDEBUG) # if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != nullptr); CHECK(symbol != nullptr);
CHECK_STREQ(symbol, "non_inline_func"); CHECK_STREQ(symbol, "non_inline_func");
#endif # endif
cout << "Test case TestWithPCInsideNonInlineFunction passed." << endl; cout << "Test case TestWithPCInsideNonInlineFunction passed." << endl;
#endif # endif
} }
static void ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() { static void ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() {
#if defined(TEST_WITH_LABEL_ADDRESSES) && defined(HAVE_ALWAYS_INLINE) # if defined(TEST_WITH_LABEL_ADDRESSES) && defined(HAVE_ALWAYS_INLINE)
void *pc = inline_func(); // Must be inlined. void* pc = inline_func(); // Must be inlined.
const char *symbol = TrySymbolize(pc); const char* symbol = TrySymbolize(pc);
#if !defined(_MSC_VER) || !defined(NDEBUG) # if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != nullptr); CHECK(symbol != nullptr);
CHECK_STREQ(symbol, __FUNCTION__); CHECK_STREQ(symbol, __FUNCTION__);
#endif # endif
cout << "Test case TestWithPCInsideInlineFunction passed." << endl; cout << "Test case TestWithPCInsideInlineFunction passed." << endl;
#endif # endif
} }
} }
// Test with a return address. // Test with a return address.
static void ATTRIBUTE_NOINLINE TestWithReturnAddress() { static void ATTRIBUTE_NOINLINE TestWithReturnAddress() {
#if defined(HAVE_ATTRIBUTE_NOINLINE) # if defined(HAVE_ATTRIBUTE_NOINLINE)
void *return_address = __builtin_return_address(0); void* return_address = __builtin_return_address(0);
const char *symbol = TrySymbolize(return_address); const char* symbol = TrySymbolize(return_address);
#if !defined(_MSC_VER) || !defined(NDEBUG) # if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != nullptr); CHECK(symbol != nullptr);
CHECK_STREQ(symbol, "main"); CHECK_STREQ(symbol, "main");
#endif # endif
cout << "Test case TestWithReturnAddress passed." << endl; cout << "Test case TestWithReturnAddress passed." << endl;
#endif # endif
} }
# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) # elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
#ifdef _MSC_VER # ifdef _MSC_VER
#include <intrin.h> # include <intrin.h>
#pragma intrinsic(_ReturnAddress) # pragma intrinsic(_ReturnAddress)
#endif # endif
struct Foo { struct Foo {
static void func(int x); static void func(int x);
@ -410,37 +410,37 @@ __declspec(noinline) void Foo::func(int x) {
TEST(Symbolize, SymbolizeWithDemangling) { TEST(Symbolize, SymbolizeWithDemangling) {
Foo::func(100); Foo::func(100);
const char* ret = TrySymbolize((void *)(&Foo::func)); const char* ret = TrySymbolize((void*)(&Foo::func));
#if defined(HAVE_DBGHELP) && !defined(NDEBUG) # if defined(HAVE_DBGHELP) && !defined(NDEBUG)
EXPECT_STREQ("public: static void __cdecl Foo::func(int)", ret); EXPECT_STREQ("public: static void __cdecl Foo::func(int)", ret);
#endif # endif
} }
__declspec(noinline) void TestWithReturnAddress() { __declspec(noinline) void TestWithReturnAddress() {
void *return_address = void* return_address =
#ifdef __GNUC__ // Cygwin and MinGW support # ifdef __GNUC__ // Cygwin and MinGW support
__builtin_return_address(0) __builtin_return_address(0)
#else # else
_ReturnAddress() _ReturnAddress()
#endif # endif
; ;
const char *symbol = TrySymbolize(return_address); const char* symbol = TrySymbolize(return_address);
#if !defined(_MSC_VER) || !defined(NDEBUG) # if !defined(_MSC_VER) || !defined(NDEBUG)
CHECK(symbol != nullptr); CHECK(symbol != nullptr);
CHECK_STREQ(symbol, "main"); CHECK_STREQ(symbol, "main");
#endif # endif
cout << "Test case TestWithReturnAddress passed." << endl; cout << "Test case TestWithReturnAddress passed." << endl;
} }
# endif // __ELF__ # endif // __ELF__
#endif // HAVE_STACKTRACE #endif // HAVE_STACKTRACE
int main(int argc, char **argv) { int main(int argc, char** argv) {
FLAGS_logtostderr = true; FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]); InitGoogleLogging(argv[0]);
InitGoogleTest(&argc, argv); InitGoogleTest(&argc, argv);
#if defined(HAVE_SYMBOLIZE) && defined(HAVE_STACKTRACE) #if defined(HAVE_SYMBOLIZE) && defined(HAVE_STACKTRACE)
# if defined(__ELF__) # if defined(__ELF__)
// We don't want to get affected by the callback interface, that may be // We don't want to get affected by the callback interface, that may be
// used to install some callback function at InitGoogle() time. // used to install some callback function at InitGoogle() time.
InstallSymbolizeCallback(nullptr); InstallSymbolizeCallback(nullptr);
@ -449,13 +449,13 @@ int main(int argc, char **argv) {
TestWithPCInsideNonInlineFunction(); TestWithPCInsideNonInlineFunction();
TestWithReturnAddress(); TestWithReturnAddress();
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) # elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
TestWithReturnAddress(); TestWithReturnAddress();
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
# else // GLOG_OS_WINDOWS # else // GLOG_OS_WINDOWS
printf("PASS (no symbolize_unittest support)\n"); printf("PASS (no symbolize_unittest support)\n");
return 0; return 0;
# endif // __ELF__ # endif // __ELF__
#else #else
printf("PASS (no symbolize support)\n"); printf("PASS (no symbolize support)\n");
return 0; return 0;
@ -463,5 +463,5 @@ int main(int argc, char **argv) {
} }
#if defined(__GNUG__) #if defined(__GNUG__)
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif

View File

@ -29,33 +29,33 @@
// //
// Author: Shinichiro Hamaji // Author: Shinichiro Hamaji
#include "config.h"
#include "utilities.h" #include "utilities.h"
#include <csignal>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <csignal> #include "config.h"
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#include <ctime> #include <ctime>
#if defined(HAVE_SYSCALL_H) #if defined(HAVE_SYSCALL_H)
#include <syscall.h> // for syscall() # include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H) #elif defined(HAVE_SYS_SYSCALL_H)
#include <sys/syscall.h> // for syscall() # include <sys/syscall.h> // for syscall()
#endif #endif
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
# include <syslog.h> # include <syslog.h>
#endif #endif
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> // For geteuid. # include <unistd.h> // For geteuid.
#endif #endif
#ifdef HAVE_PWD_H #ifdef HAVE_PWD_H
# include <pwd.h> # include <pwd.h>
#endif #endif
#ifdef __ANDROID__ #ifdef __ANDROID__
#include <android/log.h> # include <android/log.h>
#endif #endif
#include "base/googleinit.h" #include "base/googleinit.h"
@ -75,9 +75,9 @@ bool IsGoogleLoggingInitialized() {
// The following APIs are all internal. // The following APIs are all internal.
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
#include "stacktrace.h" # include "base/commandlineflags.h"
#include "symbolize.h" # include "stacktrace.h"
#include "base/commandlineflags.h" # include "symbolize.h"
GLOG_DEFINE_bool(symbolize_stacktrace, true, GLOG_DEFINE_bool(symbolize_stacktrace, true,
"Symbolize the stack trace in the tombstone"); "Symbolize the stack trace in the tombstone");
@ -90,44 +90,44 @@ using DebugWriter = void(const char*, void*);
// For some environments, add two extra bytes for the leading "0x". // For some environments, add two extra bytes for the leading "0x".
static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*); static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
static void DebugWriteToStderr(const char* data, void *) { static void DebugWriteToStderr(const char* data, void*) {
// This one is signal-safe. // This one is signal-safe.
if (write(STDERR_FILENO, data, strlen(data)) < 0) { if (write(STDERR_FILENO, data, strlen(data)) < 0) {
// Ignore errors. // Ignore errors.
} }
#if defined(__ANDROID__) # if defined(__ANDROID__)
// ANDROID_LOG_FATAL as fatal error occurred and now is dumping call stack. // ANDROID_LOG_FATAL as fatal error occurred and now is dumping call stack.
__android_log_write(ANDROID_LOG_FATAL, __android_log_write(ANDROID_LOG_FATAL,
glog_internal_namespace_::ProgramInvocationShortName(), glog_internal_namespace_::ProgramInvocationShortName(),
data); data);
#endif # endif
} }
static void DebugWriteToString(const char* data, void *arg) { static void DebugWriteToString(const char* data, void* arg) {
reinterpret_cast<string*>(arg)->append(data); reinterpret_cast<string*>(arg)->append(data);
} }
#ifdef HAVE_SYMBOLIZE # ifdef HAVE_SYMBOLIZE
// Print a program counter and its symbol name. // Print a program counter and its symbol name.
static void DumpPCAndSymbol(DebugWriter *writerfn, void *arg, void *pc, static void DumpPCAndSymbol(DebugWriter* writerfn, void* arg, void* pc,
const char * const prefix) { const char* const prefix) {
char tmp[1024]; char tmp[1024];
const char *symbol = "(unknown)"; const char* symbol = "(unknown)";
// Symbolizes the previous address of pc because pc may be in the // Symbolizes the previous address of pc because pc may be in the
// next function. The overrun happens when the function ends with // next function. The overrun happens when the function ends with
// a call to a function annotated noreturn (e.g. CHECK). // a call to a function annotated noreturn (e.g. CHECK).
if (Symbolize(reinterpret_cast<char *>(pc) - 1, tmp, sizeof(tmp))) { if (Symbolize(reinterpret_cast<char*>(pc) - 1, tmp, sizeof(tmp))) {
symbol = tmp; symbol = tmp;
} }
char buf[1024]; char buf[1024];
std::snprintf(buf, sizeof(buf), "%s@ %*p %s\n", prefix, std::snprintf(buf, sizeof(buf), "%s@ %*p %s\n", prefix,
kPrintfPointerFieldWidth, pc, symbol); kPrintfPointerFieldWidth, pc, symbol);
writerfn(buf, arg); writerfn(buf, arg);
} }
#endif # endif
static void DumpPC(DebugWriter *writerfn, void *arg, void *pc, static void DumpPC(DebugWriter* writerfn, void* arg, void* pc,
const char * const prefix) { const char* const prefix) {
char buf[100]; char buf[100];
std::snprintf(buf, sizeof(buf), "%s@ %*p\n", prefix, kPrintfPointerFieldWidth, std::snprintf(buf, sizeof(buf), "%s@ %*p\n", prefix, kPrintfPointerFieldWidth,
pc); pc);
@ -135,26 +135,26 @@ static void DumpPC(DebugWriter *writerfn, void *arg, void *pc,
} }
// Dump current stack trace as directed by writerfn // Dump current stack trace as directed by writerfn
static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg) { static void DumpStackTrace(int skip_count, DebugWriter* writerfn, void* arg) {
// Print stack trace // Print stack trace
void* stack[32]; void* stack[32];
int depth = GetStackTrace(stack, ARRAYSIZE(stack), skip_count+1); int depth = GetStackTrace(stack, ARRAYSIZE(stack), skip_count + 1);
for (int i = 0; i < depth; i++) { for (int i = 0; i < depth; i++) {
#if defined(HAVE_SYMBOLIZE) # if defined(HAVE_SYMBOLIZE)
if (FLAGS_symbolize_stacktrace) { if (FLAGS_symbolize_stacktrace) {
DumpPCAndSymbol(writerfn, arg, stack[i], " "); DumpPCAndSymbol(writerfn, arg, stack[i], " ");
} else { } else {
DumpPC(writerfn, arg, stack[i], " "); DumpPC(writerfn, arg, stack[i], " ");
} }
#else # else
DumpPC(writerfn, arg, stack[i], " "); DumpPC(writerfn, arg, stack[i], " ");
#endif # endif
} }
} }
#ifdef __GNUC__ # ifdef __GNUC__
__attribute__((noreturn)) __attribute__((noreturn))
#endif # endif
static void static void
DumpStackTraceAndExit() { DumpStackTraceAndExit() {
DumpStackTrace(1, DebugWriteToStderr, nullptr); DumpStackTrace(1, DebugWriteToStderr, nullptr);
@ -163,15 +163,15 @@ DumpStackTraceAndExit() {
if (IsFailureSignalHandlerInstalled()) { if (IsFailureSignalHandlerInstalled()) {
// Set the default signal handler for SIGABRT, to avoid invoking our // Set the default signal handler for SIGABRT, to avoid invoking our
// own signal handler installed by InstallFailureSignalHandler(). // own signal handler installed by InstallFailureSignalHandler().
#ifdef HAVE_SIGACTION # ifdef HAVE_SIGACTION
struct sigaction sig_action; struct sigaction sig_action;
memset(&sig_action, 0, sizeof(sig_action)); memset(&sig_action, 0, sizeof(sig_action));
sigemptyset(&sig_action.sa_mask); sigemptyset(&sig_action.sa_mask);
sig_action.sa_handler = SIG_DFL; sig_action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sig_action, nullptr); sigaction(SIGABRT, &sig_action, nullptr);
#elif defined(GLOG_OS_WINDOWS) # elif defined(GLOG_OS_WINDOWS)
signal(SIGABRT, SIG_DFL); signal(SIGABRT, SIG_DFL);
#endif // HAVE_SIGACTION # endif // HAVE_SIGACTION
} }
abort(); abort();
@ -199,14 +199,15 @@ struct timeval {
long tv_sec, tv_usec; long tv_sec, tv_usec;
}; };
// Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd // Based on:
// http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
// See COPYING for copyright information. // See COPYING for copyright information.
static int gettimeofday(struct timeval *tv, void* /*tz*/) { static int gettimeofday(struct timeval* tv, void* /*tz*/) {
#ifdef __GNUC__ # ifdef __GNUC__
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long" # pragma GCC diagnostic ignored "-Wlong-long"
#endif # endif
#define EPOCHFILETIME (116444736000000000ULL) # define EPOCHFILETIME (116444736000000000ULL)
FILETIME ft; FILETIME ft;
ULARGE_INTEGER li; ULARGE_INTEGER li;
uint64 tt; uint64 tt;
@ -217,9 +218,9 @@ static int gettimeofday(struct timeval *tv, void* /*tz*/) {
tt = (li.QuadPart - EPOCHFILETIME) / 10; tt = (li.QuadPart - EPOCHFILETIME) / 10;
tv->tv_sec = tt / 1000000; tv->tv_sec = tt / 1000000;
tv->tv_usec = tt % 1000000; tv->tv_usec = tt % 1000000;
#ifdef __GNUC__ # ifdef __GNUC__
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif # endif
return 0; return 0;
} }
@ -232,9 +233,7 @@ int64 CycleClock_Now() {
return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec; return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
} }
int64 UsecToCycles(int64 usec) { int64 UsecToCycles(int64 usec) { return usec; }
return usec;
}
WallTime WallTime_Now() { WallTime WallTime_Now() {
// Now, cycle clock is retuning microseconds since the epoch. // Now, cycle clock is retuning microseconds since the epoch.
@ -242,9 +241,7 @@ WallTime WallTime_Now() {
} }
static int32 g_main_thread_pid = getpid(); static int32 g_main_thread_pid = getpid();
int32 GetMainThreadPid() { int32 GetMainThreadPid() { return g_main_thread_pid; }
return g_main_thread_pid;
}
bool PidHasChanged() { bool PidHasChanged() {
int32 pid = getpid(); int32 pid = getpid();
@ -258,24 +255,24 @@ bool PidHasChanged() {
pid_t GetTID() { pid_t GetTID() {
// On Linux and MacOSX, we try to use gettid(). // On Linux and MacOSX, we try to use gettid().
#if defined GLOG_OS_LINUX || defined GLOG_OS_MACOSX #if defined GLOG_OS_LINUX || defined GLOG_OS_MACOSX
#ifndef __NR_gettid # ifndef __NR_gettid
#ifdef GLOG_OS_MACOSX # ifdef GLOG_OS_MACOSX
#define __NR_gettid SYS_gettid # define __NR_gettid SYS_gettid
#elif ! defined __i386__ # elif !defined __i386__
#error "Must define __NR_gettid for non-x86 platforms" # error "Must define __NR_gettid for non-x86 platforms"
#else # else
#define __NR_gettid 224 # define __NR_gettid 224
#endif # endif
#endif # endif
static bool lacks_gettid = false; static bool lacks_gettid = false;
if (!lacks_gettid) { if (!lacks_gettid) {
#if (defined(GLOG_OS_MACOSX) && defined(HAVE_PTHREAD_THREADID_NP)) # if (defined(GLOG_OS_MACOSX) && defined(HAVE_PTHREAD_THREADID_NP))
uint64_t tid64; uint64_t tid64;
const int error = pthread_threadid_np(nullptr, &tid64); const int error = pthread_threadid_np(nullptr, &tid64);
pid_t tid = error ? -1 : static_cast<pid_t>(tid64); pid_t tid = error ? -1 : static_cast<pid_t>(tid64);
#else # else
auto tid = static_cast<pid_t>(syscall(__NR_gettid)); auto tid = static_cast<pid_t>(syscall(__NR_gettid));
#endif # endif
if (tid != -1) { if (tid != -1) {
return tid; return tid;
} }
@ -305,16 +302,13 @@ pid_t GetTID() {
const char* const_basename(const char* filepath) { const char* const_basename(const char* filepath) {
const char* base = strrchr(filepath, '/'); const char* base = strrchr(filepath, '/');
#ifdef GLOG_OS_WINDOWS // Look for either path separator in Windows #ifdef GLOG_OS_WINDOWS // Look for either path separator in Windows
if (!base) if (!base) base = strrchr(filepath, '\\');
base = strrchr(filepath, '\\');
#endif #endif
return base ? (base+1) : filepath; return base ? (base + 1) : filepath;
} }
static string g_my_user_name; static string g_my_user_name;
const string& MyUserName() { const string& MyUserName() { return g_my_user_name; }
return g_my_user_name;
}
static void MyUserNameInitializer() { static void MyUserNameInitializer() {
// TODO(hamaji): Probably this is not portable. // TODO(hamaji): Probably this is not portable.
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
@ -356,8 +350,7 @@ void DumpStackTraceToString(string* stacktrace) {
static const CrashReason* g_reason = nullptr; static const CrashReason* g_reason = nullptr;
void SetCrashReason(const CrashReason* r) { void SetCrashReason(const CrashReason* r) {
sync_val_compare_and_swap(&g_reason, sync_val_compare_and_swap(&g_reason, reinterpret_cast<const CrashReason*>(0),
reinterpret_cast<const CrashReason*>(0),
r); r);
} }
@ -366,7 +359,7 @@ void InitGoogleLoggingUtilities(const char* argv0) {
<< "You called InitGoogleLogging() twice!"; << "You called InitGoogleLogging() twice!";
const char* slash = strrchr(argv0, '/'); const char* slash = strrchr(argv0, '/');
#ifdef GLOG_OS_WINDOWS #ifdef GLOG_OS_WINDOWS
if (!slash) slash = strrchr(argv0, '\\'); if (!slash) slash = strrchr(argv0, '\\');
#endif #endif
g_program_invocation_short_name = slash ? slash + 1 : argv0; g_program_invocation_short_name = slash ? slash + 1 : argv0;
@ -377,7 +370,8 @@ void InitGoogleLoggingUtilities(const char* argv0) {
void ShutdownGoogleLoggingUtilities() { void ShutdownGoogleLoggingUtilities() {
CHECK(IsGoogleLoggingInitialized()) CHECK(IsGoogleLoggingInitialized())
<< "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!"; << "You called ShutdownGoogleLogging() without calling "
"InitGoogleLogging() first!";
g_program_invocation_short_name = nullptr; g_program_invocation_short_name = nullptr;
#ifdef HAVE_SYSLOG_H #ifdef HAVE_SYSLOG_H
closelog(); closelog();
@ -390,13 +384,13 @@ void ShutdownGoogleLoggingUtilities() {
// Make an implementation of stacktrace compiled. // Make an implementation of stacktrace compiled.
#ifdef STACKTRACE_H #ifdef STACKTRACE_H
# include STACKTRACE_H # include STACKTRACE_H
# if 0 # if 0
// For include scanners which can't handle macro expansions. // For include scanners which can't handle macro expansions.
# include "stacktrace_libunwind-inl.h" # include "stacktrace_generic-inl.h"
# include "stacktrace_x86-inl.h" # include "stacktrace_libunwind-inl.h"
# include "stacktrace_x86_64-inl.h" # include "stacktrace_powerpc-inl.h"
# include "stacktrace_powerpc-inl.h" # include "stacktrace_x86-inl.h"
# include "stacktrace_generic-inl.h" # include "stacktrace_x86_64-inl.h"
# endif # endif
#endif #endif

View File

@ -36,9 +36,9 @@
// printf macros for size_t, in the style of inttypes.h // printf macros for size_t, in the style of inttypes.h
#ifdef _LP64 #ifdef _LP64
#define __PRIS_PREFIX "z" # define __PRIS_PREFIX "z"
#else #else
#define __PRIS_PREFIX # define __PRIS_PREFIX
#endif #endif
// Use these macros after a % in a printf format string // Use these macros after a % in a printf format string
@ -58,22 +58,22 @@
#include "glog/logging.h" #include "glog/logging.h"
#if defined(GLOG_OS_WINDOWS) #if defined(GLOG_OS_WINDOWS)
# include "port.h" # include "port.h"
#endif #endif
#include "config.h" #include "config.h"
#if defined(HAVE_UNISTD_H) #if defined(HAVE_UNISTD_H)
#include <unistd.h> # include <unistd.h>
#endif #endif
#if !defined(HAVE_SSIZE_T) #if !defined(HAVE_SSIZE_T)
#if defined(GLOG_OS_WINDOWS) # if defined(GLOG_OS_WINDOWS)
#include <basetsd.h> # include <basetsd.h>
using ssize_t = SSIZE_T; using ssize_t = SSIZE_T;
#else # else
using ssize_t = std::ptrdiff_t; using ssize_t = std::ptrdiff_t;
#endif # endif
#endif #endif
// There are three different ways we can try to get the stack trace: // There are three different ways we can try to get the stack trace:
@ -99,45 +99,45 @@ using ssize_t = std::ptrdiff_t;
// Some code may do that. // Some code may do that.
#if defined(HAVE_LIBUNWIND) #if defined(HAVE_LIBUNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h" # define STACKTRACE_H "stacktrace_libunwind-inl.h"
#elif defined(HAVE_UNWIND) #elif defined(HAVE_UNWIND)
# define STACKTRACE_H "stacktrace_unwind-inl.h" # define STACKTRACE_H "stacktrace_unwind-inl.h"
#elif !defined(NO_FRAME_POINTER) #elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2 # if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h" # define STACKTRACE_H "stacktrace_x86-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2 # elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h" # define STACKTRACE_H "stacktrace_powerpc-inl.h"
# elif defined(GLOG_OS_WINDOWS) # elif defined(GLOG_OS_WINDOWS)
# define STACKTRACE_H "stacktrace_windows-inl.h" # define STACKTRACE_H "stacktrace_windows-inl.h"
# endif # endif
#endif #endif
#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE) #if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE)
# define STACKTRACE_H "stacktrace_generic-inl.h" # define STACKTRACE_H "stacktrace_generic-inl.h"
#endif #endif
#if defined(STACKTRACE_H) #if defined(STACKTRACE_H)
# define HAVE_STACKTRACE # define HAVE_STACKTRACE
#endif #endif
#ifndef GLOG_NO_SYMBOLIZE_DETECTION #ifndef GLOG_NO_SYMBOLIZE_DETECTION
#ifndef HAVE_SYMBOLIZE # ifndef HAVE_SYMBOLIZE
// defined by gcc // defined by gcc
#if defined(__ELF__) && defined(GLOG_OS_LINUX) # if defined(__ELF__) && defined(GLOG_OS_LINUX)
# define HAVE_SYMBOLIZE # define HAVE_SYMBOLIZE
#elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) # elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
// Use dladdr to symbolize. // Use dladdr to symbolize.
# define HAVE_SYMBOLIZE # define HAVE_SYMBOLIZE
#elif defined(GLOG_OS_WINDOWS) # elif defined(GLOG_OS_WINDOWS)
// Use DbgHelp to symbolize // Use DbgHelp to symbolize
# define HAVE_SYMBOLIZE # define HAVE_SYMBOLIZE
#endif # endif
#endif // !defined(HAVE_SYMBOLIZE) # endif // !defined(HAVE_SYMBOLIZE)
#endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION) #endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION)
#ifndef ARRAYSIZE #ifndef ARRAYSIZE
// There is a better way, but this is good enough for our purpose. // There is a better way, but this is good enough for our purpose.
# define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a))) # define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
#endif #endif
namespace google { namespace google {
@ -145,21 +145,21 @@ namespace google {
namespace glog_internal_namespace_ { namespace glog_internal_namespace_ {
#if defined(__has_attribute) #if defined(__has_attribute)
#if __has_attribute(noinline) # if __has_attribute(noinline)
# define ATTRIBUTE_NOINLINE __attribute__ ((noinline)) # define ATTRIBUTE_NOINLINE __attribute__((noinline))
# define HAVE_ATTRIBUTE_NOINLINE # define HAVE_ATTRIBUTE_NOINLINE
#endif # endif
#endif #endif
#if !defined(HAVE_ATTRIBUTE_NOINLINE) #if !defined(HAVE_ATTRIBUTE_NOINLINE)
#if defined(GLOG_OS_WINDOWS) # if defined(GLOG_OS_WINDOWS)
# define ATTRIBUTE_NOINLINE __declspec(noinline) # define ATTRIBUTE_NOINLINE __declspec(noinline)
# define HAVE_ATTRIBUTE_NOINLINE # define HAVE_ATTRIBUTE_NOINLINE
#endif # endif
#endif #endif
#if !defined(HAVE_ATTRIBUTE_NOINLINE) #if !defined(HAVE_ATTRIBUTE_NOINLINE)
# define ATTRIBUTE_NOINLINE # define ATTRIBUTE_NOINLINE
#endif #endif
const char* ProgramInvocationShortName(); const char* ProgramInvocationShortName();
@ -184,20 +184,20 @@ const char* const_basename(const char* filepath);
// defined, we try the CPU specific logics (we only support x86 and // defined, we try the CPU specific logics (we only support x86 and
// x86_64 for now) first, then use a naive implementation, which has a // x86_64 for now) first, then use a naive implementation, which has a
// race condition. // race condition.
template<typename T> template <typename T>
inline T sync_val_compare_and_swap(T* ptr, T oldval, T newval) { inline T sync_val_compare_and_swap(T* ptr, T oldval, T newval) {
#if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP) #if defined(HAVE___SYNC_VAL_COMPARE_AND_SWAP)
return __sync_val_compare_and_swap(ptr, oldval, newval); return __sync_val_compare_and_swap(ptr, oldval, newval);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
T ret; T ret;
__asm__ __volatile__("lock; cmpxchg %1, (%2);" __asm__ __volatile__("lock; cmpxchg %1, (%2);"
:"=a"(ret) : "=a"(ret)
// GCC may produces %sil or %dil for // GCC may produces %sil or %dil for
// constraint "r", but some of apple's gas // constraint "r", but some of apple's gas
// doesn't know the 8 bit registers. // doesn't know the 8 bit registers.
// We use "q" to avoid these registers. // We use "q" to avoid these registers.
:"q"(newval), "q"(ptr), "a"(oldval) : "q"(newval), "q"(ptr), "a"(oldval)
:"memory", "cc"); : "memory", "cc");
return ret; return ret;
#else #else
T ret = *ptr; T ret = *ptr;

View File

@ -34,7 +34,7 @@
#include "googletest.h" #include "googletest.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
#include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
@ -51,7 +51,7 @@ TEST(utilities, InitGoogleLoggingDeathTest) {
ASSERT_DEATH(InitGoogleLogging("foobar"), ""); ASSERT_DEATH(InitGoogleLogging("foobar"), "");
} }
int main(int argc, char **argv) { int main(int argc, char** argv) {
InitGoogleLogging(argv[0]); InitGoogleLogging(argv[0]);
InitGoogleTest(&argc, argv); InitGoogleTest(&argc, argv);

View File

@ -49,14 +49,17 @@
using std::string; using std::string;
GLOG_DEFINE_int32(v, 0, "Show all VLOG(m) messages for m <= this." GLOG_DEFINE_int32(v, 0,
" Overridable by --vmodule."); "Show all VLOG(m) messages for m <= this."
" Overridable by --vmodule.");
GLOG_DEFINE_string(vmodule, "", "per-module verbose level." GLOG_DEFINE_string(
" Argument is a comma-separated list of <module name>=<log level>." vmodule, "",
" <module name> is a glob pattern, matched against the filename base" "per-module verbose level."
" (that is, name ignoring .cc/.h./-inl.h)." " Argument is a comma-separated list of <module name>=<log level>."
" <log level> overrides any value given by --v."); " <module name> is a glob pattern, matched against the filename base"
" (that is, name ignoring .cc/.h./-inl.h)."
" <log level> overrides any value given by --v.");
namespace google { namespace google {
@ -75,18 +78,19 @@ GLOG_EXPORT bool SafeFNMatch_(const char* pattern, size_t patt_len,
size_t p = 0; size_t p = 0;
size_t s = 0; size_t s = 0;
while (true) { while (true) {
if (p == patt_len && s == str_len) return true; if (p == patt_len && s == str_len) return true;
if (p == patt_len) return false; if (p == patt_len) return false;
if (s == str_len) return p+1 == patt_len && pattern[p] == '*'; if (s == str_len) return p + 1 == patt_len && pattern[p] == '*';
if (pattern[p] == str[s] || pattern[p] == '?') { if (pattern[p] == str[s] || pattern[p] == '?') {
p += 1; p += 1;
s += 1; s += 1;
continue; continue;
} }
if (pattern[p] == '*') { if (pattern[p] == '*') {
if (p+1 == patt_len) return true; if (p + 1 == patt_len) return true;
do { do {
if (SafeFNMatch_(pattern+(p+1), patt_len-(p+1), str+s, str_len-s)) { if (SafeFNMatch_(pattern + (p + 1), patt_len - (p + 1), str + s,
str_len - s)) {
return true; return true;
} }
s += 1; s += 1;
@ -177,10 +181,9 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {
found = true; found = true;
} }
info->vlog_level = log_level; info->vlog_level = log_level;
} else if (!found && } else if (!found && SafeFNMatch_(info->module_pattern.c_str(),
SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(),
info->module_pattern.size(), module_pattern, pattern_len)) {
module_pattern, pattern_len)) {
result = info->vlog_level; result = info->vlog_level;
found = true; found = true;
} }
@ -216,8 +219,8 @@ int SetVLOGLevel(const char* module_pattern, int log_level) {
// NOTE: Individual VLOG statements cache the integer log level pointers. // NOTE: Individual VLOG statements cache the integer log level pointers.
// NOTE: This function must not allocate memory or require any locks. // NOTE: This function must not allocate memory or require any locks.
bool InitVLOG3__(SiteFlag* site_flag, int32* level_default, bool InitVLOG3__(SiteFlag* site_flag, int32* level_default, const char* fname,
const char* fname, int32 verbose_level) { int32 verbose_level) {
MutexLock l(&vmodule_lock); MutexLock l(&vmodule_lock);
bool read_vmodule_flag = inited_vmodule; bool read_vmodule_flag = inited_vmodule;
if (!read_vmodule_flag) { if (!read_vmodule_flag) {
@ -240,13 +243,13 @@ bool InitVLOG3__(SiteFlag* site_flag, int32* level_default,
} }
#endif #endif
base = base ? (base+1) : fname; base = base ? (base + 1) : fname;
const char* base_end = strchr(base, '.'); const char* base_end = strchr(base, '.');
size_t base_length = size_t base_length =
base_end ? static_cast<size_t>(base_end - base) : strlen(base); base_end ? static_cast<size_t>(base_end - base) : strlen(base);
// Trim out trailing "-inl" if any // Trim out trailing "-inl" if any
if (base_length >= 4 && (memcmp(base+base_length-4, "-inl", 4) == 0)) { if (base_length >= 4 && (memcmp(base + base_length - 4, "-inl", 4) == 0)) {
base_length -= 4; base_length -= 4;
} }
@ -260,8 +263,8 @@ bool InitVLOG3__(SiteFlag* site_flag, int32* level_default,
if (SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(), if (SafeFNMatch_(info->module_pattern.c_str(), info->module_pattern.size(),
base, base_length)) { base, base_length)) {
site_flag_value = &info->vlog_level; site_flag_value = &info->vlog_level;
// value at info->vlog_level is now what controls // value at info->vlog_level is now what controls
// the VLOG at the caller site forever // the VLOG at the caller site forever
break; break;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@
*/ */
#ifndef _WIN32 #ifndef _WIN32
# error You should only be including windows/port.cc in a windows environment! # error You should only be including windows/port.cc in a windows environment!
#endif #endif
#include "port.h" #include "port.h"
@ -47,7 +47,7 @@ struct tm* localtime_r(const std::time_t* timep, std::tm* result) {
localtime_s(result, timep); localtime_s(result, timep);
return result; return result;
} }
#endif // not HAVE_LOCALTIME_R #endif // not HAVE_LOCALTIME_R
#ifndef HAVE_GMTIME_R #ifndef HAVE_GMTIME_R
struct tm* gmtime_r(const std::time_t* timep, std::tm* result) { struct tm* gmtime_r(const std::time_t* timep, std::tm* result) {
gmtime_s(result, timep); gmtime_s(result, timep);

View File

@ -45,26 +45,26 @@
#ifdef _WIN32 #ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN # ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN /* We always want minimal includes */ # define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
#endif # endif
#include <direct.h> /* for _getcwd() */ # include <direct.h> /* for _getcwd() */
#include <io.h> /* because we so often use open/close/etc */ # include <io.h> /* because we so often use open/close/etc */
#include <process.h> /* for _getpid() */ # include <process.h> /* for _getpid() */
#include <windows.h> # include <windows.h>
#include <winsock.h> /* for gethostname */ # include <winsock.h> /* for gethostname */
#include <cstdarg> /* template_dictionary.cc uses va_copy */ # include <cstdarg> /* template_dictionary.cc uses va_copy */
#include <cstring> /* for _strnicmp(), strerror_s() */ # include <cstring> /* for _strnicmp(), strerror_s() */
#include <ctime> /* for localtime_s() */ # include <ctime> /* for localtime_s() */
/* Note: the C++ #includes are all together at the bottom. This file is /* Note: the C++ #includes are all together at the bottom. This file is
* used by both C and C++ code, so we put all the C++ together. * used by both C and C++ code, so we put all the C++ together.
*/ */
#include "glog/logging.h" # include "glog/logging.h"
#ifdef _MSC_VER # ifdef _MSC_VER
/* 4244: otherwise we get problems when substracting two size_t's to an int /* 4244: otherwise we get problems when substracting two size_t's to an int
* 4251: it's complaining about a private struct I've chosen not to dllexport * 4251: it's complaining about a private struct I've chosen not to dllexport
@ -76,84 +76,85 @@
* 4267: also subtracting two size_t to int * 4267: also subtracting two size_t to int
* 4722: Destructor never returns due to abort() * 4722: Destructor never returns due to abort()
*/ */
#pragma warning(disable:4244 4251 4355 4715 4800 4996 4267 4312 4722) # pragma warning(disable : 4244 4251 4355 4715 4800 4996 4267 4312 4722)
/* file I/O */ /* file I/O */
#define PATH_MAX 1024 # define PATH_MAX 1024
#define popen _popen # define popen _popen
#define pclose _pclose # define pclose _pclose
#define R_OK 04 /* read-only (for access()) */ # define R_OK 04 /* read-only (for access()) */
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) # define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR)
#define O_WRONLY _O_WRONLY # define O_WRONLY _O_WRONLY
#define O_CREAT _O_CREAT # define O_CREAT _O_CREAT
#define O_EXCL _O_EXCL # define O_EXCL _O_EXCL
#ifndef __MINGW32__ # ifndef __MINGW32__
enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 }; enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
#endif # endif
#define S_IRUSR S_IREAD # define S_IRUSR S_IREAD
#define S_IWUSR S_IWRITE # define S_IWUSR S_IWRITE
/* Not quite as lightweight as a hard-link, but more than good enough for us. */ /* Not quite as lightweight as a hard-link, but more than good enough for us. */
#define link(oldpath, newpath) CopyFileA(oldpath, newpath, false) # define link(oldpath, newpath) CopyFileA(oldpath, newpath, false)
#define strcasecmp _stricmp # define strcasecmp _stricmp
#define strncasecmp _strnicmp # define strncasecmp _strnicmp
/* In windows-land, hash<> is called hash_compare<> (from xhash.h) */ /* In windows-land, hash<> is called hash_compare<> (from xhash.h) */
/* VC11 provides std::hash */ /* VC11 provides std::hash */
#if defined(_MSC_VER) && (_MSC_VER < 1700) # if defined(_MSC_VER) && (_MSC_VER < 1700)
#define hash hash_compare # define hash hash_compare
#endif # endif
/* Sleep is in ms, on windows */ /* Sleep is in ms, on windows */
#define sleep(secs) Sleep((secs) * 1000) # define sleep(secs) Sleep((secs)*1000)
/* Windows doesn't support specifying the number of buckets as a /* Windows doesn't support specifying the number of buckets as a
* hash_map constructor arg, so we leave this blank. * hash_map constructor arg, so we leave this blank.
*/ */
#define CTEMPLATE_SMALL_HASHTABLE # define CTEMPLATE_SMALL_HASHTABLE
#define DEFAULT_TEMPLATE_ROOTDIR ".." # define DEFAULT_TEMPLATE_ROOTDIR ".."
// ----------------------------------- SYSTEM/PROCESS // ----------------------------------- SYSTEM/PROCESS
typedef int pid_t; typedef int pid_t;
#define getpid _getpid # define getpid _getpid
#endif // _MSC_VER # endif // _MSC_VER
// ----------------------------------- THREADS // ----------------------------------- THREADS
#if defined(HAVE_PTHREAD) # if defined(HAVE_PTHREAD)
# include <pthread.h> # include <pthread.h>
#else // no PTHREAD # else // no PTHREAD
typedef DWORD pthread_t; typedef DWORD pthread_t;
typedef DWORD pthread_key_t; typedef DWORD pthread_key_t;
typedef LONG pthread_once_t; typedef LONG pthread_once_t;
enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
#define pthread_self GetCurrentThreadId # define pthread_self GetCurrentThreadId
#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2)) # define pthread_equal(pthread_t_1, pthread_t_2) \
#endif // HAVE_PTHREAD ((pthread_t_1) == (pthread_t_2))
# endif // HAVE_PTHREAD
#ifndef HAVE_LOCALTIME_R # ifndef HAVE_LOCALTIME_R
extern GLOG_EXPORT std::tm* localtime_r(const std::time_t* timep, extern GLOG_EXPORT std::tm* localtime_r(const std::time_t* timep,
std::tm* result); std::tm* result);
#endif // not HAVE_LOCALTIME_R # endif // not HAVE_LOCALTIME_R
#ifndef HAVE_GMTIME_R # ifndef HAVE_GMTIME_R
extern GLOG_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result); extern GLOG_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result);
#endif // not HAVE_GMTIME_R # endif // not HAVE_GMTIME_R
inline char* strerror_r(int errnum, char* buf, std::size_t buflen) { inline char* strerror_r(int errnum, char* buf, std::size_t buflen) {
strerror_s(buf, buflen, errnum); strerror_s(buf, buflen, errnum);
return buf; return buf;
} }
#ifndef __cplusplus # ifndef __cplusplus
/* I don't see how to get inlining for C code in MSVC. Ah well. */ /* I don't see how to get inlining for C code in MSVC. Ah well. */
#define inline # define inline
#endif # endif
#endif /* _WIN32 */ #endif /* _WIN32 */
#endif /* CTEMPLATE_WINDOWS_PORT_H_ */ #endif /* CTEMPLATE_WINDOWS_PORT_H_ */