[libc++] Implement P0980R1 (constexpr std::string)

Reviewed By: #libc, ldionne

Spies: daltenty, sdasgup3, ldionne, arichardson, MTC, ChuanqiXu, mehdi_amini, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, stephenneuendorffer, Joonsoo, grosul1, Kayjukh, jurahul, msifontes, tatianashp, rdzhabarov, teijeong, cota, dcaballe, Chia-hungDuan, wrengr, wenzhicui, arphaman, Mordante, miscco, Quuxplusone, smeenai, libcxx-commits

Differential Revision: https://reviews.llvm.org/D110598

NOKEYCHECK=True
GitOrigin-RevId: 425620ccdd47e56b59512913cdc71e116f951e4e
diff --git a/include/string b/include/string
index bd1c430..6666d50 100644
--- a/include/string
+++ b/include/string
@@ -95,248 +95,246 @@
     static const size_type npos = -1;
 
     basic_string()
-        noexcept(is_nothrow_default_constructible<allocator_type>::value);
-    explicit basic_string(const allocator_type& a);
-    basic_string(const basic_string& str);
+        noexcept(is_nothrow_default_constructible<allocator_type>::value);                      // constexpr since C++20
+    explicit basic_string(const allocator_type& a);                                             // constexpr since C++20
+    basic_string(const basic_string& str);                                                      // constexpr since C++20
     basic_string(basic_string&& str)
-        noexcept(is_nothrow_move_constructible<allocator_type>::value);
+        noexcept(is_nothrow_move_constructible<allocator_type>::value);                         // constexpr since C++20
     basic_string(const basic_string& str, size_type pos,
-                 const allocator_type& a = allocator_type());
+                 const allocator_type& a = allocator_type());                                   // constexpr since C++20
     basic_string(const basic_string& str, size_type pos, size_type n,
-                 const Allocator& a = Allocator());
+                 const Allocator& a = Allocator());                                             // constexpr since C++20
     template<class T>
-        basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17
+        basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20
     template <class T>
-        explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17
-    basic_string(const value_type* s, const allocator_type& a = allocator_type());
-    basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type());
+        explicit basic_string(const T& t, const Allocator& a = Allocator());                    // C++17, constexpr since C++20
+    basic_string(const value_type* s, const allocator_type& a = allocator_type());              // constexpr since C++20
+    basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20
     basic_string(nullptr_t) = delete; // C++2b
-    basic_string(size_type n, value_type c, const allocator_type& a = allocator_type());
+    basic_string(size_type n, value_type c, const allocator_type& a = allocator_type());        // constexpr since C++20
     template<class InputIterator>
         basic_string(InputIterator begin, InputIterator end,
-                     const allocator_type& a = allocator_type());
-    basic_string(initializer_list<value_type>, const Allocator& = Allocator());
-    basic_string(const basic_string&, const Allocator&);
-    basic_string(basic_string&&, const Allocator&);
+                     const allocator_type& a = allocator_type());                               // constexpr since C++20
+    basic_string(initializer_list<value_type>, const Allocator& = Allocator());                 // constexpr since C++20
+    basic_string(const basic_string&, const Allocator&);                                        // constexpr since C++20
+    basic_string(basic_string&&, const Allocator&);                                             // constexpr since C++20
 
-    ~basic_string();
+    ~basic_string();                                                                            // constexpr since C++20
 
-    operator basic_string_view<charT, traits>() const noexcept;
+    operator basic_string_view<charT, traits>() const noexcept;                                 // constexpr since C++20
 
-    basic_string& operator=(const basic_string& str);
+    basic_string& operator=(const basic_string& str);                                           // constexpr since C++20
     template <class T>
-        basic_string& operator=(const T& t); // C++17
+        basic_string& operator=(const T& t);                                                    // C++17, constexpr since C++20
     basic_string& operator=(basic_string&& str)
         noexcept(
              allocator_type::propagate_on_container_move_assignment::value ||
-             allocator_type::is_always_equal::value ); // C++17
-    basic_string& operator=(const value_type* s);
+             allocator_type::is_always_equal::value );                                          // C++17, constexpr since C++20
+    basic_string& operator=(const value_type* s);                                               // constexpr since C++20
     basic_string& operator=(nullptr_t) = delete; // C++2b
-    basic_string& operator=(value_type c);
-    basic_string& operator=(initializer_list<value_type>);
+    basic_string& operator=(value_type c);                                                      // constexpr since C++20
+    basic_string& operator=(initializer_list<value_type>);                                      // constexpr since C++20
 
-    iterator       begin() noexcept;
-    const_iterator begin() const noexcept;
-    iterator       end() noexcept;
-    const_iterator end() const noexcept;
+    iterator       begin() noexcept;                                                            // constexpr since C++20
+    const_iterator begin() const noexcept;                                                      // constexpr since C++20
+    iterator       end() noexcept;                                                              // constexpr since C++20
+    const_iterator end() const noexcept;                                                        // constexpr since C++20
 
-    reverse_iterator       rbegin() noexcept;
-    const_reverse_iterator rbegin() const noexcept;
-    reverse_iterator       rend() noexcept;
-    const_reverse_iterator rend() const noexcept;
+    reverse_iterator       rbegin() noexcept;                                                   // constexpr since C++20
+    const_reverse_iterator rbegin() const noexcept;                                             // constexpr since C++20
+    reverse_iterator       rend() noexcept;                                                     // constexpr since C++20
+    const_reverse_iterator rend() const noexcept;                                               // constexpr since C++20
 
-    const_iterator         cbegin() const noexcept;
-    const_iterator         cend() const noexcept;
-    const_reverse_iterator crbegin() const noexcept;
-    const_reverse_iterator crend() const noexcept;
+    const_iterator         cbegin() const noexcept;                                             // constexpr since C++20
+    const_iterator         cend() const noexcept;                                               // constexpr since C++20
+    const_reverse_iterator crbegin() const noexcept;                                            // constexpr since C++20
+    const_reverse_iterator crend() const noexcept;                                              // constexpr since C++20
 
-    size_type size() const noexcept;
-    size_type length() const noexcept;
-    size_type max_size() const noexcept;
-    size_type capacity() const noexcept;
+    size_type size() const noexcept;                                                            // constexpr since C++20
+    size_type length() const noexcept;                                                          // constexpr since C++20
+    size_type max_size() const noexcept;                                                        // constexpr since C++20
+    size_type capacity() const noexcept;                                                        // constexpr since C++20
 
-    void resize(size_type n, value_type c);
-    void resize(size_type n);
+    void resize(size_type n, value_type c);                                                     // constexpr since C++20
+    void resize(size_type n);                                                                   // constexpr since C++20
 
     template<class Operation>
     constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23
 
-    void reserve(size_type res_arg);
+    void reserve(size_type res_arg);                                                            // constexpr since C++20
     void reserve(); // deprecated in C++20
-    void shrink_to_fit();
-    void clear() noexcept;
-    bool empty() const noexcept;
+    void shrink_to_fit();                                                                       // constexpr since C++20
+    void clear() noexcept;                                                                      // constexpr since C++20
+    bool empty() const noexcept;                                                                // constexpr since C++20
 
-    const_reference operator[](size_type pos) const;
-    reference       operator[](size_type pos);
+    const_reference operator[](size_type pos) const;                                            // constexpr since C++20
+    reference       operator[](size_type pos);                                                  // constexpr since C++20
 
-    const_reference at(size_type n) const;
-    reference       at(size_type n);
+    const_reference at(size_type n) const;                                                      // constexpr since C++20
+    reference       at(size_type n);                                                            // constexpr since C++20
 
-    basic_string& operator+=(const basic_string& str);
+    basic_string& operator+=(const basic_string& str);                                          // constexpr since C++20
     template <class T>
-        basic_string& operator+=(const T& t);              // C++17
-    basic_string& operator+=(const value_type* s);
-    basic_string& operator+=(value_type c);
-    basic_string& operator+=(initializer_list<value_type>);
+        basic_string& operator+=(const T& t);                                                   // C++17, constexpr since C++20
+    basic_string& operator+=(const value_type* s);                                              // constexpr since C++20
+    basic_string& operator+=(value_type c);                                                     // constexpr since C++20
+    basic_string& operator+=(initializer_list<value_type>);                                     // constexpr since C++20
 
-    basic_string& append(const basic_string& str);
+    basic_string& append(const basic_string& str);                                              // constexpr since C++20
     template <class T>
-        basic_string& append(const T& t);                 // C++17
-    basic_string& append(const basic_string& str, size_type pos, size_type n=npos); //C++14
+        basic_string& append(const T& t);                                                       // C++17, constexpr since C++20
+    basic_string& append(const basic_string& str, size_type pos, size_type n=npos);             // C++14, constexpr since C++20
     template <class T>
-        basic_string& append(const T& t, size_type pos, size_type n=npos); // C++17
-    basic_string& append(const value_type* s, size_type n);
-    basic_string& append(const value_type* s);
-    basic_string& append(size_type n, value_type c);
+        basic_string& append(const T& t, size_type pos, size_type n=npos);                      // C++17, constexpr since C++20
+    basic_string& append(const value_type* s, size_type n);                                     // constexpr since C++20
+    basic_string& append(const value_type* s);                                                  // constexpr since C++20
+    basic_string& append(size_type n, value_type c);                                            // constexpr since C++20
     template<class InputIterator>
-        basic_string& append(InputIterator first, InputIterator last);
-    basic_string& append(initializer_list<value_type>);
+        basic_string& append(InputIterator first, InputIterator last);                          // constexpr since C++20
+    basic_string& append(initializer_list<value_type>);                                         // constexpr since C++20
 
-    void push_back(value_type c);
-    void pop_back();
-    reference       front();
-    const_reference front() const;
-    reference       back();
-    const_reference back() const;
+    void push_back(value_type c);                                                               // constexpr since C++20
+    void pop_back();                                                                            // constexpr since C++20
+    reference       front();                                                                    // constexpr since C++20
+    const_reference front() const;                                                              // constexpr since C++20
+    reference       back();                                                                     // constexpr since C++20
+    const_reference back() const;                                                               // constexpr since C++20
 
-    basic_string& assign(const basic_string& str);
+    basic_string& assign(const basic_string& str);                                              // constexpr since C++20
     template <class T>
-        basic_string& assign(const T& t);  // C++17
-    basic_string& assign(basic_string&& str);
-    basic_string& assign(const basic_string& str, size_type pos, size_type n=npos); // C++14
+        basic_string& assign(const T& t);                                                       // C++17, constexpr since C++20
+    basic_string& assign(basic_string&& str);                                                   // constexpr since C++20
+    basic_string& assign(const basic_string& str, size_type pos, size_type n=npos);             // C++14, constexpr since C++20
     template <class T>
-        basic_string& assign(const T& t, size_type pos, size_type n=npos); // C++17
-    basic_string& assign(const value_type* s, size_type n);
-    basic_string& assign(const value_type* s);
-    basic_string& assign(size_type n, value_type c);
+        basic_string& assign(const T& t, size_type pos, size_type n=npos);                      // C++17, constexpr since C++20
+    basic_string& assign(const value_type* s, size_type n);                                     // constexpr since C++20
+    basic_string& assign(const value_type* s);                                                  // constexpr since C++20
+    basic_string& assign(size_type n, value_type c);                                            // constexpr since C++20
     template<class InputIterator>
-        basic_string& assign(InputIterator first, InputIterator last);
-    basic_string& assign(initializer_list<value_type>);
+        basic_string& assign(InputIterator first, InputIterator last);                          // constexpr since C++20
+    basic_string& assign(initializer_list<value_type>);                                         // constexpr since C++20
 
-    basic_string& insert(size_type pos1, const basic_string& str);
+    basic_string& insert(size_type pos1, const basic_string& str);                              // constexpr since C++20
     template <class T>
-        basic_string& insert(size_type pos1, const T& t);
+        basic_string& insert(size_type pos1, const T& t);                                       // constexpr since C++20
     basic_string& insert(size_type pos1, const basic_string& str,
-                         size_type pos2, size_type n);
+                         size_type pos2, size_type n);                                          // constexpr since C++20
     template <class T>
-        basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n); // C++17
-    basic_string& insert(size_type pos, const value_type* s, size_type n=npos); //C++14
-    basic_string& insert(size_type pos, const value_type* s);
-    basic_string& insert(size_type pos, size_type n, value_type c);
-    iterator      insert(const_iterator p, value_type c);
-    iterator      insert(const_iterator p, size_type n, value_type c);
+        basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n);          // C++17, constexpr since C++20
+    basic_string& insert(size_type pos, const value_type* s, size_type n=npos);                 // C++14, constexpr since C++20
+    basic_string& insert(size_type pos, const value_type* s);                                   // constexpr since C++20
+    basic_string& insert(size_type pos, size_type n, value_type c);                             // constexpr since C++20
+    iterator      insert(const_iterator p, value_type c);                                       // constexpr since C++20
+    iterator      insert(const_iterator p, size_type n, value_type c);                          // constexpr since C++20
     template<class InputIterator>
-        iterator insert(const_iterator p, InputIterator first, InputIterator last);
-    iterator      insert(const_iterator p, initializer_list<value_type>);
+        iterator insert(const_iterator p, InputIterator first, InputIterator last);             // constexpr since C++20
+    iterator      insert(const_iterator p, initializer_list<value_type>);                       // constexpr since C++20
 
-    basic_string& erase(size_type pos = 0, size_type n = npos);
-    iterator      erase(const_iterator position);
-    iterator      erase(const_iterator first, const_iterator last);
+    basic_string& erase(size_type pos = 0, size_type n = npos);                                 // constexpr since C++20
+    iterator      erase(const_iterator position);                                               // constexpr since C++20
+    iterator      erase(const_iterator first, const_iterator last);                             // constexpr since C++20
 
-    basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
+    basic_string& replace(size_type pos1, size_type n1, const basic_string& str);               // constexpr since C++20
     template <class T>
-    basic_string& replace(size_type pos1, size_type n1, const T& t);  // C++17
+    basic_string& replace(size_type pos1, size_type n1, const T& t);                            // C++17, constexpr since C++20
     basic_string& replace(size_type pos1, size_type n1, const basic_string& str,
-                          size_type pos2, size_type n2=npos); // C++14
+                          size_type pos2, size_type n2=npos);                                   // C++14, constexpr since C++20
     template <class T>
         basic_string& replace(size_type pos1, size_type n1, const T& t,
-                              size_type pos2, size_type n); // C++17
-    basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2);
-    basic_string& replace(size_type pos, size_type n1, const value_type* s);
-    basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c);
-    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);
+                              size_type pos2, size_type n);                                     // C++17, constexpr since C++20
+    basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2);      // constexpr since C++20
+    basic_string& replace(size_type pos, size_type n1, const value_type* s);                    // constexpr since C++20
+    basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c);             // constexpr since C++20
+    basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);       // constexpr since C++20
     template <class T>
-        basic_string& replace(const_iterator i1, const_iterator i2, const T& t);  // C++17
-    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n);
-    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s);
-    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c);
+        basic_string& replace(const_iterator i1, const_iterator i2, const T& t);                // C++17, constexpr since C++20
+    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); // constexpr since C++20
+    basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s);           // constexpr since C++20
+    basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c);     // constexpr since C++20
     template<class InputIterator>
-        basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2);
-    basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>);
+        basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20
+    basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>);  // constexpr since C++20
 
-    size_type copy(value_type* s, size_type n, size_type pos = 0) const;
-    basic_string substr(size_type pos = 0, size_type n = npos) const;
+    size_type copy(value_type* s, size_type n, size_type pos = 0) const;                        // constexpr since C++20
+    basic_string substr(size_type pos = 0, size_type n = npos) const;                           // constexpr since C++20
 
     void swap(basic_string& str)
         noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
-                 allocator_traits<allocator_type>::is_always_equal::value);  // C++17
+                 allocator_traits<allocator_type>::is_always_equal::value);                     // C++17, constexpr since C++20
 
-    const value_type* c_str() const noexcept;
-    const value_type* data() const noexcept;
-          value_type* data()       noexcept;   // C++17
+    const value_type* c_str() const noexcept;                                                   // constexpr since C++20
+    const value_type* data() const noexcept;                                                    // constexpr since C++20
+          value_type* data()       noexcept;                                                    // C++17, constexpr since C++20
 
-    allocator_type get_allocator() const noexcept;
+    allocator_type get_allocator() const noexcept;                                              // constexpr since C++20
 
-    size_type find(const basic_string& str, size_type pos = 0) const noexcept;
+    size_type find(const basic_string& str, size_type pos = 0) const noexcept;                  // constexpr since C++20
     template <class T>
-        size_type find(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension
-    size_type find(const value_type* s, size_type pos, size_type n) const noexcept;
-    size_type find(const value_type* s, size_type pos = 0) const noexcept;
-    size_type find(value_type c, size_type pos = 0) const noexcept;
+        size_type find(const T& t, size_type pos = 0) const noexcept;                           // C++17, noexcept as an extension, constexpr since C++20
+    size_type find(const value_type* s, size_type pos, size_type n) const noexcept;             // constexpr since C++20
+    size_type find(const value_type* s, size_type pos = 0) const noexcept;                      // constexpr since C++20
+    size_type find(value_type c, size_type pos = 0) const noexcept;                             // constexpr since C++20
 
-    size_type rfind(const basic_string& str, size_type pos = npos) const noexcept;
+    size_type rfind(const basic_string& str, size_type pos = npos) const noexcept;              // constexpr since C++20
     template <class T>
-        size_type rfind(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension
-    size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept;
-    size_type rfind(const value_type* s, size_type pos = npos) const noexcept;
-    size_type rfind(value_type c, size_type pos = npos) const noexcept;
+        size_type rfind(const T& t, size_type pos = npos) const noexcept;                       // C++17, noexcept as an extension, constexpr since C++20
+    size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept;            // constexpr since C++20
+    size_type rfind(const value_type* s, size_type pos = npos) const noexcept;                  // constexpr since C++20
+    size_type rfind(value_type c, size_type pos = npos) const noexcept;                         // constexpr since C++20
 
-    size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;
+    size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept;         // constexpr since C++20
     template <class T>
-        size_type find_first_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension
-    size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept;
-    size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept;
-    size_type find_first_of(value_type c, size_type pos = 0) const noexcept;
+        size_type find_first_of(const T& t, size_type pos = 0) const noexcept;                  // C++17, noexcept as an extension, constexpr since C++20
+    size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept;    // constexpr since C++20
+    size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept;             // constexpr since C++20
+    size_type find_first_of(value_type c, size_type pos = 0) const noexcept;                    // constexpr since C++20
 
-    size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept;
+    size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept;       // constexpr since C++20
     template <class T>
-        size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept; // C++17, noexcept as an extension
-    size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept;
-    size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept;
-    size_type find_last_of(value_type c, size_type pos = npos) const noexcept;
+        size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept;       // C++17, noexcept as an extension, constexpr since C++20
+    size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept;     // constexpr since C++20
+    size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept;           // constexpr since C++20
+    size_type find_last_of(value_type c, size_type pos = npos) const noexcept;                  // constexpr since C++20
 
-    size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;
+    size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept;     // constexpr since C++20
     template <class T>
-        size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension
-    size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept;
-    size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept;
-    size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept;
+        size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept;              // C++17, noexcept as an extension, constexpr since C++20
+    size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20
+    size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept;         // constexpr since C++20
+    size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept;                // constexpr since C++20
 
-    size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept;
+    size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept;   // constexpr since C++20
     template <class T>
-        size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension
-    size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept;
-    size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept;
-    size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept;
+        size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept;            // C++17, noexcept as an extension, constexpr since C++20
+    size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20
+    size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept;       // constexpr since C++20
+    size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept;              // constexpr since C++20
 
-    int compare(const basic_string& str) const noexcept;
+    int compare(const basic_string& str) const noexcept;                                        // constexpr since C++20
     template <class T>
-        int compare(const T& t) const noexcept;  // C++17, noexcept as an extension
-    int compare(size_type pos1, size_type n1, const basic_string& str) const;
+        int compare(const T& t) const noexcept;                                                 // C++17, noexcept as an extension, constexpr since C++20
+    int compare(size_type pos1, size_type n1, const basic_string& str) const;                   // constexpr since C++20
     template <class T>
-        int compare(size_type pos1, size_type n1, const T& t) const;  // C++17
+        int compare(size_type pos1, size_type n1, const T& t) const;                            // C++17, constexpr since C++20
     int compare(size_type pos1, size_type n1, const basic_string& str,
-                size_type pos2, size_type n2=npos) const; // C++14
+                size_type pos2, size_type n2=npos) const;                                       // C++14, constexpr since C++20
     template <class T>
         int compare(size_type pos1, size_type n1, const T& t,
-                    size_type pos2, size_type n2=npos) const; // C++17
-    int compare(const value_type* s) const noexcept;
-    int compare(size_type pos1, size_type n1, const value_type* s) const;
-    int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const;
+                    size_type pos2, size_type n2=npos) const;                                   // C++17, constexpr since C++20
+    int compare(const value_type* s) const noexcept;                                            // constexpr since C++20
+    int compare(size_type pos1, size_type n1, const value_type* s) const;                       // constexpr since C++20
+    int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const;         // constexpr since C++20
 
-    bool starts_with(basic_string_view<charT, traits> sv) const noexcept; // C++20
-    bool starts_with(charT c) const noexcept;                             // C++20
-    bool starts_with(const charT* s) const;                               // C++20
-    bool ends_with(basic_string_view<charT, traits> sv) const noexcept;   // C++20
-    bool ends_with(charT c) const noexcept;                               // C++20
-    bool ends_with(const charT* s) const;                                 // C++20
+    constexpr bool starts_with(basic_string_view<charT, traits> sv) const noexcept;             // C++20
+    constexpr bool starts_with(charT c) const noexcept;                                         // C++20
+    constexpr bool starts_with(const charT* s) const;                                           // C++20
+    constexpr bool ends_with(basic_string_view<charT, traits> sv) const noexcept;               // C++20
+    constexpr bool ends_with(charT c) const noexcept;                                           // C++20
+    constexpr bool ends_with(const charT* s) const;                                             // C++20
 
-    constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept; // C++2b
-    constexpr bool contains(charT c) const noexcept;                             // C++2b
-    constexpr bool contains(const charT* s) const;                               // C++2b
-
-    bool __invariants() const;
+    constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept;                // C++2b
+    constexpr bool contains(charT c) const noexcept;                                            // C++2b
+    constexpr bool contains(const charT* s) const;                                              // C++2b
 };
 
 template<class InputIterator,
@@ -349,88 +347,88 @@
 template<class charT, class traits, class Allocator>
 basic_string<charT, traits, Allocator>
 operator+(const basic_string<charT, traits, Allocator>& lhs,
-          const basic_string<charT, traits, Allocator>& rhs);
+          const basic_string<charT, traits, Allocator>& rhs);                                   // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 basic_string<charT, traits, Allocator>
-operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs);
+operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs);                   // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 basic_string<charT, traits, Allocator>
-operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs);
+operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs);                          // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 basic_string<charT, traits, Allocator>
-operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
+operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);                 // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 basic_string<charT, traits, Allocator>
-operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);
+operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);                        // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator==(const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;
+bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept;
+bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept;    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator!=(const basic_string<charT,traits,Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;
+bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;
+bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator< (const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;
+bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;
+bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator> (const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;
+bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;
+bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator<=(const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;
+bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;
+bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 bool operator>=(const basic_string<charT, traits, Allocator>& lhs,
-                const basic_string<charT, traits, Allocator>& rhs) noexcept;
+                const basic_string<charT, traits, Allocator>& rhs) noexcept;                    // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;
+bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
-bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;
+bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept;  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 void swap(basic_string<charT, traits, Allocator>& lhs,
           basic_string<charT, traits, Allocator>& rhs)
-            noexcept(noexcept(lhs.swap(rhs)));
+            noexcept(noexcept(lhs.swap(rhs)));                                                  // constexpr since C++20
 
 template<class charT, class traits, class Allocator>
 basic_istream<charT, traits>&
@@ -508,11 +506,11 @@
 template <> struct hash<u32string>;
 template <> struct hash<wstring>;
 
-basic_string<char>     operator "" s( const char *str,     size_t len ); // C++14
-basic_string<wchar_t>  operator "" s( const wchar_t *str,  size_t len ); // C++14
-basic_string<char8_t>  operator "" s( const char8_t *str,  size_t len ); // C++20
-basic_string<char16_t> operator "" s( const char16_t *str, size_t len ); // C++14
-basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); // C++14
+basic_string<char>     operator "" s( const char *str,     size_t len );           // C++14, constexpr since C++20
+basic_string<wchar_t>  operator "" s( const wchar_t *str,  size_t len );           // C++14, constexpr since C++20
+constexpr basic_string<char8_t>  operator "" s( const char8_t *str,  size_t len ); // C++20
+basic_string<char16_t> operator "" s( const char16_t *str, size_t len );           // C++14, constexpr since C++20
+basic_string<char32_t> operator "" s( const char32_t *str, size_t len );           // C++14, constexpr since C++20
 
 }  // std
 
@@ -580,23 +578,27 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 basic_string<_CharT, _Traits, _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __x,
           const basic_string<_CharT, _Traits, _Allocator>& __y);
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const _CharT* __x, const basic_string<_CharT,_Traits,_Allocator>& __y);
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(_CharT __x, const basic_string<_CharT,_Traits,_Allocator>& __y);
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y);
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y);
 
@@ -666,8 +668,8 @@
 
     typedef __wrap_iter<pointer>                         iterator;
     typedef __wrap_iter<const_pointer>                   const_iterator;
-    typedef _VSTD::reverse_iterator<iterator>             reverse_iterator;
-    typedef _VSTD::reverse_iterator<const_iterator>       const_reverse_iterator;
+    typedef std::reverse_iterator<iterator>              reverse_iterator;
+    typedef std::reverse_iterator<const_iterator>        const_reverse_iterator;
 
 private:
 
@@ -770,7 +772,8 @@
     // Construct a string with the given allocator and enough storage to hold `__size` characters, but
     // don't initialize the characters. The contents of the string, including the null terminator, must be
     // initialized separately.
-    _LIBCPP_HIDE_FROM_ABI explicit basic_string(__uninitialized_size_tag, size_type __size, const allocator_type& __a)
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+    explicit basic_string(__uninitialized_size_tag, size_type __size, const allocator_type& __a)
             : __r_(__default_init_tag(), __a) {
         if (__size > max_size())
             __throw_length_error();
@@ -780,6 +783,7 @@
         } else {
             auto __capacity = __recommend(__size) + 1;
             auto __allocation = __alloc_traits::allocate(__alloc(), __capacity);
+            __begin_lifetime(__allocation, __capacity);
             __set_long_cap(__capacity);
             __set_long_pointer(__allocation);
             __set_long_size(__size);
@@ -791,21 +795,21 @@
     _LIBCPP_TEMPLATE_DATA_VIS
     static const size_type npos = -1;
 
-    _LIBCPP_INLINE_VISIBILITY basic_string()
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string()
         _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value);
 
-    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit basic_string(const allocator_type& __a)
 #if _LIBCPP_STD_VER <= 14
         _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value);
 #else
         _NOEXCEPT;
 #endif
 
-    basic_string(const basic_string& __str);
-    basic_string(const basic_string& __str, const allocator_type& __a);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string(const basic_string& __str);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string(const basic_string& __str, const allocator_type& __a);
 
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(basic_string&& __str)
 #if _LIBCPP_STD_VER <= 14
         _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
@@ -813,12 +817,12 @@
         _NOEXCEPT;
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(basic_string&& __str, const allocator_type& __a);
 #endif // _LIBCPP_CXX03_LANG
 
     template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(const _CharT* __s) : __r_(__default_init_tag(), __default_init_tag()) {
       _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr");
       __init(__s, traits_type::length(__s));
@@ -826,146 +830,151 @@
     }
 
     template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
-        _LIBCPP_INLINE_VISIBILITY
+        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
         basic_string(const _CharT* __s, const _Allocator& __a);
 
 #if _LIBCPP_STD_VER > 20
     basic_string(nullptr_t) = delete;
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(const _CharT* __s, size_type __n);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(const _CharT* __s, size_type __n, const _Allocator& __a);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(size_type __n, _CharT __c);
 
     template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> >
-        _LIBCPP_INLINE_VISIBILITY
+        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
         basic_string(size_type __n, _CharT __c, const _Allocator& __a);
 
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(const basic_string& __str, size_type __pos, size_type __n,
                  const _Allocator& __a = _Allocator());
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(const basic_string& __str, size_type __pos,
                  const _Allocator& __a = _Allocator());
 
     template<class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >
-        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
         basic_string(const _Tp& __t, size_type __pos, size_type __n,
                      const allocator_type& __a = allocator_type());
 
     template<class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
                                           !__is_same_uncvref<_Tp, basic_string>::value> >
-        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
         explicit basic_string(const _Tp& __t);
 
     template<class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >
-        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
         explicit basic_string(const _Tp& __t, const allocator_type& __a);
 
     template<class _InputIterator, class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value> >
-        _LIBCPP_INLINE_VISIBILITY
+        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
         basic_string(_InputIterator __first, _InputIterator __last);
     template<class _InputIterator, class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value> >
-        _LIBCPP_INLINE_VISIBILITY
+        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
         basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a);
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(initializer_list<_CharT> __il);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string(initializer_list<_CharT> __il, const _Allocator& __a);
 #endif // _LIBCPP_CXX03_LANG
 
-    inline ~basic_string();
+    inline _LIBCPP_CONSTEXPR_AFTER_CXX17 ~basic_string();
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); }
 
-    basic_string& operator=(const basic_string& __str);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator=(const basic_string& __str);
 
-    template <class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value> >
-    basic_string& operator=(const _Tp& __t)
-        {__self_view __sv = __t; return assign(__sv);}
+    template <class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
+                                               !__is_same_uncvref<_Tp, basic_string>::value> >
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator=(const _Tp& __t) {
+      __self_view __sv = __t;
+      return assign(__sv);
+    }
 
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& operator=(basic_string&& __str)
         _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
-     _LIBCPP_INLINE_VISIBILITY
+     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& operator=(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());}
 #endif
-    _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    basic_string& operator=(const value_type* __s) {return assign(__s);}
 #if _LIBCPP_STD_VER > 20
     basic_string& operator=(nullptr_t) = delete;
 #endif
-    basic_string& operator=(value_type __c);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator=(value_type __c);
 
 #if _LIBCPP_DEBUG_LEVEL == 2
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator begin() _NOEXCEPT
         {return iterator(this, __get_pointer());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_iterator begin() const _NOEXCEPT
         {return const_iterator(this, __get_pointer());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator end() _NOEXCEPT
         {return iterator(this, __get_pointer() + size());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_iterator end() const _NOEXCEPT
         {return const_iterator(this, __get_pointer() + size());}
 #else
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator begin() _NOEXCEPT
         {return iterator(__get_pointer());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_iterator begin() const _NOEXCEPT
         {return const_iterator(__get_pointer());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator end() _NOEXCEPT
         {return iterator(__get_pointer() + size());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_iterator end() const _NOEXCEPT
         {return const_iterator(__get_pointer() + size());}
 #endif // _LIBCPP_DEBUG_LEVEL == 2
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     reverse_iterator rbegin() _NOEXCEPT
         {return reverse_iterator(end());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_reverse_iterator rbegin() const _NOEXCEPT
         {return const_reverse_iterator(end());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     reverse_iterator rend() _NOEXCEPT
         {return reverse_iterator(begin());}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_reverse_iterator rend() const _NOEXCEPT
         {return const_reverse_iterator(begin());}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_iterator cbegin() const _NOEXCEPT
         {return begin();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_iterator cend() const _NOEXCEPT
         {return end();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_reverse_iterator crbegin() const _NOEXCEPT
         {return rbegin();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_reverse_iterator crend() const _NOEXCEPT
         {return rend();}
 
-    _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type size() const _NOEXCEPT
         {return __is_long() ? __get_long_size() : __get_short_size();}
-    _LIBCPP_INLINE_VISIBILITY size_type length() const _NOEXCEPT {return size();}
-    _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY size_type capacity() const _NOEXCEPT
-        {return (__is_long() ? __get_long_cap()
-                             : static_cast<size_type>(__min_cap)) - 1;}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type length() const _NOEXCEPT {return size();}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type capacity() const _NOEXCEPT {
+        return (__is_long() ? __get_long_cap() : static_cast<size_type>(__min_cap)) - 1;
+    }
 
-    void resize(size_type __n, value_type __c);
-    _LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {resize(__n, value_type());}
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __n, value_type __c);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __n) { resize(__n, value_type()); }
 
-    void reserve(size_type __requested_capacity);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __requested_capacity);
 
 #if _LIBCPP_STD_VER > 20
     template <class _Op>
@@ -976,55 +985,67 @@
     }
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY void __resize_default_init(size_type __n);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __resize_default_init(size_type __n);
 
-    _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY
-    void reserve() _NOEXCEPT {shrink_to_fit();}
-    _LIBCPP_INLINE_VISIBILITY
-    void shrink_to_fit() _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
-    void clear() _NOEXCEPT;
-    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void reserve() _NOEXCEPT { shrink_to_fit(); }
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void clear() _NOEXCEPT;
+
+    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     bool empty() const _NOEXCEPT {return size() == 0;}
 
-    _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __pos) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY reference       operator[](size_type __pos)       _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    const_reference operator[](size_type __pos) const _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator[](size_type __pos) _NOEXCEPT;
 
-    const_reference at(size_type __n) const;
-    reference       at(size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference at(size_type __n) const;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 reference       at(size_type __n);
 
-    _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const basic_string& __str) {return append(__str);}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator+=(const basic_string& __str) {
+        return append(__str);
+    }
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
             && !__is_same_uncvref<_Tp, basic_string >::value,
             basic_string&
         >
-                                            operator+=(const _Tp& __t)            {__self_view __sv = __t; return append(__sv);}
-    _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const value_type* __s)     {return append(__s);}
-    _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(value_type __c)            {push_back(__c); return *this;}
+    operator+=(const _Tp& __t) {
+        __self_view __sv = __t; return append(__sv);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator+=(const value_type* __s) {
+        return append(__s);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& operator+=(value_type __c) {
+        push_back(__c);
+        return *this;
+    }
+
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(initializer_list<value_type> __il) {return append(__il);}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    basic_string& operator+=(initializer_list<value_type> __il) { return append(__il); }
 #endif // _LIBCPP_CXX03_LANG
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& append(const basic_string& __str);
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t<
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
             && !__is_same_uncvref<_Tp, basic_string>::value,
             basic_string&
         >
                   append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); }
-    basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos);
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
@@ -1032,11 +1053,11 @@
             basic_string&
         >
                   append(const _Tp& __t, size_type __pos, size_type __n=npos);
-    basic_string& append(const value_type* __s, size_type __n);
-    basic_string& append(const value_type* __s);
-    basic_string& append(size_type __n, value_type __c);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& append(const value_type* __s, size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& append(const value_type* __s);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& append(size_type __n, value_type __c);
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __append_default_init(size_type __n);
 
     template<class _InputIterator>
@@ -1046,7 +1067,7 @@
             __is_exactly_cpp17_input_iterator<_InputIterator>::value,
             basic_string&
         >
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     append(_InputIterator __first, _InputIterator __last) {
       const basic_string __temp(__first, __last, __alloc());
       append(__temp.data(), __temp.size());
@@ -1059,41 +1080,40 @@
             __is_cpp17_forward_iterator<_ForwardIterator>::value,
             basic_string&
         >
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     append(_ForwardIterator __first, _ForwardIterator __last);
 
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& append(initializer_list<value_type> __il) {return append(__il.begin(), __il.size());}
 #endif // _LIBCPP_CXX03_LANG
 
-    void push_back(value_type __c);
-    _LIBCPP_INLINE_VISIBILITY
-    void pop_back();
-    _LIBCPP_INLINE_VISIBILITY reference       front() _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY reference       back() _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_back(value_type __c);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void pop_back();
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference       front() _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference front() const _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference       back() _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference back() const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             basic_string&
         >
                  assign(const _Tp & __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); }
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& assign(const basic_string& __str) { return *this = __str; }
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& assign(basic_string&& __str)
         _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
         {*this = _VSTD::move(__str); return *this;}
 #endif
-    basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos);
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
@@ -1101,11 +1121,11 @@
             basic_string&
         >
                   assign(const _Tp & __t, size_type __pos, size_type __n=npos);
-    basic_string& assign(const value_type* __s, size_type __n);
-    basic_string& assign(const value_type* __s);
-    basic_string& assign(size_type __n, value_type __c);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& assign(const value_type* __s, size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& assign(const value_type* __s);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& assign(size_type __n, value_type __c);
     template<class _InputIterator>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __is_exactly_cpp17_input_iterator<_InputIterator>::value,
@@ -1113,7 +1133,7 @@
         >
         assign(_InputIterator __first, _InputIterator __last);
     template<class _ForwardIterator>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -1121,15 +1141,15 @@
         >
         assign(_ForwardIterator __first, _ForwardIterator __last);
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& assign(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());}
 #endif // _LIBCPP_CXX03_LANG
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& insert(size_type __pos1, const basic_string& __str);
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -1139,22 +1159,23 @@
     { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); }
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value,
             basic_string&
         >
                   insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n=npos);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n=npos);
-    basic_string& insert(size_type __pos, const value_type* __s, size_type __n);
-    basic_string& insert(size_type __pos, const value_type* __s);
-    basic_string& insert(size_type __pos, size_type __n, value_type __c);
-    iterator      insert(const_iterator __pos, value_type __c);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& insert(size_type __pos, const value_type* __s, size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& insert(size_type __pos, const value_type* __s);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& insert(size_type __pos, size_type __n, value_type __c);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator      insert(const_iterator __pos, value_type __c);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator      insert(const_iterator __pos, size_type __n, value_type __c);
     template<class _InputIterator>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __is_exactly_cpp17_input_iterator<_InputIterator>::value,
@@ -1162,7 +1183,7 @@
         >
         insert(const_iterator __pos, _InputIterator __first, _InputIterator __last);
     template<class _ForwardIterator>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -1170,45 +1191,47 @@
         >
         insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator insert(const_iterator __pos, initializer_list<value_type> __il)
                     {return insert(__pos, __il.begin(), __il.end());}
 #endif // _LIBCPP_CXX03_LANG
 
-    basic_string& erase(size_type __pos = 0, size_type __n = npos);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& erase(size_type __pos = 0, size_type __n = npos);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator      erase(const_iterator __pos);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     iterator      erase(const_iterator __first, const_iterator __last);
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str);
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             basic_string&
         >
                   replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); }
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos);
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string>::value,
             basic_string&
         >
                   replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2);
-    basic_string& replace(size_type __pos, size_type __n1, const value_type* __s);
-    basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(const_iterator __i1, const_iterator __i2, const basic_string& __str);
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -1216,14 +1239,14 @@
         >
                   replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c);
     template<class _InputIterator>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __is_cpp17_input_iterator<_InputIterator>::value,
@@ -1231,16 +1254,16 @@
         >
         replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2);
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il)
         {return replace(__i1, __i2, __il.begin(), __il.end());}
 #endif // _LIBCPP_CXX03_LANG
 
-    size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string substr(size_type __pos = 0, size_type __n = npos) const;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void swap(basic_string& __str)
 #if _LIBCPP_STD_VER >= 14
         _NOEXCEPT;
@@ -1249,123 +1272,129 @@
                     __is_nothrow_swappable<allocator_type>::value);
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const value_type* c_str() const _NOEXCEPT {return data();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const value_type* data() const _NOEXCEPT  {return _VSTD::__to_address(__get_pointer());}
 #if _LIBCPP_STD_VER > 14 || defined(_LIBCPP_BUILDING_LIBRARY)
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     value_type* data()             _NOEXCEPT  {return _VSTD::__to_address(__get_pointer());}
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     allocator_type get_allocator() const _NOEXCEPT {return __alloc();}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             size_type
         >
               find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT;
-    size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             size_type
         >
               rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT;
-    size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             size_type
         >
               find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             size_type
         >
               find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             size_type
         >
               find_first_not_of(const _Tp &__t, size_type __pos = 0) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
             size_type
         >
               find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     int compare(const basic_string& __str) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -1374,7 +1403,7 @@
         compare(const _Tp &__t) const _NOEXCEPT;
 
     template <class _Tp>
-    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -1382,20 +1411,23 @@
         >
          compare(size_type __pos1, size_type __n1, const _Tp& __t) const;
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     int compare(size_type __pos1, size_type __n1, const basic_string& __str) const;
-    int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos) const;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
+    int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2,
+                size_type __n2 = npos) const;
 
     template <class _Tp>
-    inline _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
         __enable_if_t
         <
             __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string>::value,
             int
         >
         compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos) const;
-    int compare(const value_type* __s) const _NOEXCEPT;
-    int compare(size_type __pos1, size_type __n1, const value_type* __s) const;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 int compare(const value_type* __s) const _NOEXCEPT;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 int compare(size_type __pos1, size_type __n1, const value_type* __s) const;
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const;
 
 #if _LIBCPP_STD_VER > 17
@@ -1438,16 +1470,9 @@
     { return __self_view(data(), size()).contains(__s); }
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY bool __invariants() const;
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const;
 
-    _LIBCPP_INLINE_VISIBILITY void __clear_and_shrink() _NOEXCEPT;
-
-    _LIBCPP_INLINE_VISIBILITY void __shrink_or_extend(size_type __target_capacity);
-
-    _LIBCPP_INLINE_VISIBILITY
-    bool __is_long() const _NOEXCEPT {
-        return __r_.first().__s.__is_long_;
-    }
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __clear_and_shrink() _NOEXCEPT;
 
 #if _LIBCPP_DEBUG_LEVEL == 2
 
@@ -1459,6 +1484,49 @@
 #endif // _LIBCPP_DEBUG_LEVEL == 2
 
 private:
+    template<class _Alloc>
+    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    bool friend operator==(const basic_string<char, char_traits<char>, _Alloc>& __lhs,
+                           const basic_string<char, char_traits<char>, _Alloc>& __rhs) _NOEXCEPT;
+
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __shrink_or_extend(size_type __target_capacity);
+
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    bool __is_long() const _NOEXCEPT {
+        if (__libcpp_is_constant_evaluated())
+            return true;
+        return __r_.first().__s.__is_long_;
+    }
+
+    static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __begin_lifetime(pointer __begin, size_type __n) {
+#if _LIBCPP_STD_VER > 17
+        if (__libcpp_is_constant_evaluated()) {
+            for (size_type __i = 0; __i != __n; ++__i)
+                std::construct_at(std::addressof(__begin[__i]));
+        }
+#else
+        (void)__begin;
+        (void)__n;
+#endif // _LIBCPP_STD_VER > 17
+    }
+
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __default_init() {
+        __zero();
+        if (__libcpp_is_constant_evaluated()) {
+            size_type __sz = __recommend(0) + 1;
+            pointer __ptr = __alloc_traits::allocate(__alloc(), __sz);
+            __begin_lifetime(__ptr, __sz);
+            __set_long_pointer(__ptr);
+            __set_long_cap(__sz);
+            __set_long_size(0);
+        }
+    }
+
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __deallocate_constexpr() {
+        if (__libcpp_is_constant_evaluated() && __get_pointer() != nullptr)
+            __alloc_traits::deallocate(__alloc(), __get_pointer(), __get_long_cap());
+    }
+
     _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) {
         // SSO is disabled during constant evaluation because `__is_long` isn't constexpr friendly
         return !__libcpp_is_constant_evaluated() && (__sz < __min_cap);
@@ -1491,93 +1559,95 @@
         return begin() + __ip;
     }
 
-    _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __r_.second(); }
-    _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); }
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); }
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __set_short_size(size_type __s) _NOEXCEPT {
         _LIBCPP_ASSERT(__s < __min_cap, "__s should never be greater than or equal to the short string capacity");
         __r_.first().__s.__size_ = __s;
         __r_.first().__s.__is_long_ = false;
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type __get_short_size() const _NOEXCEPT {
         _LIBCPP_ASSERT(!__r_.first().__s.__is_long_, "String has to be short when trying to get the short size");
         return __r_.first().__s.__size_;
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __set_long_size(size_type __s) _NOEXCEPT
         {__r_.first().__l.__size_ = __s;}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type __get_long_size() const _NOEXCEPT
         {return __r_.first().__l.__size_;}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __set_size(size_type __s) _NOEXCEPT
         {if (__is_long()) __set_long_size(__s); else __set_short_size(__s);}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __set_long_cap(size_type __s) _NOEXCEPT {
         __r_.first().__l.__cap_ = __s / __endian_factor;
         __r_.first().__l.__is_long_ = true;
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type __get_long_cap() const _NOEXCEPT {
         return __r_.first().__l.__cap_ * __endian_factor;
     }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __set_long_pointer(pointer __p) _NOEXCEPT
         {__r_.first().__l.__data_ = __p;}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pointer __get_long_pointer() _NOEXCEPT
         {return __r_.first().__l.__data_;}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_pointer __get_long_pointer() const _NOEXCEPT
         {return __r_.first().__l.__data_;}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pointer __get_short_pointer() _NOEXCEPT
         {return pointer_traits<pointer>::pointer_to(__r_.first().__s.__data_[0]);}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_pointer __get_short_pointer() const _NOEXCEPT
         {return pointer_traits<const_pointer>::pointer_to(__r_.first().__s.__data_[0]);}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     pointer __get_pointer() _NOEXCEPT
         {return __is_long() ? __get_long_pointer() : __get_short_pointer();}
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     const_pointer __get_pointer() const _NOEXCEPT
         {return __is_long() ? __get_long_pointer() : __get_short_pointer();}
 
-    _LIBCPP_INLINE_VISIBILITY
-    void __zero() _NOEXCEPT
-        {
-            size_type (&__a)[__n_words] = __r_.first().__r.__words;
-            for (unsigned __i = 0; __i < __n_words; ++__i)
-                __a[__i] = 0;
-        }
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+    void __zero() _NOEXCEPT {
+        __r_.first() = __rep();
+    }
 
     template <size_type __a> static
-        _LIBCPP_INLINE_VISIBILITY
+        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
         size_type __align_it(size_type __s) _NOEXCEPT
             {return (__s + (__a-1)) & ~(__a-1);}
     enum {__alignment = 16};
-    static _LIBCPP_INLINE_VISIBILITY
+    static _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     size_type __recommend(size_type __s) _NOEXCEPT
-        {
-        if (__s < __min_cap) return static_cast<size_type>(__min_cap) - 1;
+    {
+        if (__s < __min_cap) {
+            if (__libcpp_is_constant_evaluated())
+                return static_cast<size_type>(__min_cap);
+            else
+                return static_cast<size_type>(__min_cap) - 1;
+        }
         size_type __guess = __align_it<sizeof(value_type) < __alignment ?
                      __alignment/sizeof(value_type) : 1 > (__s+1) - 1;
         if (__guess == __min_cap) ++__guess;
         return __guess;
-        }
+    }
 
-    inline
+    inline _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __init(const value_type* __s, size_type __sz, size_type __reserve);
-    inline
+    inline _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __init(const value_type* __s, size_type __sz);
-    inline
+    inline _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __init(size_type __n, value_type __c);
 
     // Slow path for the (inlined) copy constructor for 'long' strings.
@@ -1588,10 +1658,10 @@
     // to call the __init() functions as those are marked as inline which may
     // result in over-aggressive inlining by the compiler, where our aim is
     // to only inline the fast path code directly in the ctor.
-    void __init_copy_ctor_external(const value_type* __s, size_type __sz);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __init_copy_ctor_external(const value_type* __s, size_type __sz);
 
     template <class _InputIterator>
-    inline
+    inline _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
     <
         __is_exactly_cpp17_input_iterator<_InputIterator>::value
@@ -1599,15 +1669,17 @@
     __init(_InputIterator __first, _InputIterator __last);
 
     template <class _ForwardIterator>
-    inline
+    inline _LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
     <
         __is_cpp17_forward_iterator<_ForwardIterator>::value
     >
     __init(_ForwardIterator __first, _ForwardIterator __last);
 
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
                    size_type __n_copy,  size_type __n_del,     size_type __n_add = 0);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __grow_by_and_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
                                size_type __n_copy,  size_type __n_del,
                                size_type __n_add, const value_type* __p_new_stuff);
@@ -1616,21 +1688,21 @@
     // have proof that the input does not alias the current instance.
     // For example, operator=(basic_string) performs a 'self' check.
     template <bool __is_short>
-    basic_string& __assign_no_alias(const value_type* __s, size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& __assign_no_alias(const value_type* __s, size_type __n);
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __erase_to_end(size_type __pos);
 
     // __erase_external_with_move is invoked for erase() invocations where
     // `n ~= npos`, likely requiring memory moves on the string data.
-    void __erase_external_with_move(size_type __pos, size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __erase_external_with_move(size_type __pos, size_type __n);
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __copy_assign_alloc(const basic_string& __str)
         {__copy_assign_alloc(__str, integral_constant<bool,
                       __alloc_traits::propagate_on_container_copy_assignment::value>());}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __copy_assign_alloc(const basic_string& __str, true_type)
         {
             if (__alloc() == __str.__alloc())
@@ -1646,6 +1718,7 @@
                 {
                     allocator_type __a = __str.__alloc();
                     auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
+                    __begin_lifetime(__allocation.ptr, __allocation.count);
                     __clear_and_shrink();
                     __alloc() = _VSTD::move(__a);
                     __set_long_pointer(__allocation.ptr);
@@ -1655,15 +1728,15 @@
             }
         }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __copy_assign_alloc(const basic_string&, false_type) _NOEXCEPT
         {}
 
 #ifndef _LIBCPP_CXX03_LANG
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __move_assign(basic_string& __str, false_type)
         _NOEXCEPT_(__alloc_traits::is_always_equal::value);
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __move_assign(basic_string& __str, true_type)
 #if _LIBCPP_STD_VER > 14
         _NOEXCEPT;
@@ -1672,7 +1745,7 @@
 #endif
 #endif
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void
     __move_assign_alloc(basic_string& __str)
         _NOEXCEPT_(
@@ -1681,20 +1754,20 @@
     {__move_assign_alloc(__str, integral_constant<bool,
                       __alloc_traits::propagate_on_container_move_assignment::value>());}
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __move_assign_alloc(basic_string& __c, true_type)
         _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
         {
             __alloc() = _VSTD::move(__c.__alloc());
         }
 
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     void __move_assign_alloc(basic_string&, false_type)
         _NOEXCEPT
         {}
 
-    basic_string& __assign_external(const value_type* __s);
-    basic_string& __assign_external(const value_type* __s, size_type __n);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& __assign_external(const value_type* __s);
+    _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string& __assign_external(const value_type* __s, size_type __n);
 
     // Assigns the value in __s, guaranteed to be __n < __min_cap in length.
     inline basic_string& __assign_short(const value_type* __s, size_type __n) {
@@ -1706,19 +1779,23 @@
       return *this;
     }
 
-    _LIBCPP_HIDE_FROM_ABI basic_string& __null_terminate_at(value_type* __p, size_type __newsz) {
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+    basic_string& __null_terminate_at(value_type* __p, size_type __newsz) {
       __set_size(__newsz);
       __invalidate_iterators_past(__newsz);
       traits_type::assign(__p[__newsz], value_type());
       return *this;
     }
 
-    _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();
-    _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type);
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __invalidate_all_iterators();
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __invalidate_iterators_past(size_type);
 
     template<class _Tp>
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     bool __addr_in_range(_Tp&& __t) const {
+        // assume that the ranges overlap, because we can't check during constant evaluation
+        if (__libcpp_is_constant_evaluated())
+          return true;
         const volatile void *__p = _VSTD::addressof(__t);
         return data() <= __p && __p <= data() + size();
     }
@@ -1733,11 +1810,11 @@
         _VSTD::__throw_out_of_range("basic_string");
     }
 
-    friend basic_string operator+<>(const basic_string&, const basic_string&);
-    friend basic_string operator+<>(const value_type*, const basic_string&);
-    friend basic_string operator+<>(value_type, const basic_string&);
-    friend basic_string operator+<>(const basic_string&, const value_type*);
-    friend basic_string operator+<>(const basic_string&, value_type);
+    friend _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string operator+<>(const basic_string&, const basic_string&);
+    friend _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string operator+<>(const value_type*, const basic_string&);
+    friend _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string operator+<>(value_type, const basic_string&);
+    friend _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string operator+<>(const basic_string&, const value_type*);
+    friend _LIBCPP_CONSTEXPR_AFTER_CXX17 basic_string operator+<>(const basic_string&, value_type);
 };
 
 // These declarations must appear before any functions are implicitly used
@@ -1784,7 +1861,7 @@
 #endif
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__invalidate_all_iterators()
 {
@@ -1795,7 +1872,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type __pos)
 {
@@ -1825,17 +1902,17 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string()
     _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
      : __r_(__default_init_tag(), __default_init_tag())
 {
-    _VSTD::__debug_db_insert_c(this);
-    __zero();
+    std::__debug_db_insert_c(this);
+    __default_init();
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
 #if _LIBCPP_STD_VER <= 14
         _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
@@ -1844,15 +1921,18 @@
 #endif
 : __r_(__default_init_tag(), __a)
 {
-    _VSTD::__debug_db_insert_c(this);
-    __zero();
+    std::__debug_db_insert_c(this);
+    __default_init();
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s,
                                                        size_type __sz,
                                                        size_type __reserve)
 {
+    if (__libcpp_is_constant_evaluated())
+        __zero();
     if (__reserve > max_size())
         __throw_length_error();
     pointer __p;
@@ -1865,6 +1945,7 @@
     {
         auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1);
         __p = __allocation.ptr;
+        __begin_lifetime(__p, __allocation.count);
         __set_long_pointer(__p);
         __set_long_cap(__allocation.count);
         __set_long_size(__sz);
@@ -1874,9 +1955,12 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz)
 {
+    if (__libcpp_is_constant_evaluated())
+        __zero();
     if (__sz > max_size())
         __throw_length_error();
     pointer __p;
@@ -1889,6 +1973,7 @@
     {
         auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
         __p = __allocation.ptr;
+        __begin_lifetime(__p, __allocation.count);
         __set_long_pointer(__p);
         __set_long_cap(__allocation.count);
         __set_long_size(__sz);
@@ -1899,6 +1984,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a)
     : __r_(__default_init_tag(), __a)
 {
@@ -1908,7 +1994,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n)
      : __r_(__default_init_tag(), __default_init_tag())
 {
@@ -1918,7 +2004,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n, const _Allocator& __a)
     : __r_(__default_init_tag(), __a)
 {
@@ -1928,6 +2014,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str)
     : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc()))
 {
@@ -1940,6 +2027,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(
     const basic_string& __str, const allocator_type& __a)
     : __r_(__default_init_tag(), __a)
@@ -1953,8 +2041,11 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(
     const value_type* __s, size_type __sz) {
+  if (__libcpp_is_constant_evaluated())
+    __zero();
   pointer __p;
   if (__fits_in_sso(__sz)) {
     __p = __get_short_pointer();
@@ -1964,17 +2055,18 @@
       __throw_length_error();
     auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
     __p = __allocation.ptr;
+    __begin_lifetime(__p, __allocation.count);
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
     __set_long_size(__sz);
   }
-  traits_type::copy(_VSTD::__to_address(__p), __s, __sz + 1);
+  traits_type::copy(std::__to_address(__p), __s, __sz + 1);
 }
 
 #ifndef _LIBCPP_CXX03_LANG
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str)
 #if _LIBCPP_STD_VER <= 14
         _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
@@ -1983,7 +2075,7 @@
 #endif
     : __r_(_VSTD::move(__str.__r_))
 {
-    __str.__zero();
+    __str.__default_init();
     _VSTD::__debug_db_insert_c(this);
 #if _LIBCPP_DEBUG_LEVEL == 2
     if (!__libcpp_is_constant_evaluated() && __is_long())
@@ -1992,7 +2084,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a)
     : __r_(__default_init_tag(), __a)
 {
@@ -2000,8 +2092,13 @@
         __init(_VSTD::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
     else
     {
-        __r_.first().__r = __str.__r_.first().__r;
-        __str.__zero();
+        if (__libcpp_is_constant_evaluated()) {
+            __zero();
+            __r_.first().__l = __str.__r_.first().__l;
+        } else {
+            __r_.first().__r = __str.__r_.first().__r;
+        }
+        __str.__default_init();
     }
     _VSTD::__debug_db_insert_c(this);
 #if _LIBCPP_DEBUG_LEVEL == 2
@@ -2013,9 +2110,12 @@
 #endif // _LIBCPP_CXX03_LANG
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
 {
+    if (__libcpp_is_constant_evaluated())
+        __zero();
     if (__n > max_size())
         __throw_length_error();
     pointer __p;
@@ -2028,6 +2128,7 @@
     {
         auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1);
         __p = __allocation.ptr;
+        __begin_lifetime(__p, __allocation.count);
         __set_long_pointer(__p);
         __set_long_cap(__allocation.count);
         __set_long_size(__n);
@@ -2037,7 +2138,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c)
      : __r_(__default_init_tag(), __default_init_tag())
 {
@@ -2047,6 +2148,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a)
     : __r_(__default_init_tag(), __a)
 {
@@ -2055,6 +2157,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str,
                                                         size_type __pos, size_type __n,
                                                         const _Allocator& __a)
@@ -2068,7 +2171,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos,
                                                         const _Allocator& __a)
     : __r_(__default_init_tag(), __a)
@@ -2082,6 +2185,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp, class>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(
              const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a)
     : __r_(__default_init_tag(), __a)
@@ -2094,6 +2198,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp, class>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t)
      : __r_(__default_init_tag(), __default_init_tag())
 {
@@ -2104,6 +2209,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp, class>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t, const _Allocator& __a)
     : __r_(__default_init_tag(), __a)
 {
@@ -2114,13 +2220,14 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _InputIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __is_exactly_cpp17_input_iterator<_InputIterator>::value
 >
 basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last)
 {
-    __zero();
+    __default_init();
 #ifndef _LIBCPP_NO_EXCEPTIONS
     try
     {
@@ -2140,12 +2247,15 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _ForwardIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __is_cpp17_forward_iterator<_ForwardIterator>::value
 >
 basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last)
 {
+    if (__libcpp_is_constant_evaluated())
+        __zero();
     size_type __sz = static_cast<size_type>(_VSTD::distance(__first, __last));
     if (__sz > max_size())
         __throw_length_error();
@@ -2159,6 +2269,7 @@
     {
         auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
         __p = __allocation.ptr;
+        __begin_lifetime(__p, __allocation.count);
         __set_long_pointer(__p);
         __set_long_cap(__allocation.count);
         __set_long_size(__sz);
@@ -2184,7 +2295,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _InputIterator, class>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last)
      : __r_(__default_init_tag(), __default_init_tag())
 {
@@ -2194,7 +2305,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _InputIterator, class>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last,
                                                         const allocator_type& __a)
     : __r_(__default_init_tag(), __a)
@@ -2206,7 +2317,7 @@
 #ifndef _LIBCPP_CXX03_LANG
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(
     initializer_list<_CharT> __il)
      : __r_(__default_init_tag(), __default_init_tag())
@@ -2216,8 +2327,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
-
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::basic_string(
     initializer_list<_CharT> __il, const _Allocator& __a)
     : __r_(__default_init_tag(), __a)
@@ -2229,6 +2339,7 @@
 #endif // _LIBCPP_CXX03_LANG
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::~basic_string()
 {
 #if _LIBCPP_DEBUG_LEVEL == 2
@@ -2240,6 +2351,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
     (size_type __old_cap, size_type __delta_cap, size_type __old_sz,
@@ -2254,6 +2366,7 @@
                           __ms - 1;
     auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
     pointer __p = __allocation.ptr;
+    __begin_lifetime(__p, __allocation.count);
     __invalidate_all_iterators();
     if (__n_copy != 0)
         traits_type::copy(_VSTD::__to_address(__p),
@@ -2264,7 +2377,7 @@
     if (__sec_cp_sz != 0)
         traits_type::copy(_VSTD::__to_address(__p) + __n_copy + __n_add,
                           _VSTD::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz);
-    if (__old_cap+1 != __min_cap)
+    if (__old_cap+1 != __min_cap || __libcpp_is_constant_evaluated())
         __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
@@ -2275,6 +2388,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 void
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz,
                                                      size_type __n_copy,  size_type __n_del,     size_type __n_add)
 {
@@ -2287,6 +2401,7 @@
                           __ms - 1;
     auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
     pointer __p = __allocation.ptr;
+    __begin_lifetime(__p, __allocation.count);
     __invalidate_all_iterators();
     if (__n_copy != 0)
         traits_type::copy(_VSTD::__to_address(__p),
@@ -2296,8 +2411,8 @@
         traits_type::copy(_VSTD::__to_address(__p) + __n_copy + __n_add,
                           _VSTD::__to_address(__old_p) + __n_copy + __n_del,
                           __sec_cp_sz);
-    if (__old_cap+1 != __min_cap)
-        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
+    if (__libcpp_is_constant_evaluated() || __old_cap + 1 != __min_cap)
+        __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1);
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
 }
@@ -2306,6 +2421,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <bool __is_short>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(
     const value_type* __s, size_type __n) {
@@ -2313,7 +2429,7 @@
   if (__n < __cap) {
     pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
     __is_short ? __set_short_size(__n) : __set_long_size(__n);
-    traits_type::copy(_VSTD::__to_address(__p), __s, __n);
+    traits_type::copy(std::__to_address(__p), __s, __n);
     traits_type::assign(__p[__n], value_type());
     __invalidate_iterators_past(__n);
   } else {
@@ -2324,6 +2440,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::__assign_external(
     const value_type* __s, size_type __n) {
@@ -2340,6 +2457,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)
 {
@@ -2350,6 +2468,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
 {
@@ -2365,6 +2484,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c)
 {
@@ -2386,6 +2506,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
 {
@@ -2407,7 +2528,7 @@
 #ifndef _LIBCPP_CXX03_LANG
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type)
     _NOEXCEPT_(__alloc_traits::is_always_equal::value)
@@ -2419,7 +2540,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
 #if _LIBCPP_STD_VER > 14
@@ -2440,12 +2561,16 @@
   }
   __move_assign_alloc(__str);
   __r_.first() = __str.__r_.first();
-  __str.__set_short_size(0);
-  traits_type::assign(__str.__get_short_pointer()[0], value_type());
+  if (__libcpp_is_constant_evaluated()) {
+    __str.__default_init();
+  } else {
+    __str.__set_short_size(0);
+    traits_type::assign(__str.__get_short_pointer()[0], value_type());
+  }
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str)
     _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
@@ -2459,6 +2584,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _InputIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
      __is_exactly_cpp17_input_iterator<_InputIterator>::value,
@@ -2473,6 +2599,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _ForwardIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -2508,6 +2635,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n)
 {
@@ -2519,6 +2647,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
@@ -2536,12 +2665,14 @@
 
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) {
   return __assign_external(__s, traits_type::length(__s));
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s)
 {
@@ -2555,6 +2686,7 @@
 // append
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n)
 {
@@ -2578,6 +2710,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c)
 {
@@ -2597,7 +2730,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline void
+_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void
 basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n)
 {
     if (__n)
@@ -2614,6 +2747,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c)
 {
@@ -2635,7 +2769,7 @@
         __grow_by(__cap, 1, __sz, __sz, 0);
         __is_short = false; // the string is always long after __grow_by
     }
-    pointer __p;
+    pointer __p = __get_pointer();
     if (__is_short)
     {
         __p = __get_short_pointer() + __sz;
@@ -2652,6 +2786,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _ForwardIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -2686,7 +2821,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str)
 {
@@ -2694,6 +2829,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n)
 {
@@ -2705,6 +2841,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
     __enable_if_t
     <
         __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
@@ -2720,6 +2857,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s)
 {
@@ -2730,6 +2868,7 @@
 // insert
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n)
 {
@@ -2738,6 +2877,13 @@
     if (__pos > __sz)
         __throw_out_of_range();
     size_type __cap = capacity();
+    if (__libcpp_is_constant_evaluated()) {
+        if (__cap - __sz >= __n)
+            __grow_by_and_replace(__cap, 0, __sz, __pos, 0, __n, __s);
+        else
+            __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s);
+        return *this;
+    }
     if (__cap - __sz >= __n)
     {
         if (__n)
@@ -2762,6 +2908,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c)
 {
@@ -2794,6 +2941,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _InputIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
    __is_exactly_cpp17_input_iterator<_InputIterator>::value,
@@ -2810,6 +2958,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _ForwardIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -2837,7 +2986,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str)
 {
@@ -2845,6 +2994,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str,
                                                   size_type __pos2, size_type __n)
@@ -2857,6 +3007,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value  && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
@@ -2873,6 +3024,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s)
 {
@@ -2881,6 +3033,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::iterator
 basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c)
 {
@@ -2911,7 +3064,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::iterator
 basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, size_type __n, value_type __c)
 {
@@ -2926,6 +3079,7 @@
 // replace
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2)
     _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
@@ -2938,6 +3092,10 @@
     size_type __cap = capacity();
     if (__cap - __sz + __n1 >= __n2)
     {
+        if (__libcpp_is_constant_evaluated()) {
+            __grow_by_and_replace(__cap, 0, __sz, __pos, __n1, __n2, __s);
+            return *this;
+        }
         value_type* __p = _VSTD::__to_address(__get_pointer());
         if (__n1 != __n2)
         {
@@ -2975,6 +3133,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c)
 {
@@ -3005,6 +3164,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template<class _InputIterator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __is_cpp17_input_iterator<_InputIterator>::value,
@@ -3018,7 +3178,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str)
 {
@@ -3026,6 +3186,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str,
                                                    size_type __pos2, size_type __n2)
@@ -3038,6 +3199,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value,
@@ -3054,6 +3216,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s)
 {
@@ -3062,7 +3225,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const basic_string& __str)
 {
@@ -3071,7 +3234,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n)
 {
@@ -3079,7 +3242,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s)
 {
@@ -3087,7 +3250,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c)
 {
@@ -3099,6 +3262,7 @@
 // 'externally instantiated' erase() implementation, called when __n != npos.
 // Does not check __pos against size()
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move(
     size_type __pos, size_type __n)
@@ -3116,6 +3280,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos,
                                                  size_type __n) {
@@ -3130,7 +3295,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::iterator
 basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos)
 {
@@ -3146,7 +3311,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::iterator
 basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last)
 {
@@ -3162,7 +3327,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::pop_back()
 {
@@ -3171,7 +3336,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT
 {
@@ -3189,7 +3354,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__erase_to_end(size_type __pos)
 {
@@ -3197,6 +3362,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c)
 {
@@ -3208,7 +3374,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline void
+_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void
 basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n)
 {
     size_type __sz = size();
@@ -3219,7 +3385,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::max_size() const _NOEXCEPT
 {
@@ -3233,6 +3399,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacity)
 {
@@ -3253,7 +3420,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::shrink_to_fit() _NOEXCEPT
 {
@@ -3264,7 +3431,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity)
 {
@@ -3273,7 +3440,7 @@
 
     pointer __new_data, __p;
     bool __was_long, __now_long;
-    if (__target_capacity == __min_cap - 1)
+    if (__fits_in_sso(__target_capacity))
     {
         __was_long = true;
         __now_long = false;
@@ -3307,6 +3474,7 @@
                 return;
         #endif // _LIBCPP_NO_EXCEPTIONS
         }
+        __begin_lifetime(__new_data, __target_capacity + 1);
         __now_long = true;
         __was_long = __is_long();
         __p = __get_pointer();
@@ -3327,7 +3495,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::const_reference
 basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) const _NOEXCEPT
 {
@@ -3336,7 +3504,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::reference
 basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) _NOEXCEPT
 {
@@ -3345,6 +3513,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::const_reference
 basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const
 {
@@ -3354,6 +3523,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::reference
 basic_string<_CharT, _Traits, _Allocator>::at(size_type __n)
 {
@@ -3363,7 +3533,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::reference
 basic_string<_CharT, _Traits, _Allocator>::front() _NOEXCEPT
 {
@@ -3372,7 +3542,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::const_reference
 basic_string<_CharT, _Traits, _Allocator>::front() const _NOEXCEPT
 {
@@ -3381,7 +3551,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::reference
 basic_string<_CharT, _Traits, _Allocator>::back() _NOEXCEPT
 {
@@ -3390,7 +3560,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::const_reference
 basic_string<_CharT, _Traits, _Allocator>::back() const _NOEXCEPT
 {
@@ -3399,6 +3569,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const
 {
@@ -3411,7 +3582,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 basic_string<_CharT, _Traits, _Allocator>::substr(size_type __pos, size_type __n) const
 {
@@ -3419,7 +3590,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
 #if _LIBCPP_STD_VER >= 14
@@ -3458,6 +3629,7 @@
 };
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s,
                                                 size_type __pos,
@@ -3469,7 +3641,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str,
                                                 size_type __pos) const _NOEXCEPT
@@ -3480,6 +3652,7 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3494,7 +3667,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s,
                                                 size_type __pos) const _NOEXCEPT
@@ -3505,6 +3678,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find(value_type __c,
                                                 size_type __pos) const _NOEXCEPT
@@ -3516,6 +3690,7 @@
 // rfind
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s,
                                                  size_type __pos,
@@ -3527,7 +3702,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str,
                                                  size_type __pos) const _NOEXCEPT
@@ -3538,6 +3713,7 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3552,7 +3728,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s,
                                                  size_type __pos) const _NOEXCEPT
@@ -3563,6 +3739,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c,
                                                  size_type __pos) const _NOEXCEPT
@@ -3574,6 +3751,7 @@
 // find_first_of
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s,
                                                          size_type __pos,
@@ -3585,7 +3763,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str,
                                                          size_type __pos) const _NOEXCEPT
@@ -3596,6 +3774,7 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3610,7 +3789,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s,
                                                          size_type __pos) const _NOEXCEPT
@@ -3621,7 +3800,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c,
                                                          size_type __pos) const _NOEXCEPT
@@ -3632,6 +3811,7 @@
 // find_last_of
 
 template<class _CharT, class _Traits, class _Allocator>
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s,
                                                         size_type __pos,
@@ -3643,7 +3823,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str,
                                                         size_type __pos) const _NOEXCEPT
@@ -3654,6 +3834,7 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3668,7 +3849,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s,
                                                         size_type __pos) const _NOEXCEPT
@@ -3679,7 +3860,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c,
                                                         size_type __pos) const _NOEXCEPT
@@ -3690,6 +3871,7 @@
 // find_first_not_of
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s,
                                                              size_type __pos,
@@ -3701,7 +3883,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str,
                                                              size_type __pos) const _NOEXCEPT
@@ -3712,6 +3894,7 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3726,7 +3909,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s,
                                                              size_type __pos) const _NOEXCEPT
@@ -3737,7 +3920,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c,
                                                              size_type __pos) const _NOEXCEPT
@@ -3749,6 +3932,7 @@
 // find_last_not_of
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s,
                                                             size_type __pos,
@@ -3760,7 +3944,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str,
                                                             size_type __pos) const _NOEXCEPT
@@ -3771,6 +3955,7 @@
 
 template<class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3785,7 +3970,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s,
                                                             size_type __pos) const _NOEXCEPT
@@ -3796,7 +3981,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename basic_string<_CharT, _Traits, _Allocator>::size_type
 basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c,
                                                             size_type __pos) const _NOEXCEPT
@@ -3809,6 +3994,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3831,7 +4017,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 int
 basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT
 {
@@ -3839,6 +4025,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 int
 basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
                                                    size_type __n1,
@@ -3863,6 +4050,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
@@ -3877,7 +4065,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 int
 basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
                                                    size_type __n1,
@@ -3888,6 +4076,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _Tp>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 __enable_if_t
 <
     __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value
@@ -3905,6 +4094,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 int
 basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
                                                    size_type __n1,
@@ -3916,6 +4106,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 int
 basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT
 {
@@ -3924,6 +4115,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 int
 basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1,
                                                    size_type __n1,
@@ -3936,7 +4128,7 @@
 // __invariants
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 bool
 basic_string<_CharT, _Traits, _Allocator>::__invariants() const
 {
@@ -3954,7 +4146,7 @@
 // __clear_and_shrink
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT
 {
@@ -3971,7 +4163,7 @@
 // operator==
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -3983,7 +4175,7 @@
 }
 
 template<class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs,
            const basic_string<char, char_traits<char>, _Allocator>& __rhs) _NOEXCEPT
@@ -4002,7 +4194,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator==(const _CharT* __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4015,7 +4207,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
@@ -4028,7 +4220,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4037,7 +4229,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator!=(const _CharT* __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4046,7 +4238,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
@@ -4057,7 +4249,7 @@
 // operator<
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4066,7 +4258,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
@@ -4075,7 +4267,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator< (const _CharT* __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4086,7 +4278,7 @@
 // operator>
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4095,7 +4287,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
@@ -4104,7 +4296,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator> (const _CharT* __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4115,7 +4307,7 @@
 // operator<=
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4124,7 +4316,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
@@ -4133,7 +4325,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator<=(const _CharT* __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4144,7 +4336,7 @@
 // operator>=
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4153,7 +4345,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
            const _CharT* __rhs) _NOEXCEPT
@@ -4162,7 +4354,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
 bool
 operator>=(const _CharT* __lhs,
            const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT
@@ -4173,6 +4365,7 @@
 // operator +
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
           const basic_string<_CharT, _Traits, _Allocator>& __rhs)
@@ -4191,6 +4384,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const _CharT* __lhs , const basic_string<_CharT,_Traits,_Allocator>& __rhs)
 {
@@ -4208,6 +4402,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs)
 {
@@ -4224,7 +4419,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline
+inline _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs)
 {
@@ -4242,6 +4437,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
+_LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs)
 {
@@ -4260,7 +4456,7 @@
 #ifndef _LIBCPP_CXX03_LANG
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs)
 {
@@ -4268,7 +4464,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
 {
@@ -4276,7 +4472,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
 {
@@ -4284,7 +4480,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(const _CharT* __lhs , basic_string<_CharT,_Traits,_Allocator>&& __rhs)
 {
@@ -4292,7 +4488,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(_CharT __lhs, basic_string<_CharT,_Traits,_Allocator>&& __rhs)
 {
@@ -4301,7 +4497,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs)
 {
@@ -4309,7 +4505,7 @@
 }
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 basic_string<_CharT, _Traits, _Allocator>
 operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs)
 {
@@ -4322,7 +4518,7 @@
 // swap
 
 template<class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 swap(basic_string<_CharT, _Traits, _Allocator>& __lhs,
      basic_string<_CharT, _Traits, _Allocator>& __rhs)
@@ -4487,14 +4683,14 @@
 {
   inline namespace string_literals
   {
-    inline _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string<char> operator "" s( const char *__str, size_t __len )
     {
         return basic_string<char> (__str, __len);
     }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-    inline _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string<wchar_t> operator "" s( const wchar_t *__str, size_t __len )
     {
         return basic_string<wchar_t> (__str, __len);
@@ -4502,20 +4698,20 @@
 #endif
 
 #ifndef _LIBCPP_HAS_NO_CHAR8_T
-    inline _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY constexpr
     basic_string<char8_t> operator "" s(const char8_t *__str, size_t __len) _NOEXCEPT
     {
         return basic_string<char8_t> (__str, __len);
     }
 #endif
 
-    inline _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string<char16_t> operator "" s( const char16_t *__str, size_t __len )
     {
         return basic_string<char16_t> (__str, __len);
     }
 
-    inline _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
     basic_string<char32_t> operator "" s( const char32_t *__str, size_t __len )
     {
         return basic_string<char32_t> (__str, __len);