From: Zachary Turner Date: Thu, 15 Dec 2016 19:02:43 +0000 (+0000) Subject: [StringRef] Add enable-if to StringLiteral. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18e2348b674a6b5477462c3d4437ebf50528f1a8;p=llvm [StringRef] Add enable-if to StringLiteral. to prevent StringLiteral from being created with a non-literal char array, clang has a macro enable_if() that can be used in such a way as to guarantee that the constructor is disabled unless the length fo the string can be computed at compile time. This only works on clang, but at least it should allow bots to catch abuse of StringLiteral. Differential Revision: https://reviews.llvm.org/D27780 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289853 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 56b75cb34cd..4a7a991b3ed 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -838,22 +838,21 @@ namespace llvm { /// A wrapper around a string literal that serves as a proxy for constructing /// global tables of StringRefs with the length computed at compile time. - /// Using this class with a non-literal char array is considered undefined - /// behavior. To prevent this, it is recommended that StringLiteral *only* - /// be used in a constexpr context, as such: + /// In order to avoid the invocation of a global constructor, StringLiteral + /// should *only* be used in a constexpr context, as such: /// /// constexpr StringLiteral S("test"); /// - /// Note: There is a subtle behavioral difference in the constructor of - /// StringRef and StringLiteral, as illustrated below: - /// - /// constexpr StringLiteral S("a\0b"); // S.size() == 3 - /// StringRef S("a\0b"); // S.size() == 1 - /// class StringLiteral : public StringRef { public: template - constexpr StringLiteral(const char (&Str)[N]) : StringRef(Str, N - 1) {} + constexpr StringLiteral(const char (&Str)[N]) +#if __has_attribute(enable_if) + __attribute((enable_if(__builtin_strlen(Str) == N - 1, + "invalid string literal"))) +#endif + : StringRef(Str, N - 1) { + } }; /// @name StringRef Comparison Operators @@ -865,9 +864,7 @@ namespace llvm { } LLVM_ATTRIBUTE_ALWAYS_INLINE - inline bool operator!=(StringRef LHS, StringRef RHS) { - return !(LHS == RHS); - } + inline bool operator!=(StringRef LHS, StringRef RHS) { return !(LHS == RHS); } inline bool operator<(StringRef LHS, StringRef RHS) { return LHS.compare(RHS) == -1;