[llvm] r289853 - [StringRef] Add enable-if to StringLiteral.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 15 11:02:44 PST 2016


Author: zturner
Date: Thu Dec 15 13:02:43 2016
New Revision: 289853

URL: http://llvm.org/viewvc/llvm-project?rev=289853&view=rev
Log:
[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

Modified:
    llvm/trunk/include/llvm/ADT/StringRef.h

Modified: llvm/trunk/include/llvm/ADT/StringRef.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/StringRef.h?rev=289853&r1=289852&r2=289853&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/StringRef.h (original)
+++ llvm/trunk/include/llvm/ADT/StringRef.h Thu Dec 15 13:02:43 2016
@@ -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 <size_t N>
-    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;




More information about the llvm-commits mailing list