From 837d6ed3ea52e063ff35f96f16558146941c0874 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 19 Dec 2013 20:32:44 +0000 Subject: [PATCH] Make sys::ThreadLocal<> zero-initialized on non-thread builds (PR18205) According to the docs, ThreadLocal<>::get() should return NULL if no object has been set. This patch makes that the case also for non-thread builds and adds a very basic unit test to check it. (This was causing PR18205 because PrettyStackTraceHead didn't get zero- initialized and we'd crash trying to read past the end of that list. We didn't notice this so much on Linux since we'd crash after printing all the entries, but on Mac we print into a SmallString, and would crash before printing that.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197718 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/ThreadLocal.cpp | 2 +- lib/Support/Unix/ThreadLocal.inc | 2 +- unittests/Support/CMakeLists.txt | 1 + unittests/Support/ThreadLocalTest.cpp | 38 +++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 unittests/Support/ThreadLocalTest.cpp diff --git a/lib/Support/ThreadLocal.cpp b/lib/Support/ThreadLocal.cpp index 0587aaec7e6..868b6ea566a 100644 --- a/lib/Support/ThreadLocal.cpp +++ b/lib/Support/ThreadLocal.cpp @@ -23,7 +23,7 @@ // Define all methods as no-ops if threading is explicitly disabled namespace llvm { using namespace sys; -ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::ThreadLocalImpl() : data() { } ThreadLocalImpl::~ThreadLocalImpl() { } void ThreadLocalImpl::setInstance(const void* d) { typedef int SIZE_TOO_BIG[sizeof(d) <= sizeof(data) ? 1 : -1]; diff --git a/lib/Support/Unix/ThreadLocal.inc b/lib/Support/Unix/ThreadLocal.inc index 2b4c9017cd9..f14d0fa3d52 100644 --- a/lib/Support/Unix/ThreadLocal.inc +++ b/lib/Support/Unix/ThreadLocal.inc @@ -18,7 +18,7 @@ namespace llvm { using namespace sys; -ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::ThreadLocalImpl() : data() { } ThreadLocalImpl::~ThreadLocalImpl() { } void ThreadLocalImpl::setInstance(const void* d) { data = const_cast(d);} const void* ThreadLocalImpl::getInstance() { return data; } diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index c2753629cb9..0abc2ffe1d9 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -30,6 +30,7 @@ add_llvm_unittest(SupportTests RegexTest.cpp SourceMgrTest.cpp SwapByteOrderTest.cpp + ThreadLocalTest.cpp TimeValueTest.cpp UnicodeTest.cpp ValueHandleTest.cpp diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp new file mode 100644 index 00000000000..dd4d706f5cf --- /dev/null +++ b/unittests/Support/ThreadLocalTest.cpp @@ -0,0 +1,38 @@ +//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ThreadLocal.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace sys; + +namespace { + +class ThreadLocalTest : public ::testing::Test { +}; + +struct S { + int i; +}; + +TEST_F(ThreadLocalTest, Basics) { + ThreadLocal x; + + EXPECT_EQ(0, x.get()); + + S s; + x.set(&s); + EXPECT_EQ(&s, x.get()); + + x.erase(); + EXPECT_EQ(0, x.get()); +} + +}