OSDN Git Service

[StringRef] Add enable-if to StringLiteral.
authorZachary Turner <zturner@google.com>
Thu, 15 Dec 2016 19:02:43 +0000 (19:02 +0000)
committerZachary Turner <zturner@google.com>
Thu, 15 Dec 2016 19:02:43 +0000 (19:02 +0000)
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

include/llvm/ADT/StringRef.h

index 56b75cb..4a7a991 100644 (file)
@@ -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;