mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-27 00:21:03 +00:00
StringRef: Extend constexpr capabilities and introduce ConstStringRef
(1) Add llvm_expect(), an asserting macro that can be evaluated as a constexpr expression as well as a runtime assert or compiler hint in release builds. This technique can be used to construct functions that are both unevaluated and compiled depending on usage. (2) Update StringRef using llvm_expect() to preserve runtime assertions while extending the same checks to static asserts in C++11 builds that support the feature. (3) Introduce ConstStringRef, a strong subclass of StringRef that references compile-time constant strings. It's convertible to, but not from, ordinary StringRef and thus can be used to add compile-time safety to various interfaces in LLVM and clang that only accept fixed inputs such as diagnostic format strings that tend to get misused. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200187 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -10,6 +10,8 @@
|
|||||||
#ifndef LLVM_ADT_STRINGREF_H
|
#ifndef LLVM_ADT_STRINGREF_H
|
||||||
#define LLVM_ADT_STRINGREF_H
|
#define LLVM_ADT_STRINGREF_H
|
||||||
|
|
||||||
|
#include "llvm/Support/Compiler.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/type_traits.h"
|
#include "llvm/Support/type_traits.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -70,7 +72,7 @@ namespace llvm {
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// Construct an empty string ref.
|
/// Construct an empty string ref.
|
||||||
/*implicit*/ StringRef() : Data(0), Length(0) {}
|
/*implicit*/ LLVM_CONSTEXPR StringRef() : Data(0), Length(0) {}
|
||||||
|
|
||||||
/// Construct a string ref from a cstring.
|
/// Construct a string ref from a cstring.
|
||||||
/*implicit*/ StringRef(const char *Str)
|
/*implicit*/ StringRef(const char *Str)
|
||||||
@@ -80,11 +82,8 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a string ref from a pointer and length.
|
/// Construct a string ref from a pointer and length.
|
||||||
/*implicit*/ StringRef(const char *data, size_t length)
|
/*implicit*/ LLVM_CONSTEXPR StringRef(const char *data, size_t length)
|
||||||
: Data(data), Length(length) {
|
: Data(data), Length((llvm_expect(data || length == 0), length)) {}
|
||||||
assert((data || length == 0) &&
|
|
||||||
"StringRef cannot be built from a NULL argument with non-null length");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a string ref from an std::string.
|
/// Construct a string ref from an std::string.
|
||||||
/*implicit*/ StringRef(const std::string &Str)
|
/*implicit*/ StringRef(const std::string &Str)
|
||||||
@@ -104,24 +103,20 @@ namespace llvm {
|
|||||||
|
|
||||||
/// data - Get a pointer to the start of the string (which may not be null
|
/// data - Get a pointer to the start of the string (which may not be null
|
||||||
/// terminated).
|
/// terminated).
|
||||||
const char *data() const { return Data; }
|
LLVM_CONSTEXPR const char *data() const { return Data; }
|
||||||
|
|
||||||
/// empty - Check if the string is empty.
|
/// empty - Check if the string is empty.
|
||||||
bool empty() const { return Length == 0; }
|
LLVM_CONSTEXPR bool empty() const { return Length == 0; }
|
||||||
|
|
||||||
/// size - Get the string size.
|
/// size - Get the string size.
|
||||||
size_t size() const { return Length; }
|
LLVM_CONSTEXPR size_t size() const { return Length; }
|
||||||
|
|
||||||
/// front - Get the first character in the string.
|
/// front - Get the first character in the string.
|
||||||
char front() const {
|
LLVM_CONSTEXPR char front() const { return llvm_expect(!empty()), Data[0]; }
|
||||||
assert(!empty());
|
|
||||||
return Data[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// back - Get the last character in the string.
|
/// back - Get the last character in the string.
|
||||||
char back() const {
|
LLVM_CONSTEXPR char back() const {
|
||||||
assert(!empty());
|
return llvm_expect(!empty()), Data[Length - 1];
|
||||||
return Data[Length-1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// equals - Check for string equality, this is more efficient than
|
/// equals - Check for string equality, this is more efficient than
|
||||||
@@ -187,9 +182,8 @@ namespace llvm {
|
|||||||
/// @name Operator Overloads
|
/// @name Operator Overloads
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
char operator[](size_t Index) const {
|
LLVM_CONSTEXPR char operator[](size_t Index) const {
|
||||||
assert(Index < Length && "Invalid index!");
|
return llvm_expect(Index < Length), Data[Index];
|
||||||
return Data[Index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -547,6 +541,20 @@ namespace llvm {
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/// ConstStringRef - A \c StringRef carrying the additional stipulation that
|
||||||
|
/// the referenced string is a compile-time constant.
|
||||||
|
///
|
||||||
|
/// Use this to specify function parameters that require fixed inputs such
|
||||||
|
/// as debug and diagnostic messages or format strings.
|
||||||
|
class ConstStringRef : public StringRef {
|
||||||
|
public:
|
||||||
|
/*implicit*/ LLVM_CONSTEXPR ConstStringRef() : StringRef() {}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
/*implicit*/ LLVM_CONSTEXPR ConstStringRef(const char (&data)[N])
|
||||||
|
: StringRef(data, (llvm_expect(N > 0 && data[N - 1] == '\0'), N - 1)) {}
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief Compute a hash_code for a StringRef.
|
/// \brief Compute a hash_code for a StringRef.
|
||||||
hash_code hash_value(StringRef S);
|
hash_code hash_value(StringRef S);
|
||||||
|
|
||||||
|
@@ -15,11 +15,11 @@
|
|||||||
#ifndef LLVM_SUPPORT_ERRORHANDLING_H
|
#ifndef LLVM_SUPPORT_ERRORHANDLING_H
|
||||||
#define LLVM_SUPPORT_ERRORHANDLING_H
|
#define LLVM_SUPPORT_ERRORHANDLING_H
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class StringRef;
|
||||||
class Twine;
|
class Twine;
|
||||||
|
|
||||||
/// An error handler callback.
|
/// An error handler callback.
|
||||||
@@ -78,7 +78,7 @@ namespace llvm {
|
|||||||
bool gen_crash_diag = true);
|
bool gen_crash_diag = true);
|
||||||
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
|
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
|
||||||
bool gen_crash_diag = true);
|
bool gen_crash_diag = true);
|
||||||
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason,
|
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const StringRef &reason,
|
||||||
bool gen_crash_diag = true);
|
bool gen_crash_diag = true);
|
||||||
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason,
|
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason,
|
||||||
bool gen_crash_diag = true);
|
bool gen_crash_diag = true);
|
||||||
@@ -108,4 +108,14 @@ namespace llvm {
|
|||||||
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
|
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// An assert macro that's usable in constexprs and that becomes an optimizer
|
||||||
|
/// hint in NDEBUG builds.
|
||||||
|
///
|
||||||
|
/// Unlike \c assert() the \param test expression may be evaluated in optimized
|
||||||
|
/// builds and so should be simple, accurate and never have side effects.
|
||||||
|
#define llvm_expect(test) (void)(!!(test) ? 0 : (llvm_unreachable(#test), 0))
|
||||||
|
|
||||||
|
// TODO: Update other headers to explicitly include StringRef.h and drop this.
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -58,7 +58,7 @@ void llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) {
|
|||||||
report_fatal_error(Twine(Reason), GenCrashDiag);
|
report_fatal_error(Twine(Reason), GenCrashDiag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
|
void llvm::report_fatal_error(const StringRef &Reason, bool GenCrashDiag) {
|
||||||
report_fatal_error(Twine(Reason), GenCrashDiag);
|
report_fatal_error(Twine(Reason), GenCrashDiag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -531,4 +531,22 @@ TEST(StringRefTest, joinStrings) {
|
|||||||
EXPECT_TRUE(v2_join3);
|
EXPECT_TRUE(v2_join3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fn_stringref(StringRef str) {
|
||||||
|
EXPECT_TRUE(str == "hello");
|
||||||
|
}
|
||||||
|
static void fn_conststringref(ConstStringRef str) {
|
||||||
|
fn_stringref(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringRefTest, constStringRef) {
|
||||||
|
LLVM_CONSTEXPR ConstStringRef csr("hello");
|
||||||
|
#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
|
LLVM_STATIC_ASSERT(csr[0] != csr[1], "");
|
||||||
|
LLVM_STATIC_ASSERT(csr[2] == csr[3], "");
|
||||||
|
LLVM_STATIC_ASSERT(csr.size() == 5, "");
|
||||||
|
#endif
|
||||||
|
llvm_expect(csr[2] == csr[3]);
|
||||||
|
fn_conststringref(csr);
|
||||||
|
}
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
Reference in New Issue
Block a user