[PATCH] D137488: [clang][Interp] Array initialization via string literal
Timm Bäder via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 15 23:39:34 PST 2022
tbaeder updated this revision to Diff 475697.
tbaeder marked 2 inline comments as done.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D137488/new/
https://reviews.llvm.org/D137488
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -350,6 +350,46 @@
#endif
#pragma clang diagnostic pop
+
+ constexpr char foo[12] = "abc";
+ static_assert(foo[0] == 'a', "");
+ static_assert(foo[1] == 'b', "");
+ static_assert(foo[2] == 'c', "");
+ static_assert(foo[3] == 0, "");
+ static_assert(foo[11] == 0, "");
+
+ constexpr char foo2[] = "abc\0def";
+ static_assert(foo2[0] == 'a', "");
+ static_assert(foo2[3] == '\0', "");
+ static_assert(foo2[6] == 'f', "");
+ static_assert(foo2[7] == '\0', "");
+ static_assert(foo2[8] == '\0', ""); // expected-error {{not an integral constant expression}} \
+ // expected-note {{read of dereferenced one-past-the-end pointer}} \
+ // ref-error {{not an integral constant expression}} \
+ // ref-note {{read of dereferenced one-past-the-end pointer}}
+
+ constexpr char foo3[4] = "abc";
+ static_assert(foo3[3] == '\0', "");
+ static_assert(foo3[4] == '\0', ""); // expected-error {{not an integral constant expression}} \
+ // expected-note {{read of dereferenced one-past-the-end pointer}} \
+ // ref-error {{not an integral constant expression}} \
+ // ref-note {{read of dereferenced one-past-the-end pointer}}
+
+ constexpr char foo4[2] = "abcd"; // expected-error {{initializer-string for char array is too long}} \
+ // ref-error {{initializer-string for char array is too long}}
+ static_assert(foo4[0] == 'a', "");
+ static_assert(foo4[1] == 'b', "");
+ static_assert(foo4[2] == '\0', ""); // expected-error {{not an integral constant expression}} \
+ // expected-note {{read of dereferenced one-past-the-end pointer}} \
+ // ref-error {{not an integral constant expression}} \
+ // ref-note {{read of dereferenced one-past-the-end pointer}}
+
+constexpr char foo5[12] = "abc\xff";
+#if defined(__CHAR_UNSIGNED__) || __CHAR_BIT__ > 8
+static_assert(foo5[3] == 255, "");
+#else
+static_assert(foo5[3] == -1, "");
+#endif
};
#if __cplusplus > 201402L
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1073,6 +1073,34 @@
return false;
}
return true;
+ } else if (const auto *SL = dyn_cast<StringLiteral>(Initializer)) {
+ const ConstantArrayType *CAT =
+ Ctx.getASTContext().getAsConstantArrayType(SL->getType());
+ assert(CAT && "a string literal that's not a constant array?");
+
+ // If the initializer string is too long, a diagnostic has already been
+ // emitted.
+ unsigned N = std::min(SL->getLength(),
+ static_cast<unsigned>(CAT->getSize().getZExtValue()));
+ size_t CharWidth = SL->getCharByteWidth();
+
+ for (unsigned I = 0; I != N; ++I) {
+ uint32_t CodeUnit = SL->getCodeUnit(I);
+
+ if (CharWidth == 1) {
+ this->emitConstSint8(CodeUnit, SL);
+ this->emitInitElemSint8(I, SL);
+ } else if (CharWidth == 2) {
+ this->emitConstUint16(CodeUnit, SL);
+ this->emitInitElemUint16(I, SL);
+ } else if (CharWidth == 4) {
+ this->emitConstUint32(CodeUnit, SL);
+ this->emitInitElemUint32(I, SL);
+ } else {
+ llvm_unreachable("unsupported character width");
+ }
+ }
+ return true;
}
assert(false && "Unknown expression for array initialization");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D137488.475697.patch
Type: text/x-patch
Size: 3867 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20221116/03e7dd28/attachment-0001.bin>
More information about the cfe-commits
mailing list