[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG44eee659f1c5: [AST] Print NTTP args as string-literals when possible (authored by lichray). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -80,3 +80,34 @@ varDecl(hasType(qualType().bind("id"))), "const f *", Clean)); } + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; +
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 412289. lichray added a comment. Herald added a project: All. - Add a trigraph test case Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -80,3 +80,34 @@ varDecl(hasType(qualType().bind("id"))), "const f *", Clean)); } + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255,
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. Aside from a testing nit, this LGTM! Comment at: clang/include/clang/Basic/CharInfo.h:199-200 +return "\\t"; + case '\v': +return "\\v"; + } lichray wrote: > aaron.ballman wrote: > > lichray wrote: > > > aaron.ballman wrote: > > > > We're also missing `\?` right? > > > `?` does not seem to need `"escaping?"` > > It's the only simple escape sequence we're not handling here: > > http://eel.is/c++draft/lex.literal#nt:simple-escape-sequence-char > > > > (You need to escape `?` thanks to trigraphs. Consider a string literal like > > `"This does what now??!"`.) > > It's the only simple escape sequence we're not handling here: > > http://eel.is/c++draft/lex.literal#nt:simple-escape-sequence-char > > > > (You need to escape `?` thanks to trigraphs. Consider a string literal like > > `"This does what now??!"`.) > > Hmm, I think we're safe here > ``` > ~/devel/llvm-project> ./build/bin/clang++ -fsyntax-only -std=c++14 c.cc > c.cc:1:50: warning: trigraph converted to '|' character [-Wtrigraphs] > void foo() { char const s[] = "This does what now??!"; } > ^ > 1 warning generated. > ~/devel/llvm-project> ./build/bin/clang++ -fsyntax-only -std=c++20 c.cc > c.cc:1:50: warning: trigraph ignored [-Wtrigraphs] > void foo() { char const s[] = "This does what now??!"; } > ^ > 1 warning generated. > ``` > For these reasons, > 1. I don't want users to copy diagnosis messages, paste them into a program, > and get something different. This has been prevented by the warnings. > 2. We support trigraph up to C++14, way behind the version (C++20) we can use > string literals in NTTP. So it should be mostly fine. > 3. In C++14 we can use the characters in NTTP, but that one has a different > diagnosis: > > ``` > template class ASCII {}; > > void Foo(ASCII<'?'>); > void Foo(ASCII<'??!'>); > void test_pascal() { > ASCII<'!'> a; > Foo(a); > } > ``` > > ``` > c.cc:4:17: warning: trigraph converted to '|' character [-Wtrigraphs] > void Foo(ASCII<'??!'>); > ^ > c.cc:7:3: error: no matching function for call to 'Foo' > Foo(a); > ^~~ > c.cc:3:6: note: candidate function not viable: no known conversion from > 'ASCII<'!' aka 33>' to 'ASCII<'?' aka 63>' for 1st argument > void Foo(ASCII<'?'>); > ^ > c.cc:4:6: note: candidate function not viable: no known conversion from > 'ASCII<'!' aka 33>' to 'ASCII<'|' aka 124>' for 1st argument > void Foo(ASCII<'??!'>); > ^ > 1 warning and 1 error generated. > ``` > Looks nice to me even if we don't escape. Okay, that sounds reasonable to me, thank you for checking! Can you add a trigraph test case so that it's clear we purposefully don't escape the `\?` (with some comment to that effect)? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray marked 4 inline comments as done. lichray added inline comments. Comment at: clang/include/clang/Basic/CharInfo.h:199-200 +return "\\t"; + case '\v': +return "\\v"; + } aaron.ballman wrote: > lichray wrote: > > aaron.ballman wrote: > > > We're also missing `\?` right? > > `?` does not seem to need `"escaping?"` > It's the only simple escape sequence we're not handling here: > http://eel.is/c++draft/lex.literal#nt:simple-escape-sequence-char > > (You need to escape `?` thanks to trigraphs. Consider a string literal like > `"This does what now??!"`.) > It's the only simple escape sequence we're not handling here: > http://eel.is/c++draft/lex.literal#nt:simple-escape-sequence-char > > (You need to escape `?` thanks to trigraphs. Consider a string literal like > `"This does what now??!"`.) Hmm, I think we're safe here ``` ~/devel/llvm-project> ./build/bin/clang++ -fsyntax-only -std=c++14 c.cc c.cc:1:50: warning: trigraph converted to '|' character [-Wtrigraphs] void foo() { char const s[] = "This does what now??!"; } ^ 1 warning generated. ~/devel/llvm-project> ./build/bin/clang++ -fsyntax-only -std=c++20 c.cc c.cc:1:50: warning: trigraph ignored [-Wtrigraphs] void foo() { char const s[] = "This does what now??!"; } ^ 1 warning generated. ``` For these reasons, 1. I don't want users to copy diagnosis messages, paste them into a program, and get something different. This has been prevented by the warnings. 2. We support trigraph up to C++14, way behind the version (C++20) we can use string literals in NTTP. So it should be mostly fine. 3. In C++14 we can use the characters in NTTP, but that one has a different diagnosis: ``` template class ASCII {}; void Foo(ASCII<'?'>); void Foo(ASCII<'??!'>); void test_pascal() { ASCII<'!'> a; Foo(a); } ``` ``` c.cc:4:17: warning: trigraph converted to '|' character [-Wtrigraphs] void Foo(ASCII<'??!'>); ^ c.cc:7:3: error: no matching function for call to 'Foo' Foo(a); ^~~ c.cc:3:6: note: candidate function not viable: no known conversion from 'ASCII<'!' aka 33>' to 'ASCII<'?' aka 63>' for 1st argument void Foo(ASCII<'?'>); ^ c.cc:4:6: note: candidate function not viable: no known conversion from 'ASCII<'!' aka 33>' to 'ASCII<'|' aka 124>' for 1st argument void Foo(ASCII<'??!'>); ^ 1 warning and 1 error generated. ``` Looks nice to me even if we don't escape. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
aaron.ballman added inline comments. Comment at: clang/include/clang/Basic/CharInfo.h:199-200 +return "\\t"; + case '\v': +return "\\v"; + } lichray wrote: > aaron.ballman wrote: > > We're also missing `\?` right? > `?` does not seem to need `"escaping?"` It's the only simple escape sequence we're not handling here: http://eel.is/c++draft/lex.literal#nt:simple-escape-sequence-char (You need to escape `?` thanks to trigraphs. Consider a string literal like `"This does what now??!"`.) Comment at: clang/lib/AST/APValue.cpp:676-683 + if (Ty->isWideCharType()) +Out << 'L'; + else if (Ty->isChar8Type()) +Out << "u8"; + else if (Ty->isChar16Type()) +Out << 'u'; + else if (Ty->isChar32Type()) lichray wrote: > aaron.ballman wrote: > > Not quite the same thing, but do we have to worry about printing pascal > > strings here? (e.g., do we need to do `"\pwhatever"`? > This is in `APValue` where we lost the context of StringLiteral; nothing > tells me that this array was created from a Pascal string literal. Unless you > want to do some heuristics, like printing `"\pthis"` when seens an `unsigned > char[6]` where the first element = 4 (last element = 0 is checked at the > beginning). Whelp, that explains that. I think the current behavior is fine (I have to imagine the number of people still using Pascal strings is as high as four or five these days). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray marked 3 inline comments as done. lichray added inline comments. Comment at: clang/include/clang/Basic/CharInfo.h:199-200 +return "\\t"; + case '\v': +return "\\v"; + } aaron.ballman wrote: > We're also missing `\?` right? `?` does not seem to need `"escaping?"` Comment at: clang/lib/AST/APValue.cpp:676-683 + if (Ty->isWideCharType()) +Out << 'L'; + else if (Ty->isChar8Type()) +Out << "u8"; + else if (Ty->isChar16Type()) +Out << 'u'; + else if (Ty->isChar32Type()) aaron.ballman wrote: > Not quite the same thing, but do we have to worry about printing pascal > strings here? (e.g., do we need to do `"\pwhatever"`? This is in `APValue` where we lost the context of StringLiteral; nothing tells me that this array was created from a Pascal string literal. Unless you want to do some heuristics, like printing `"\pthis"` when seens an `unsigned char[6]` where the first element = 4 (last element = 0 is checked at the beginning). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 411856. lichray added a comment. - Revert some auto's Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -80,3 +80,34 @@ varDecl(hasType(qualType().bind("id"))), "const f *", Clean)); } + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
aaron.ballman added inline comments. Comment at: clang/include/clang/Basic/CharInfo.h:199-200 +return "\\t"; + case '\v': +return "\\v"; + } We're also missing `\?` right? Comment at: clang/lib/AST/APValue.cpp:658 + for (auto : Inits) { +auto Char64 = Val.getInt().getExtValue(); +if (!isASCII(Char64)) Comment at: clang/lib/AST/APValue.cpp:663 +// The diagnostic message is 'quoted' +auto Escaped = escapeCStyle(Ch); +if (Escaped.empty()) { Comment at: clang/lib/AST/APValue.cpp:676-683 + if (Ty->isWideCharType()) +Out << 'L'; + else if (Ty->isChar8Type()) +Out << "u8"; + else if (Ty->isChar16Type()) +Out << 'u'; + else if (Ty->isChar32Type()) Not quite the same thing, but do we have to worry about printing pascal strings here? (e.g., do we need to do `"\pwhatever"`? Comment at: clang/lib/AST/Expr.cpp:1137 +uint32_t Char = getCodeUnit(I); +auto Escaped = escapeCStyle(Char); +if (Escaped.empty()) { Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 408137. lichray added a comment. Rerun pre-merge checks Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -80,3 +80,34 @@ varDecl(hasType(qualType().bind("id"))), "const f *", Clean)); } + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> +
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 407464. lichray added a comment. Rebased Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -80,3 +80,34 @@ varDecl(hasType(qualType().bind("id"))), "const f *", Clean)); } + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new ASCII; + //
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 403760. lichray added a comment. Rebased Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -80,3 +80,34 @@ varDecl(hasType(qualType().bind("id"))), "const f *", Clean)); } + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new ASCII; + //
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray added a comment. Ping. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray marked an inline comment as done. lichray added a comment. Restricted the ellipsis only to diagnosis. Type comparison now shows full initializers, which could be made smarter next time. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 402180. lichray added a comment. - Flip the default and set EntireContentsOfLargeArray off only in diagnosis Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/ASTDiagnostic.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateBase.cpp clang/lib/Sema/Sema.cpp clang/test/SemaCXX/cxx2a-nttp-printing.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -62,4 +62,35 @@ ASSERT_TRUE(PrintedTypeMatches( Code, {}, Matcher, "const N::Type &", [](PrintingPolicy ) { Policy.FullyQualifiedName = true; })); -} \ No newline at end of file +} + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}> + new ASCII<"print more characters as string, no uplimit">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17,
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
rsmith added inline comments. Comment at: clang/include/clang/AST/PrettyPrinter.h:288 + /// template parameters, no matter how many elements there are. + unsigned EntireContentsOfLargeArray : 1; + lichray wrote: > rsmith wrote: > > It looks like nothing is setting this to `true` yet, so that part of this > > patch seems untested. The places I think we want to set this to `true` are: > > > > 1) When forming types in a diagnostic, if we have two types that differ > > only in the contents of large arrays. That's checked in here: > > https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTDiagnostic.cpp#L259 > > > > I think what we'd want is: if we still have a collision between type > > names after comparing the canonical strings > > (https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTDiagnostic.cpp#L291), > > then set this policy to `true` for the rest of the function, and recompute > > `S` and `CanS`. > > > > This should be detectable in a case such as: > > > > ``` > > void f(X<{"some very long string that differs here: x"}>); > > void g() { > > f(X<{"some very long string that differs here: y"}>()); > > } > > ``` > > > > ... where the diagnostic should include the whole string, not elide the > > differing portion at the end. > > > > 2) In the `-ast-print` output: when pretty-printing as code, we want to > > produce correct, non-elided template arguments. I think this will require > > passing a printing policy into `TemplateParamObjectDecl::printAsInit` and > > `::printAsExpr` > > (https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/DeclTemplate.cpp#L1509). > > This should be detectable in the output of `-ast-print`, where we do not > > want to elide any part of template arguments. Perhaps `StmtPrinter` and > > `DeclPrinter` should enable this `PrintingPolicy` flag? > > > > 3) When generating debug information: > > https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/CGDebugInfo.cpp#L230 > > > > It's generally important that debug information has complete type names. > Added `PrintingPolicy` parameter to `TemplateParamObjectDecl::printAsInit` > and `printAsExpr`, fixed the implementation, and added tests for the effect > of the new `EntireContentsOfLargeArray` bit. > > Whether how diagnosis, codegen, and higher-level printers should make use of > them, I think they're outside the scope of this patch. Generally I agree, we don't need to fix all the places that should be setting this new flag as part of the same patch, but I think at least `-ast-print` should be fixed here, given how obviously broken it currently is. That would also remove the need to add a unit test for the new flag. Comment at: clang/test/SemaTemplate/temp_arg_string_printing.cpp:1 +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + Please use something like diagnostics to test that elision happens, rather than `-ast-print`, because `-ast-print` aims to produce valid C++ code that has the same meaning as the input -- this is a canonical example of a case that should *not* elide large array contents. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 399433. lichray added a comment. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/TemplateBase.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -62,4 +62,35 @@ ASSERT_TRUE(PrintedTypeMatches( Code, {}, Matcher, "const N::Type &", [](PrintingPolicy ) { Policy.FullyQualifiedName = true; })); -} \ No newline at end of file +} + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more than[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"}> + new ASCII<"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 399415. lichray added a comment. - clang-format Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/TemplateBase.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -62,4 +62,35 @@ ASSERT_TRUE(PrintedTypeMatches( Code, {}, Matcher, "const N::Type &", [](PrintingPolicy ) { Policy.FullyQualifiedName = true; })); -} \ No newline at end of file +} + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more than[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"}> + new ASCII<"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 396408. lichray added a comment. - Put tests in TypePrinterTest.cpp Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/TemplateBase.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/TypePrinterTest.cpp Index: clang/unittests/AST/TypePrinterTest.cpp === --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -62,4 +62,35 @@ ASSERT_TRUE(PrintedTypeMatches( Code, {}, Matcher, "const N::Type &", [](PrintingPolicy ) { Policy.FullyQualifiedName = true; })); -} \ No newline at end of file +} + +TEST(TypePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl( + hasName("ASCII"), has(cxxConstructorDecl( +isMoveConstructor(), +has(parmVarDecl(hasType(qualType().bind("id"))); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is [...]"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedTypeMatches( + Code, {"-std=c++20"}, Matcher, + R"(ASCII<{"this nontype template argument is too long to print"}> &&)", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more than[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"}> + new ASCII<"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}:
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray marked 2 inline comments as done. lichray added inline comments. Comment at: clang/include/clang/AST/PrettyPrinter.h:288 + /// template parameters, no matter how many elements there are. + unsigned EntireContentsOfLargeArray : 1; + rsmith wrote: > It looks like nothing is setting this to `true` yet, so that part of this > patch seems untested. The places I think we want to set this to `true` are: > > 1) When forming types in a diagnostic, if we have two types that differ only > in the contents of large arrays. That's checked in here: > https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTDiagnostic.cpp#L259 > > I think what we'd want is: if we still have a collision between type > names after comparing the canonical strings > (https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTDiagnostic.cpp#L291), > then set this policy to `true` for the rest of the function, and recompute > `S` and `CanS`. > > This should be detectable in a case such as: > > ``` > void f(X<{"some very long string that differs here: x"}>); > void g() { > f(X<{"some very long string that differs here: y"}>()); > } > ``` > > ... where the diagnostic should include the whole string, not elide the > differing portion at the end. > > 2) In the `-ast-print` output: when pretty-printing as code, we want to > produce correct, non-elided template arguments. I think this will require > passing a printing policy into `TemplateParamObjectDecl::printAsInit` and > `::printAsExpr` > (https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/DeclTemplate.cpp#L1509). > This should be detectable in the output of `-ast-print`, where we do not > want to elide any part of template arguments. Perhaps `StmtPrinter` and > `DeclPrinter` should enable this `PrintingPolicy` flag? > > 3) When generating debug information: > https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/CGDebugInfo.cpp#L230 > > It's generally important that debug information has complete type names. Added `PrintingPolicy` parameter to `TemplateParamObjectDecl::printAsInit` and `printAsExpr`, fixed the implementation, and added tests for the effect of the new `EntireContentsOfLargeArray` bit. Whether how diagnosis, codegen, and higher-level printers should make use of them, I think they're outside the scope of this patch. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 396187. lichray marked an inline comment as done. lichray added a comment. Herald added a subscriber: mgorny. - Fix categorizing int64_t chars of negative values - More ArrayRef - Fix and test the EntireContentsOfLargeArray bit Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/DeclTemplate.h clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/DeclTemplate.cpp clang/lib/AST/Expr.cpp clang/lib/AST/TemplateBase.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp clang/unittests/AST/CMakeLists.txt clang/unittests/AST/ElidePrinterTest.cpp Index: clang/unittests/AST/ElidePrinterTest.cpp === --- /dev/null +++ clang/unittests/AST/ElidePrinterTest.cpp @@ -0,0 +1,74 @@ +//===- unittests/AST/ElidePrinterTest.cpp --- Elide printer output tests --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file contains tests for shortening NTTP in AST printer. +// +//===--===// + +#include "ASTPrint.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/SmallString.h" +#include "gtest/gtest.h" + +using namespace clang; +using namespace ast_matchers; +using namespace tooling; + +namespace { + +void PrintDecl(raw_ostream , const ASTContext *Context, const Decl *D, + PrintingPolicyAdjuster PolicyModifier) { + PrintingPolicy Policy = Context->getPrintingPolicy(); + Policy.Indentation = 0; + if (PolicyModifier) +PolicyModifier(Policy); + D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false); +} + +::testing::AssertionResult +PrintedDeclMatches(StringRef Code, const std::vector , + const DeclarationMatcher , + StringRef ExpectedPrinted, + PrintingPolicyAdjuster PolicyModifier) { + return PrintedNodeMatches(Code, Args, NodeMatch, ExpectedPrinted, "", + PrintDecl, PolicyModifier); +} + +} // unnamed namespace + +TEST(ElidePrinter, TemplateIdWithNTTP) { + constexpr char Code[] = R"cpp( +template +struct Str { + constexpr Str(char const ()[N]) { __builtin_memcpy(value, s, N); } + char value[N]; +}; +template class ASCII {}; + +ASCII<"this nontype template argument is too long to print"> x; + )cpp"; + auto Matcher = classTemplateSpecializationDecl(hasName("ASCII")).bind("id"); + + ASSERT_TRUE(PrintedDeclMatches( + Code, {"-std=c++20"}, Matcher, + R"(template<> class ASCII<{"this nontype template argument is [...]"}> { +})", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = false; + })); + + ASSERT_TRUE(PrintedDeclMatches( + Code, {"-std=c++20"}, Matcher, + R"(template<> class ASCII<{"this nontype template argument is too long to print"}> { +})", + [](PrintingPolicy ) { +Policy.EntireContentsOfLargeArray = true; + })); +} Index: clang/unittests/AST/CMakeLists.txt === --- clang/unittests/AST/CMakeLists.txt +++ clang/unittests/AST/CMakeLists.txt @@ -22,6 +22,7 @@ DataCollectionTest.cpp DeclPrinterTest.cpp DeclTest.cpp + ElidePrinterTest.cpp EvaluateAsRValueTest.cpp ExternalASTSourceTest.cpp NamedDeclPrinterTest.cpp Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
rsmith added inline comments. Comment at: clang/include/clang/AST/PrettyPrinter.h:288 + /// template parameters, no matter how many elements there are. + unsigned EntireContentsOfLargeArray : 1; + It looks like nothing is setting this to `true` yet, so that part of this patch seems untested. The places I think we want to set this to `true` are: 1) When forming types in a diagnostic, if we have two types that differ only in the contents of large arrays. That's checked in here: https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTDiagnostic.cpp#L259 I think what we'd want is: if we still have a collision between type names after comparing the canonical strings (https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTDiagnostic.cpp#L291), then set this policy to `true` for the rest of the function, and recompute `S` and `CanS`. This should be detectable in a case such as: ``` void f(X<{"some very long string that differs here: x"}>); void g() { f(X<{"some very long string that differs here: y"}>()); } ``` ... where the diagnostic should include the whole string, not elide the differing portion at the end. 2) In the `-ast-print` output: when pretty-printing as code, we want to produce correct, non-elided template arguments. I think this will require passing a printing policy into `TemplateParamObjectDecl::printAsInit` and `::printAsExpr` (https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/DeclTemplate.cpp#L1509). This should be detectable in the output of `-ast-print`, where we do not want to elide any part of template arguments. Perhaps `StmtPrinter` and `DeclPrinter` should enable this `PrintingPolicy` flag? 3) When generating debug information: https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/CGDebugInfo.cpp#L230 It's generally important that debug information has complete type names. Comment at: clang/include/clang/Basic/CharInfo.h:50 LLVM_READNONE inline bool isASCII(uint32_t c) { return c <= 127; } +LLVM_READNONE inline bool isASCII(int64_t c) { return c <= 127; } I think this should also return false for negative values. Comment at: clang/lib/AST/APValue.cpp:630-631 +const PrintingPolicy , +const ArrayType *ATy, const APValue *Data, +size_t Size) { + if (Size == 0) Consider passing in an `ArrayRef` here instead of forming one below. Comment at: clang/lib/AST/APValue.cpp:654 + + for (auto : ArrayRef(Data, Size)) { +auto Char64 = Val.getInt().getExtValue(); I think `ArrayRef` and `ArrayRef` are effectively the same thing (you'd need `MutableArrayRef` to remove the implied `const`), so you should be able to just use `ArrayRef` here. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray added a comment. @rsmith Ping. I'm all on you :) You are almost the only one designed these files. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray added a comment. Ping. Ready to review again. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 391833. lichray marked an inline comment as done. lichray added a comment. - Switch to `llvm::SmallString` - Refactor code that prints C-style builtin escape sequences - Stop printing strings with embedded NULs in NTTP types - Add an `EntireContentsOfLargeArray` pretty-print policy Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/CharInfo.h clang/lib/AST/APValue.cpp clang/lib/AST/Expr.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void not_string() { + // CHECK{LITERAL}: ASCII<{{9, -1, 42}}> + new ASCII<(int[]){9, -1, 42}>; + // CHECK{LITERAL}: ASCII<{{3.14e+00, 0.00e+00, 4.20e+01}}> + new ASCII<(double[]){3.14, 0., 42.}>; +} + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}> + new ASCII<"escape\\\t\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more than[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"}> + new ASCII<"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, ...}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print even more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print many characters no more than[...]"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII; +} + +void utf8() { + // CHECK{LITERAL}: ASCII<{u8""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{229,
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray marked 5 inline comments as done. lichray added inline comments. Comment at: clang/lib/AST/APValue.cpp:637-639 + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; lichray wrote: > lichray wrote: > > rsmith wrote: > > > lichray wrote: > > > > rsmith wrote: > > > > > We should drop all trailing zeroes here, because array initialization > > > > > from a string literal will reconstruct them. > > > > Are you sure? `MyType<{""}>` and `MyType<{"\0\0\0"}>` are different > > > > types. > > > That's a separate bug. `APValue`'s printing is not intended to identify > > > the type of the result, only to identify the value in the case where we > > > already know the type. Eg, we don't print a type suffix on a > > > pretty-printed integer value. For the specific case of template > > > parameters, it's the responsibility of the template argument printing > > > code to uniquely identify the template argument. > > > > > > When a template parameter has a deduced class type, we should include > > > that type in the printed output in order to uniquely identify the > > > specialization, but we don't, because that's not been implemented yet. > > > When that's fixed, we should print those cases as `MyType > > 1>{""}>` and `MyType{""}>`. This is necessary anyway, > > > because we can't in general assume that the resulting value is enough to > > > indicate what type CTAD will have selected. > > > > > > We already handle this properly in some cases, but see this FIXMEs: > > > https://github.com/llvm/llvm-project/blob/6c2be3015e07f25912b8cd5b75214c532f568638/clang/lib/AST/TemplateBase.cpp#L433 > > > > > > See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that > > > the non-struct enum case is handled properly but the enum-in-struct case > > > is not). > > > That's a separate bug. [...] > > > > > > When a template parameter has a deduced class type, we should include > > > that type in the printed output in order to uniquely identify the > > > specialization, but we don't, because that's not been implemented yet. > > > When that's fixed, we should print those cases as `MyType > > 1>{""}>` and `MyType{""}>`. This is necessary anyway, > > > because we can't in general assume that the resulting value is enough to > > > indicate what type CTAD will have selected. > > > > > > > But it looks like a feature rather than a bug? String literals provided > > both type and value to emphasis a structural type's value for equivalence > > comparison. The reason of why `MyType<{""}>` and `MyType<"\0\0\0">` are > > different looks more obvious to me. > > > > > See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that > > > the non-struct enum case is handled properly but the enum-in-struct case > > > is not). > > > > I'm fine if a specific NTTP, `A`, is treated differently from `auto`. But > > the last case is similar to this https://godbolt.org/z/YcscTrchM Which I > > thought about printing something like `Y<{(E[]){97, 98}}>` :) > That discussion looks OT... For now, not shrinking `"\0\0\0"` down to `""` > follows the existing logic, i.e., we are printing `{0, 0, 0}` even though > it's an array. > Nvm, I did not realize that null characters cannot be safely escaped with just `\0` without looking at the characters that follow it. Dropping that case and fallback to print the integer sequence. Comment at: clang/lib/AST/APValue.cpp:645 + + // Better than printing a two-digit sequence of 10 integers. + StringRef Ellipsis; rsmith wrote: > ...except that some callers want output that uniquely identifies the template > argument, and moreover some callers want output that is valid C++ code that > produces the same template-id. > > It'd be better to do this behind a `PrintingPolicy` flag that the diagnostics > engine sets. But we'd want to turn that flag off during template type diffing. Added `Policy.EntireContentsOfLargeArray`. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray added inline comments. Comment at: clang/lib/AST/APValue.cpp:637-639 + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; lichray wrote: > rsmith wrote: > > lichray wrote: > > > rsmith wrote: > > > > We should drop all trailing zeroes here, because array initialization > > > > from a string literal will reconstruct them. > > > Are you sure? `MyType<{""}>` and `MyType<{"\0\0\0"}>` are different types. > > That's a separate bug. `APValue`'s printing is not intended to identify the > > type of the result, only to identify the value in the case where we already > > know the type. Eg, we don't print a type suffix on a pretty-printed integer > > value. For the specific case of template parameters, it's the > > responsibility of the template argument printing code to uniquely identify > > the template argument. > > > > When a template parameter has a deduced class type, we should include that > > type in the printed output in order to uniquely identify the > > specialization, but we don't, because that's not been implemented yet. When > > that's fixed, we should print those cases as `MyType{""}>` and > > `MyType{""}>`. This is necessary anyway, because we can't in > > general assume that the resulting value is enough to indicate what type > > CTAD will have selected. > > > > We already handle this properly in some cases, but see this FIXMEs: > > https://github.com/llvm/llvm-project/blob/6c2be3015e07f25912b8cd5b75214c532f568638/clang/lib/AST/TemplateBase.cpp#L433 > > > > See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that > > the non-struct enum case is handled properly but the enum-in-struct case is > > not). > > That's a separate bug. [...] > > > > When a template parameter has a deduced class type, we should include that > > type in the printed output in order to uniquely identify the > > specialization, but we don't, because that's not been implemented yet. When > > that's fixed, we should print those cases as `MyType{""}>` and > > `MyType{""}>`. This is necessary anyway, because we can't in > > general assume that the resulting value is enough to indicate what type > > CTAD will have selected. > > > > But it looks like a feature rather than a bug? String literals provided both > type and value to emphasis a structural type's value for equivalence > comparison. The reason of why `MyType<{""}>` and `MyType<"\0\0\0">` are > different looks more obvious to me. > > > See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that > > the non-struct enum case is handled properly but the enum-in-struct case is > > not). > > I'm fine if a specific NTTP, `A`, is treated differently from `auto`. But the > last case is similar to this https://godbolt.org/z/YcscTrchM Which I thought > about printing something like `Y<{(E[]){97, 98}}>` :) That discussion looks OT... For now, not shrinking `"\0\0\0"` down to `""` follows the existing logic, i.e., we are printing `{0, 0, 0}` even though it's an array. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray added inline comments. Comment at: clang/lib/AST/APValue.cpp:637-639 + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; rsmith wrote: > lichray wrote: > > rsmith wrote: > > > We should drop all trailing zeroes here, because array initialization > > > from a string literal will reconstruct them. > > Are you sure? `MyType<{""}>` and `MyType<{"\0\0\0"}>` are different types. > That's a separate bug. `APValue`'s printing is not intended to identify the > type of the result, only to identify the value in the case where we already > know the type. Eg, we don't print a type suffix on a pretty-printed integer > value. For the specific case of template parameters, it's the responsibility > of the template argument printing code to uniquely identify the template > argument. > > When a template parameter has a deduced class type, we should include that > type in the printed output in order to uniquely identify the specialization, > but we don't, because that's not been implemented yet. When that's fixed, we > should print those cases as `MyType{""}>` and `MyType 4>{""}>`. This is necessary anyway, because we can't in general assume that > the resulting value is enough to indicate what type CTAD will have selected. > > We already handle this properly in some cases, but see this FIXMEs: > https://github.com/llvm/llvm-project/blob/6c2be3015e07f25912b8cd5b75214c532f568638/clang/lib/AST/TemplateBase.cpp#L433 > > See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that the > non-struct enum case is handled properly but the enum-in-struct case is not). > That's a separate bug. [...] > > When a template parameter has a deduced class type, we should include that > type in the printed output in order to uniquely identify the specialization, > but we don't, because that's not been implemented yet. When that's fixed, we > should print those cases as `MyType{""}>` and `MyType 4>{""}>`. This is necessary anyway, because we can't in general assume that > the resulting value is enough to indicate what type CTAD will have selected. > But it looks like a feature rather than a bug? String literals provided both type and value to emphasis a structural type's value for equivalence comparison. The reason of why `MyType<{""}>` and `MyType<"\0\0\0">` are different looks more obvious to me. > See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that the > non-struct enum case is handled properly but the enum-in-struct case is not). I'm fine if a specific NTTP, `A`, is treated differently from `auto`. But the last case is similar to this https://godbolt.org/z/YcscTrchM Which I thought about printing something like `Y<{(E[]){97, 98}}>` :) Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
rsmith added inline comments. Comment at: clang/lib/AST/APValue.cpp:637-639 + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; lichray wrote: > rsmith wrote: > > We should drop all trailing zeroes here, because array initialization from > > a string literal will reconstruct them. > Are you sure? `MyType<{""}>` and `MyType<{"\0\0\0"}>` are different types. That's a separate bug. `APValue`'s printing is not intended to identify the type of the result, only to identify the value in the case where we already know the type. Eg, we don't print a type suffix on a pretty-printed integer value. For the specific case of template parameters, it's the responsibility of the template argument printing code to uniquely identify the template argument. When a template parameter has a deduced class type, we should include that type in the printed output in order to uniquely identify the specialization, but we don't, because that's not been implemented yet. When that's fixed, we should print those cases as `MyType{""}>` and `MyType{""}>`. This is necessary anyway, because we can't in general assume that the resulting value is enough to indicate what type CTAD will have selected. We already handle this properly in some cases, but see this FIXMEs: https://github.com/llvm/llvm-project/blob/6c2be3015e07f25912b8cd5b75214c532f568638/clang/lib/AST/TemplateBase.cpp#L433 See also some related issues: https://godbolt.org/z/YhcdMYx6n (note that the non-struct enum case is handled properly but the enum-in-struct case is not). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray added inline comments. Comment at: clang/lib/AST/APValue.cpp:628-629 +static bool TryPrintAsStringLiteral(raw_ostream , const ArrayType *ATy, +const APValue *Data, size_t Size) { + if (Size == 0) rsmith wrote: > Is there anything you can factor out of `StringLiteral::outputString` and > reuse here? At least the single-character printing code seems like something > we should try to not overly duplicate. The goals of the two routines are different. `StringLiteral::outputString` must output something that can parse back as a string literal, even it doesn't decode UTF-8 right now; the new routine in this patch doesn't have to -- it can give up anytime it wants. I wish `switch` statements were more composable. But if you don't mind, I can add a function in `CharInfo.h` to test and get the C-style escaped char and retire the outmost `switch` statements in those two routines. Comment at: clang/lib/AST/APValue.cpp:637-639 + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; rsmith wrote: > We should drop all trailing zeroes here, because array initialization from a > string literal will reconstruct them. Are you sure? `MyType<{""}>` and `MyType<{"\0\0\0"}>` are different types. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 391744. lichray added a comment. Ensure the ellipses output is never shorter than the normal ones (will look at review comments later) Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/lib/AST/APValue.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{"escape\0"}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\'\f\v"}> + new ASCII<"escape\\\t'\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more than[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}> + new ASCII<"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{L"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, ...}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print even more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print many characters no more than[...]"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII; +} + +void utf8() +{ + // CHECK{LITERAL}: ASCII<{u8""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{u8"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{229, 165, 189, 239, 191, 189, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"print many characters no more than[...]"}> + new ASCII; +} + +void utf16() +{ + // CHECK{LITERAL}: ASCII<{u""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{u"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{22909, 65533, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"print many characters no more
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
rsmith added inline comments. Comment at: clang/lib/AST/APValue.cpp:628-629 +static bool TryPrintAsStringLiteral(raw_ostream , const ArrayType *ATy, +const APValue *Data, size_t Size) { + if (Size == 0) Is there anything you can factor out of `StringLiteral::outputString` and reuse here? At least the single-character printing code seems like something we should try to not overly duplicate. Comment at: clang/lib/AST/APValue.cpp:637-639 + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; We should drop all trailing zeroes here, because array initialization from a string literal will reconstruct them. Comment at: clang/lib/AST/APValue.cpp:641-643 + constexpr size_t MaxN = 36; + char Buf[MaxN * 2 + 3] = {'"'}; // "At most 36 escaped chars" + \0 + auto *pBuf = Buf + 1; Prefer `llvm::SmallString` and `push_back`. Comment at: clang/lib/AST/APValue.cpp:645 + + // Better than printing a two-digit sequence of 10 integers. + StringRef Ellipsis; ...except that some callers want output that uniquely identifies the template argument, and moreover some callers want output that is valid C++ code that produces the same template-id. It'd be better to do this behind a `PrintingPolicy` flag that the diagnostics engine sets. But we'd want to turn that flag off during template type diffing. Comment at: clang/lib/AST/APValue.cpp:902 if (I == 10) { // Avoid printing out the entire contents of large arrays. + Out << "...}"; (The existing code is also doing elision here that will be inappropriate for some callers. If you add a `PrintingPolicy` to unambiguously print template arguments, it should disable this check too.) Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 391718. lichray added a comment. Add EOL to source file Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/lib/AST/APValue.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{"escape\0"}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\'\f\v"}> + new ASCII<"escape\\\t'\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more t[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}> + new ASCII<"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{L"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, ...}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print even more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print many characters no more t[...]"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII; +} + +void utf8() +{ + // CHECK{LITERAL}: ASCII<{u8""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{u8"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{229, 165, 189, 239, 191, 189, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"print many characters no more t[...]"}> + new ASCII; +} + +void utf16() +{ + // CHECK{LITERAL}: ASCII<{u""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{u"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{22909, 65533, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"print many characters no more t[...]"}> + new ASCII; +} + +void utf32() +{ + // CHECK{LITERAL}: ASCII<{U""}> + new ASCII; + //
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 391717. lichray added a comment. - Add tests Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/lib/AST/APValue.cpp clang/test/SemaTemplate/temp_arg_string_printing.cpp Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp === --- /dev/null +++ clang/test/SemaTemplate/temp_arg_string_printing.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s + +using size_t = __SIZE_TYPE__; +static_assert(__has_builtin(__make_integer_seq)); + +template class idx_seq {}; +template using make_idx_seq = __make_integer_seq; + +template +struct Str { + constexpr Str(CharT const ()[N]) : Str(s, make_idx_seq()) {} + CharT value[N]; + +private: + template + constexpr Str(CharT const ()[N], idx_seq) : value{s[I]...} {} +}; + +template class ASCII {}; + +void narrow() { + // CHECK{LITERAL}: ASCII<{""}> + new ASCII<"">; + // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}> + new ASCII<"the quick brown fox jumps">; + // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}> + new ASCII<"OVER THE LAZY DOG 0123456789">; + // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{"escape\0"}> + new ASCII<"escape\0">; + // CHECK{LITERAL}: ASCII<{"escape\r\n"}> + new ASCII<"escape\r\n">; + // CHECK{LITERAL}: ASCII<{"escape\\\t\'\f\v"}> + new ASCII<"escape\\\t'\f\v">; + // CHECK{LITERAL}: ASCII<{"escape\a\bc"}> + new ASCII<"escape\a\b\c">; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII<"not\x11">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}> + new ASCII<"\x12\x14\x7f\x10\x01 abc">; + // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}> + new ASCII<"\x12\x14\x7f\x10\x01 abcd">; + // CHECK{LITERAL}: ASCII<{"print more characters as string"}> + new ASCII<"print more characters as string">; + // CHECK{LITERAL}: ASCII<{"print even more characters as string"}> + new ASCII<"print even more characters as string">; + // CHECK{LITERAL}: ASCII<{"print many characters no more t[...]"}> + new ASCII<"print many characters no more than a limit">; + // CHECK{LITERAL}: ASCII<{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}> + new ASCII<"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0">; + // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">; +} + +void wide() { + // CHECK{LITERAL}: ASCII<{L""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{L"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, ...}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print even more characters as string"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"print many characters no more t[...]"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{L"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}> + new ASCII; +} + +void utf8() +{ + // CHECK{LITERAL}: ASCII<{u8""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{u8"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{229, 165, 189, 239, 191, 189, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u8"print many characters no more t[...]"}> + new ASCII; +} + +void utf16() +{ + // CHECK{LITERAL}: ASCII<{u""}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}> + new ASCII?/)">; + // CHECK{LITERAL}: ASCII<{u"escape\0"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"escape\r\n"}> + new ASCII; + // CHECK{LITERAL}: ASCII<{{22909, 65533, 0}}> + new ASCII; + // CHECK{LITERAL}: ASCII<{u"print many characters no more t[...]"}> + new ASCII; +} + +void utf32() +{ + // CHECK{LITERAL}: ASCII<{U""}> + new ASCII; + // CHECK{LITERAL}:
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 391602. lichray added a comment. Restore deleted comment Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/lib/AST/APValue.cpp Index: clang/lib/AST/APValue.cpp === --- clang/lib/AST/APValue.cpp +++ clang/lib/AST/APValue.cpp @@ -625,6 +625,97 @@ return V.convertToDouble(); } +static bool TryPrintAsStringLiteral(raw_ostream , const ArrayType *ATy, +const APValue *Data, size_t Size) { + if (Size == 0) +return false; + + QualType Ty = ATy->getElementType(); + if (!Ty->isAnyCharacterType()) +return false; + + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; + + constexpr size_t MaxN = 36; + char Buf[MaxN * 2 + 3] = {'"'}; // "At most 36 escaped chars" + \0 + auto *pBuf = Buf + 1; + + // Better than printing a two-digit sequence of 10 integers. + StringRef Ellipsis; + if (Size > MaxN) { +Ellipsis = " [...]"; +Size = std::min(MaxN - Ellipsis.size(), Size); + } + + auto writeEscape = [](char *Ptr, char Ch) { +Ptr[0] = '\\'; +Ptr[1] = Ch; +return Ptr + 2; + }; + + for (auto : ArrayRef(Data, Size)) { +auto Char64 = Val.getInt().getExtValue(); +if (Char64 > 0x7f) + return false; // Bye bye, see you in integers. +switch (auto Ch = static_cast(Char64)) { +default: + if (isPrintable(Ch)) { +*pBuf++ = Ch; +break; + } + return false; +case '\\': +case '\'': // The diagnostic message is 'quoted' + pBuf = writeEscape(pBuf, Ch); + break; +case '\0': + pBuf = writeEscape(pBuf, '0'); + break; +case '\a': + pBuf = writeEscape(pBuf, 'a'); + break; +case '\b': + pBuf = writeEscape(pBuf, 'b'); + break; +case '\f': + pBuf = writeEscape(pBuf, 'f'); + break; +case '\n': + pBuf = writeEscape(pBuf, 'n'); + break; +case '\r': + pBuf = writeEscape(pBuf, 'r'); + break; +case '\t': + pBuf = writeEscape(pBuf, 't'); + break; +case '\v': + pBuf = writeEscape(pBuf, 'v'); + break; +} + } + + if (!Ellipsis.empty()) { +memcpy(pBuf, Ellipsis.data(), Ellipsis.size()); +pBuf += Ellipsis.size(); + } + *pBuf++ = '"'; + + if (Ty->isWideCharType()) +Out << 'L'; + else if (Ty->isChar8Type()) +Out << "u8"; + else if (Ty->isChar16Type()) +Out << 'u'; + else if (Ty->isChar32Type()) +Out << 'U'; + + Out << StringRef(Buf, pBuf - Buf); + return true; +} + void APValue::printPretty(raw_ostream , const ASTContext , QualType Ty) const { printPretty(Out, Ctx.getPrintingPolicy(), Ty, ); @@ -795,17 +886,24 @@ } case APValue::Array: { const ArrayType *AT = Ty->castAsArrayTypeUnsafe(); +unsigned N = getArrayInitializedElts(); +if (N != 0 && +TryPrintAsStringLiteral(Out, AT, (0), N)) + return; QualType ElemTy = AT->getElementType(); Out << '{'; -if (unsigned N = getArrayInitializedElts()) { - getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx); - for (unsigned I = 1; I != N; ++I) { +unsigned I = 0; +switch (N) { +case 0: + for (; I != N; ++I) { Out << ", "; if (I == 10) { // Avoid printing out the entire contents of large arrays. - Out << "..."; - break; + Out << "...}"; + return; } +LLVM_FALLTHROUGH; + default: getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx); } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray updated this revision to Diff 391600. lichray added a comment. Fix failed assertion Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115031/new/ https://reviews.llvm.org/D115031 Files: clang/lib/AST/APValue.cpp Index: clang/lib/AST/APValue.cpp === --- clang/lib/AST/APValue.cpp +++ clang/lib/AST/APValue.cpp @@ -625,6 +625,97 @@ return V.convertToDouble(); } +static bool TryPrintAsStringLiteral(raw_ostream , const ArrayType *ATy, +const APValue *Data, size_t Size) { + if (Size == 0) +return false; + + QualType Ty = ATy->getElementType(); + if (!Ty->isAnyCharacterType()) +return false; + + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; + + constexpr size_t MaxN = 36; + char Buf[MaxN * 2 + 3] = {'"'}; // "At most 36 escaped chars" + \0 + auto *pBuf = Buf + 1; + + // Better than printing a two-digit sequence of 10 integers. + StringRef Ellipsis; + if (Size > MaxN) { +Ellipsis = " [...]"; +Size = std::min(MaxN - Ellipsis.size(), Size); + } + + auto writeEscape = [](char *Ptr, char Ch) { +Ptr[0] = '\\'; +Ptr[1] = Ch; +return Ptr + 2; + }; + + for (auto : ArrayRef(Data, Size)) { +auto Char64 = Val.getInt().getExtValue(); +if (Char64 > 0x7f) + return false; // Bye bye, see you in integers. +switch (auto Ch = static_cast(Char64)) { +default: + if (isPrintable(Ch)) { +*pBuf++ = Ch; +break; + } + return false; +case '\\': +case '\'': // The diagnostic message is 'quoted' + pBuf = writeEscape(pBuf, Ch); + break; +case '\0': + pBuf = writeEscape(pBuf, '0'); + break; +case '\a': + pBuf = writeEscape(pBuf, 'a'); + break; +case '\b': + pBuf = writeEscape(pBuf, 'b'); + break; +case '\f': + pBuf = writeEscape(pBuf, 'f'); + break; +case '\n': + pBuf = writeEscape(pBuf, 'n'); + break; +case '\r': + pBuf = writeEscape(pBuf, 'r'); + break; +case '\t': + pBuf = writeEscape(pBuf, 't'); + break; +case '\v': + pBuf = writeEscape(pBuf, 'v'); + break; +} + } + + if (!Ellipsis.empty()) { +memcpy(pBuf, Ellipsis.data(), Ellipsis.size()); +pBuf += Ellipsis.size(); + } + *pBuf++ = '"'; + + if (Ty->isWideCharType()) +Out << 'L'; + else if (Ty->isChar8Type()) +Out << "u8"; + else if (Ty->isChar16Type()) +Out << 'u'; + else if (Ty->isChar32Type()) +Out << 'U'; + + Out << StringRef(Buf, pBuf - Buf); + return true; +} + void APValue::printPretty(raw_ostream , const ASTContext , QualType Ty) const { printPretty(Out, Ctx.getPrintingPolicy(), Ty, ); @@ -795,17 +886,23 @@ } case APValue::Array: { const ArrayType *AT = Ty->castAsArrayTypeUnsafe(); +unsigned N = getArrayInitializedElts(); +if (N != 0 && +TryPrintAsStringLiteral(Out, AT, (0), N)) + return; QualType ElemTy = AT->getElementType(); Out << '{'; -if (unsigned N = getArrayInitializedElts()) { - getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx); - for (unsigned I = 1; I != N; ++I) { +unsigned I = 0; +switch (N) { +case 0: + for (; I != N; ++I) { Out << ", "; if (I == 10) { - // Avoid printing out the entire contents of large arrays. - Out << "..."; - break; + Out << "...}"; + return; } +LLVM_FALLTHROUGH; + default: getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx); } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D115031: [AST] Print NTTP args as string-literals when possible
lichray created this revision. lichray requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. C++20 NTTP (non-type template parameter) prints `MyType<{{116, 104, 105, 115}}>` when the code is as simple as `MyType<"this">`. Of course, due to the need for an intermediate structural type to trigger CTAD, it'd be better to keep one layer of the braces. So this patch prints `MyType<{"this"}>`. Currently, `StringLiteral` can handle this case nicely, but `StringLiteral` inside `APValue` code looks like a circular dependency. So, in this patch, I implemented a very cheap strategy to emit string literals in diagnostic message only when it's more readable and fall back to integer sequences. *Please tell me whether this approach is acceptable* before I write tests. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D115031 Files: clang/lib/AST/APValue.cpp Index: clang/lib/AST/APValue.cpp === --- clang/lib/AST/APValue.cpp +++ clang/lib/AST/APValue.cpp @@ -625,6 +625,97 @@ return V.convertToDouble(); } +static bool TryPrintAsStringLiteral(raw_ostream , const ArrayType *ATy, +const APValue *Data, size_t Size) { + if (Size == 0) +return false; + + QualType Ty = ATy->getElementType(); + if (!Ty->isAnyCharacterType()) +return false; + + // Nothing we can do about a sequence that is not null-terminated + if (!Data[--Size].getInt().isZero()) +return false; + + constexpr size_t MaxN = 36; + char Buf[MaxN * 2 + 3] = {'"'}; // "At most 36 escaped chars" + \0 + auto *pBuf = Buf + 1; + + // Better than printing a two-digit sequence of 10 integers. + StringRef Ellipsis; + if (Size > MaxN) { +Ellipsis = " [...]"; +Size = std::min(MaxN - Ellipsis.size(), Size); + } + + auto writeEscape = [](char *Ptr, char Ch) { +Ptr[0] = '\\'; +Ptr[1] = Ch; +return Ptr + 2; + }; + + for (auto : ArrayRef(Data, Size)) { +auto Char64 = Val.getInt().getExtValue(); +if (Char64 > 0x7f) + return false; // Bye bye, see you in integers. +switch (auto Ch = static_cast(Char64)) { +default: + if (isPrintable(Ch)) { +*pBuf++ = Ch; +break; + } + return false; +case '\\': +case '\'': // The diagnostic message is 'quoted' + pBuf = writeEscape(pBuf, Ch); + break; +case '\0': + pBuf = writeEscape(pBuf, '0'); + break; +case '\a': + pBuf = writeEscape(pBuf, 'a'); + break; +case '\b': + pBuf = writeEscape(pBuf, 'b'); + break; +case '\f': + pBuf = writeEscape(pBuf, 'f'); + break; +case '\n': + pBuf = writeEscape(pBuf, 'n'); + break; +case '\r': + pBuf = writeEscape(pBuf, 'r'); + break; +case '\t': + pBuf = writeEscape(pBuf, 't'); + break; +case '\v': + pBuf = writeEscape(pBuf, 'v'); + break; +} + } + + if (!Ellipsis.empty()) { +memcpy(pBuf, Ellipsis.data(), Ellipsis.size()); +pBuf += Ellipsis.size(); + } + *pBuf++ = '"'; + + if (Ty->isWideCharType()) +Out << 'L'; + else if (Ty->isChar8Type()) +Out << "u8"; + else if (Ty->isChar16Type()) +Out << 'u'; + else if (Ty->isChar32Type()) +Out << 'U'; + + Out << StringRef(Buf, pBuf - Buf); + return true; +} + void APValue::printPretty(raw_ostream , const ASTContext , QualType Ty) const { printPretty(Out, Ctx.getPrintingPolicy(), Ty, ); @@ -795,17 +886,22 @@ } case APValue::Array: { const ArrayType *AT = Ty->castAsArrayTypeUnsafe(); +if (TryPrintAsStringLiteral(Out, AT, (0), +getArrayInitializedElts())) + return; QualType ElemTy = AT->getElementType(); Out << '{'; -if (unsigned N = getArrayInitializedElts()) { - getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx); - for (unsigned I = 1; I != N; ++I) { +unsigned I = 0; +switch (unsigned N = getArrayInitializedElts()) { +case 0: + for (; I != N; ++I) { Out << ", "; if (I == 10) { - // Avoid printing out the entire contents of large arrays. - Out << "..."; - break; + Out << "...}"; + return; } +LLVM_FALLTHROUGH; + default: getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx); } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits