[PATCH] D105759: [WIP] Implement P2361 Unevaluated string literals
Aaron Ballman via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 2 07:48:20 PDT 2021
aaron.ballman added inline comments.
================
Comment at: clang/include/clang/AST/Expr.h:1839-1840
StringRef getString() const {
- assert(getCharByteWidth() == 1 &&
- "This function is used in places that assume strings use char");
+ assert(isUnevaluated() ||
+ getCharByteWidth() == 1 &&
+ "This function is used in places that assume strings use char");
----------------
This should silence some diagnostics about mixed && and || in the same expression.
================
Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:248
+def err_unevaluated_string_udl : Error<
+ "an unevaluated string literal cannot be a user defined literal">;
+def err_unevaluated_string_invalid_escape_sequence : Error<
----------------
================
Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:250
+def err_unevaluated_string_invalid_escape_sequence : Error<
+ "Invalid escape sequence '%0' in an unevaluated string literal">;
def err_string_concat_mixed_suffix : Error<
----------------
================
Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:59-60
+
+def err_expected_unevaluated_string : Error<
+ "expected a string literal!">;
+
----------------
No need for this diagnostic, you can use `err_expected_string_literal` from DiagnosticCommonKinds.td instead.
================
Comment at: clang/include/clang/Lex/LiteralSupport.h:220
tok::TokenKind Kind;
+ SmallString<512> UnevaluatedBuf;
SmallString<512> ResultBuf;
----------------
This seems to be unused.
================
Comment at: clang/include/clang/Lex/LiteralSupport.h:235
MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown),
ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
init(StringToks);
----------------
Alternatively, you could use an in-class initializer and drop the changes to both ctor init lists.
================
Comment at: clang/lib/AST/Expr.cpp:1076
+
unsigned ByteLength = Str.size();
+ unsigned Length = ByteLength;
----------------
Basically unused and is shadowed by a declaration below (on line 1087).
================
Comment at: clang/lib/AST/Expr.cpp:1157-1158
switch (getKind()) {
+ case Unevaluated:
+ break; // no prefic
case Ascii: break; // no prefix.
----------------
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:95-96
+ case '?':
+ case 'n':
+ case 't':
+ return true;
----------------
Do you intend to miss a bunch of escapes like `\'` and `\r` (etc)?
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:242
+ diag::err_unevaluated_string_invalid_escape_sequence)
+ << std::string(1, EscapeBegin[1]);
+ }
----------------
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:1539
- // Implement Translation Phase #6: concatenation of string literals
+ // Determines the kind of string from the prefix
+ Kind = tok::string_literal;
----------------
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:1541
+ Kind = tok::string_literal;
+ for (const auto &Tok : StringToks) {
+ // Unevaluated string literals can never have a prefix
----------------
This means we're looping over (almost) all the string tokens three times -- once here, once below on line 1562, and again on 1605.
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:1542
+ for (const auto &Tok : StringToks) {
+ // Unevaluated string literals can never have a prefix
+ if (Unevaluated && Tok.getKind() != tok::string_literal) {
----------------
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:1545
+ if (Diags)
+ Diags->Report(Tok.getLocation(), diag::err_unevaluated_string_prefix);
+ hadError = true;
----------------
This diagnostic might be somewhat odd for Pascal strings because those sort of have a prefix but it's not really the kind of prefix we're talking about. I don't know of a better way to word the diagnostic though. If you think of a way to improve it, then yay, but otherwise, I think it's fine as-is.
================
Comment at: clang/lib/Lex/LiteralSupport.cpp:1963
+ FullSourceLoc(Tok.getLocation(), SM), CharByteWidth * 8,
+ Diags, Features, false);
--ByteNo;
----------------
================
Comment at: clang/lib/Parse/ParseDecl.cpp:422-423
- ExprResult ArgExpr(
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
+ ExprResult ArgExpr(Actions.CorrectDelayedTyposInExpr(
+ ParseAttributeArgAsUnevaluatedLiteralOrExpression(AttrKind)));
if (ArgExpr.isInvalid()) {
----------------
Hmmm, I'm not certain about these changes.
For some attributes, the standard currently requires accepting any kind of string literal (like `[[deprecated]]` https://eel.is/c++draft/dcl.attr.deprecated#1). P2361 is proposing to change that, but it's not yet accepted by WG21 (let alone WG14). So giving errors in those cases is a bit of a hard sell -- I think warnings would be a bit more reasonable.
But for other attributes (like `annotate`), it's a bit less clear whether we should *prevent* literal prefixes because the attribute can be used to have runtime impacts (for example, I can imagine someone using `annotate` to emit the string literal bytes into the resulting binary). In some cases, I think it's very reasonable (e.g., `diagnose_if` should behave the same as `deprecated` and `nodiscard` because those are purely about generating diagnostics at compile time).
I kind of wonder whether we're going to want to tablegenerate whether the argument needs to be parsed as unevaluated or not on an attribute-by-attribute basis.
================
Comment at: clang/lib/Parse/ParseDecl.cpp:455-456
+ ParsedAttr::Kind Kind) {
+ if (isTokenStringLiteral() && (Kind == ParsedAttr::AT_Deprecated ||
+ Kind == ParsedAttr::AT_WarnUnusedResult)) {
+ ExprResult Result = ParseUnevaluatedStringLiteralExpression();
----------------
I don't think this is the right way to go about this, but the comments were left above.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D105759/new/
https://reviews.llvm.org/D105759
More information about the cfe-commits
mailing list