-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[clang] Introduce "binary" StringLiteral for #embed data #127629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
700ec6f
97c1c04
600c7bb
c07dc09
8ff7d03
84f745e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1756,7 +1756,14 @@ enum class StringLiteralKind { | |
UTF8, | ||
UTF16, | ||
UTF32, | ||
Unevaluated | ||
Unevaluated, | ||
// Binary kind of string literal is used for the data coming via #embed | ||
// directive. File's binary contents is transformed to a special kind of | ||
// string literal that in some cases may be used directly as an initializer | ||
// and some features of classic string literals are not applicable to this | ||
// kind of a string literal, for example finding a particular byte's source | ||
// location for better diagnosing. | ||
Binary | ||
}; | ||
|
||
/// StringLiteral - This represents a string literal expression, e.g. "foo" | ||
|
@@ -1888,6 +1895,8 @@ class StringLiteral final | |
int64_t getCodeUnitS(size_t I, uint64_t BitWidth) const { | ||
int64_t V = getCodeUnit(I); | ||
if (isOrdinary() || isWide()) { | ||
// Ordinary and wide string literals have types that can be signed. | ||
// It is important for checking C23 constexpr initializers. | ||
unsigned Width = getCharByteWidth() * BitWidth; | ||
llvm::APInt AInt(Width, (uint64_t)V); | ||
V = AInt.getSExtValue(); | ||
|
@@ -5029,9 +5038,9 @@ class EmbedExpr final : public Expr { | |
assert(EExpr && CurOffset != ULLONG_MAX && | ||
"trying to dereference an invalid iterator"); | ||
IntegerLiteral *N = EExpr->FakeChildNode; | ||
StringRef DataRef = EExpr->Data->BinaryData->getBytes(); | ||
N->setValue(*EExpr->Ctx, | ||
llvm::APInt(N->getValue().getBitWidth(), DataRef[CurOffset], | ||
llvm::APInt(N->getValue().getBitWidth(), | ||
EExpr->Data->BinaryData->getCodeUnit(CurOffset), | ||
Comment on lines
+5042
to
+5043
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you change that line (and nothing else) does it still works? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wish it did. This particular line helps for generic case of |
||
N->getType()->isSignedIntegerType())); | ||
// We want to return a reference to the fake child node in the | ||
// EmbedExpr, not the local variable N. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// RUN: %clang_cc1 %s -fsyntax-only --embed-dir=%S/Inputs -verify -std=c23 | ||
|
||
static constexpr unsigned char data[] = { | ||
#embed "big_char.txt" | ||
}; | ||
|
||
static constexpr char data1[] = { | ||
#embed "big_char.txt" // expected-error {{constexpr initializer evaluates to 255 which is not exactly representable in type 'const char'}} | ||
}; | ||
|
||
static constexpr int data2[] = { | ||
#embed "big_char.txt" | ||
}; | ||
|
||
static constexpr unsigned data3[] = { | ||
#embed "big_char.txt" suffix(, -1) // expected-error {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned int'}} | ||
}; | ||
|
||
static constexpr int data4[] = { | ||
#embed "big_char.txt" suffix(, -1) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment explaining this is for embed?
I'm sorry it took me a while to understand how this patch works.
(The reason is that this allows us to not "cast" to char in
getCodeUnitS()
- which is only used in C23 mode)Maybe also add a comment in
getCodeUnitS
and/orCheckC23ConstexprInitStringLiteral
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some comments in 8ff7d03 . Do you think it turned out helpful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, Thanks!