[clang] [clang] Constant-evaluate format strings as last resort (PR #135864)
Hubert Tong via cfe-commits
cfe-commits at lists.llvm.org
Wed May 7 10:53:16 PDT 2025
================
@@ -238,3 +246,69 @@ void f(Scoped1 S1, Scoped2 S2) {
}
#endif
+
+#if __cplusplus >= 202000L
+class my_string {
+ char *data;
+ unsigned size;
+
+public:
+ template<unsigned N>
+ constexpr my_string(const char (&literal)[N]) {
+ data = new char[N+1];
+ for (size = 0; size < N; ++size) {
+ data[size] = literal[size];
+ if (data[size] == 0)
+ break;
+ }
+ data[size] = 0;
+ }
+
+ my_string(const my_string &) = delete;
+
+ constexpr my_string(my_string &&that) {
+ data = that.data;
+ size = that.size;
+ that.data = nullptr;
+ that.size = 0;
+ }
+
+ constexpr ~my_string() {
+ delete[] data;
+ }
+
+ template<unsigned N>
+ constexpr void append(const char (&literal)[N]) {
+ char *cat = new char[size + N + 1];
+ char *tmp = cat;
+ for (unsigned i = 0; i < size; ++i) {
+ *tmp++ = data[i];
+ }
+ for (unsigned i = 0; i < N; ++i) {
+ *tmp = literal[i];
+ if (*tmp == 0)
+ break;
+ ++tmp;
+ }
+ *tmp = 0;
+ delete[] data;
+ size = tmp - cat;
+ data = cat;
+ }
+
+ constexpr const char *c_str() const {
+ return data;
+ }
+};
+
+constexpr my_string const_string() {
+ my_string str("hello %s");
+ str.append(", %d");
+ return str;
+}
+
+void test_constexpr_string() {
+ printf(const_string().c_str(), "hello", 123); // no-warning
+ printf(const_string().c_str(), 123, 456); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+#endif
----------------
hubert-reinterpretcast wrote:
The context of the expression being evaluated during computation for the format string determines whether we can get a false positive/negative if we insist on getting a format string computation result.
We know whether or not `if consteval` should return true or false if the context is:
- in a manifestly constant-evaluated context or
- outside of a manifestly constant-evaluated context and not "in"
- a default member initializer, or
- a constexpr function or the default arguments thereof.
For such cases, I think we should get the correct format string computation.
For the other cases, I think (at least in the long term) we should (by default) fail the format string computation attempt when `if consteval` is encountered.
https://github.com/llvm/llvm-project/pull/135864
More information about the cfe-commits
mailing list