summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAlp Toker <alp@nuanti.com>2014-01-27 04:07:17 +0000
committerAlp Toker <alp@nuanti.com>2014-01-27 04:07:17 +0000
commitbad91954cf7c2caae19728bed33729a390d88725 (patch)
tree25de33597852132787915526cf83f9a8524ae09b /include
parent1943ce9b6e16d58ec7341f4c1b4fdca2e4f327e9 (diff)
downloadllvm-bad91954cf7c2caae19728bed33729a390d88725.tar.gz
llvm-bad91954cf7c2caae19728bed33729a390d88725.tar.bz2
llvm-bad91954cf7c2caae19728bed33729a390d88725.tar.xz
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
Diffstat (limited to 'include')
-rw-r--r--include/llvm/ADT/StringRef.h46
-rw-r--r--include/llvm/Support/ErrorHandling.h14
2 files changed, 39 insertions, 21 deletions
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index ec0c2849f3..a35dfbfeba 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -10,6 +10,8 @@
#ifndef 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 <algorithm>
#include <cassert>
@@ -70,7 +72,7 @@ namespace llvm {
/// @{
/// 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.
/*implicit*/ StringRef(const char *Str)
@@ -80,11 +82,8 @@ namespace llvm {
}
/// Construct a string ref from a pointer and length.
- /*implicit*/ StringRef(const char *data, size_t length)
- : Data(data), Length(length) {
- assert((data || length == 0) &&
- "StringRef cannot be built from a NULL argument with non-null length");
- }
+ /*implicit*/ LLVM_CONSTEXPR StringRef(const char *data, size_t length)
+ : Data(data), Length((llvm_expect(data || length == 0), length)) {}
/// Construct a string ref from an std::string.
/*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
/// terminated).
- const char *data() const { return Data; }
+ LLVM_CONSTEXPR const char *data() const { return Data; }
/// 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_t size() const { return Length; }
+ LLVM_CONSTEXPR size_t size() const { return Length; }
/// front - Get the first character in the string.
- char front() const {
- assert(!empty());
- return Data[0];
- }
+ LLVM_CONSTEXPR char front() const { return llvm_expect(!empty()), Data[0]; }
/// back - Get the last character in the string.
- char back() const {
- assert(!empty());
- return Data[Length-1];
+ LLVM_CONSTEXPR char back() const {
+ return llvm_expect(!empty()), Data[Length - 1];
}
/// equals - Check for string equality, this is more efficient than
@@ -187,9 +182,8 @@ namespace llvm {
/// @name Operator Overloads
/// @{
- char operator[](size_t Index) const {
- assert(Index < Length && "Invalid index!");
- return Data[Index];
+ LLVM_CONSTEXPR char operator[](size_t Index) const {
+ return llvm_expect(Index < Length), 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.
hash_code hash_value(StringRef S);
diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h
index b948d97bff..d2f16821bf 100644
--- a/include/llvm/Support/ErrorHandling.h
+++ b/include/llvm/Support/ErrorHandling.h
@@ -15,11 +15,11 @@
#ifndef LLVM_SUPPORT_ERRORHANDLING_H
#define LLVM_SUPPORT_ERRORHANDLING_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include <string>
namespace llvm {
+ class StringRef;
class Twine;
/// An error handler callback.
@@ -78,7 +78,7 @@ namespace llvm {
bool gen_crash_diag = true);
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
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);
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason,
bool gen_crash_diag = true);
@@ -108,4 +108,14 @@ namespace llvm {
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
#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