Skip to content

Commit

Permalink
Disambiguate type names when printing NTTP types
Browse files Browse the repository at this point in the history
When printing NTTP template types, ensure that type name of the NTTP is
printed.

Fixes #57562

Differential Revision: https://reviews.llvm.org/D134453
  • Loading branch information
DoDoENT authored and AaronBallman committed Oct 28, 2022
1 parent 76cf890 commit 835b99e
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 64 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -336,6 +336,8 @@ Improvements to Clang's diagnostics
<https://clang.llvm.org/docs/ControlFlowIntegrity.html>`_ failures. This diagnostic
is grouped under ``-Wcast-function-type`` as it identifies a more strict set of
potentially problematic function type casts.
- Clang will now disambiguate NTTP types when printing diagnostic that contain NTTP types.
Fixes `Issue 57562 <https://github.com/llvm/llvm-project/issues/57562>`_.

Non-comprehensive list of changes in this release
-------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/TemplateBase.cpp
Expand Up @@ -422,10 +422,10 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
}

case Declaration: {
// FIXME: Include the type if it's not obvious from the context.
NamedDecl *ND = getAsDecl();
if (getParamTypeForDecl()->isRecordType()) {
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
TPO->getType().getUnqualifiedType().print(Out, Policy);
TPO->printAsInit(Out, Policy);
break;
}
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGenCXX/debug-info-template.cpp
Expand Up @@ -165,7 +165,7 @@ template<ClassTemplateArg A> struct ClassTemplateArgTemplate {
static constexpr const ClassTemplateArg &Arg = A;
};

// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ClassTemplateArgTemplate<{1, 2.000000e+00}>", {{.*}}, templateParams: ![[CLASS_TEMP_ARGS:[0-9]*]],
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ClassTemplateArgTemplate<ClassTemplateArg{1, 2.000000e+00}>", {{.*}}, templateParams: ![[CLASS_TEMP_ARGS:[0-9]*]],
// CHECK: ![[CLASS_TEMP_ARG_CONST_REF_TYPE:[0-9]*]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: ![[CLASS_TEMP_ARG_CONST_TYPE:[0-9]*]],
// CHECK: ![[CLASS_TEMP_ARG_CONST_TYPE]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[CLASS_TEMP_ARG_TYPE:[0-9]*]])
// CHECK: ![[CLASS_TEMP_ARG_TYPE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ClassTemplateArg",
Expand Down Expand Up @@ -225,16 +225,16 @@ template void f1<t1 () volatile, t1 () const volatile, t1 () &, t1 () &&>();
// CHECK-SAME: templateParams: ![[RAW_FUNC_QUAL_ARGS:[0-9]*]],

// CHECK: ![[RAW_FUNC_QUAL_ARGS]] = !{![[RAW_FUNC_QUAL_T1:[0-9]*]], ![[RAW_FUNC_QUAL_T2:[0-9]*]], ![[RAW_FUNC_QUAL_T3:[0-9]*]], ![[RAW_FUNC_QUAL_T4:[0-9]*]]}
// CHECK: ![[RAW_FUNC_QUAL_T1]] = !DITemplateTypeParameter(name: "T1", type: ![[RAW_FUNC_QUAL_VOL:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_T1]] = !DITemplateTypeParameter(name: "T1", type: ![[RAW_FUNC_QUAL_VOL:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_VOL]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[RAW_FUNC_QUAL_TYPE:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_TYPE]] = !DISubroutineType(types: ![[RAW_FUNC_QUAL_LIST:[0-9]*]]
// CHECK: ![[RAW_FUNC_QUAL_LIST]] = !{![[RAW_FUNC_QUAL_STRUCT:[0-9]*]]}
// CHECK: ![[RAW_FUNC_QUAL_STRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "t1"
// CHECK: ![[RAW_FUNC_QUAL_T2]] = !DITemplateTypeParameter(name: "T2", type: ![[RAW_FUNC_QUAL_CNST:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_T2]] = !DITemplateTypeParameter(name: "T2", type: ![[RAW_FUNC_QUAL_CNST:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_CNST]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[RAW_FUNC_QUAL_TYPE:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_T3]] = !DITemplateTypeParameter(name: "T3", type: ![[RAW_FUNC_QUAL_REF:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_T3]] = !DITemplateTypeParameter(name: "T3", type: ![[RAW_FUNC_QUAL_REF:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_REF]] = !DISubroutineType(flags: DIFlagLValueReference, types: ![[RAW_FUNC_QUAL_LIST]])
// CHECK: ![[RAW_FUNC_QUAL_T4]] = !DITemplateTypeParameter(name: "T4", type: ![[RAW_FUNC_QUAL_REF_REF:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_T4]] = !DITemplateTypeParameter(name: "T4", type: ![[RAW_FUNC_QUAL_REF_REF:[0-9]*]])
// CHECK: ![[RAW_FUNC_QUAL_REF_REF]] = !DISubroutineType(flags: DIFlagRValueReference, types: ![[RAW_FUNC_QUAL_LIST]])

} // namespace RawFuncQual
Expand Down
6 changes: 3 additions & 3 deletions clang/test/SemaCXX/cxx2a-nttp-printing.cpp
Expand Up @@ -16,19 +16,19 @@ void test_ascii() {
" is too long">
a;
Foo(a); // expected-error {{no matching function}}
decltype(a)::display(); // expected-error {{no member named 'display' in 'ASCII<{"this nontype template argument is [...]"}>'}}
decltype(a)::display(); // expected-error {{no member named 'display' in 'ASCII<Str<43>{"this nontype template argument is [...]"}>'}}
}

void test_non_ascii() {
ASCII<"wait a s\033cond"> a;
Bar(a); // expected-error {{no matching function}}
decltype(a)::display(); // expected-error {{no member named 'display' in 'ASCII<{{119, 97, 105, 116, 32, 97, 32, 115, 27, 99, ...}}>'}}
decltype(a)::display(); // expected-error {{no member named 'display' in 'ASCII<Str<14>{{119, 97, 105, 116, 32, 97, 32, 115, 27, 99, ...}}>'}}
}

// The dialects (C++20 and above) that accept string literals as non-type
// template arguments do not support trigraphs.
void test_trigraph() {
ASCII<"what??!"> a; // expected-warning {{trigraph ignored}}
Meow(a); // expected-error {{no matching function}}
decltype(a)::display(); // expected-error {{no member named 'display' in 'ASCII<{"what??!"}>'}}
decltype(a)::display(); // expected-error {{no member named 'display' in 'ASCII<Str<8>{"what??!"}>'}}
}
2 changes: 1 addition & 1 deletion clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
Expand Up @@ -186,7 +186,7 @@ namespace Diags {
struct A { int n, m; };
template<A a> struct X { static_assert(a.n == a.m); }; // expected-error {{static assertion failed due to requirement 'Diags::A{1, 2}.n == Diags::A{1, 2}.m'}} \
// expected-note {{evaluates to '1 == 2'}}
template struct X<A{1, 2}>; // expected-note {{in instantiation of template class 'Diags::X<{1, 2}>' requested here}}
template struct X<A{1, 2}>; // expected-note {{in instantiation of template class 'Diags::X<A{1, 2}>' requested here}}
}

namespace CTADPartialOrder {
Expand Down
92 changes: 46 additions & 46 deletions clang/test/SemaTemplate/temp_arg_string_printing.cpp
Expand Up @@ -19,111 +19,111 @@ struct Str {
template <Str> class ASCII {};

void not_string() {
// CHECK{LITERAL}: ASCII<{{9, -1, 42}}>
// CHECK{LITERAL}: ASCII<Str<int, 3>{{9, -1, 42}}>
new ASCII<(int[]){9, -1, 42}>;
// CHECK{LITERAL}: ASCII<{{3.140000e+00, 0.000000e+00, 4.200000e+01}}>
// CHECK{LITERAL}: ASCII<Str<double, 3>{{3.140000e+00, 0.000000e+00, 4.200000e+01}}>
new ASCII<(double[]){3.14, 0., 42.}>;
}

void narrow() {
// CHECK{LITERAL}: ASCII<{""}>
// CHECK{LITERAL}: ASCII<Str<char, 1>{""}>
new ASCII<"">;
// CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}>
// CHECK{LITERAL}: ASCII<Str<char, 26>{"the quick brown fox jumps"}>
new ASCII<"the quick brown fox jumps">;
// CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}>
// CHECK{LITERAL}: ASCII<Str<char, 29>{"OVER THE LAZY DOG 0123456789"}>
new ASCII<"OVER THE LAZY DOG 0123456789">;
// CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
// CHECK{LITERAL}: ASCII<Str<char, 33>{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
new ASCII<R"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
// CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}>
// CHECK{LITERAL}: ASCII<Str<char, 8>{{101, 115, 99, 97, 112, 101, 0, 0}}>
new ASCII<"escape\0">;
// CHECK{LITERAL}: ASCII<{"escape\r\n"}>
// CHECK{LITERAL}: ASCII<Str<char, 9>{"escape\r\n"}>
new ASCII<"escape\r\n">;
// CHECK{LITERAL}: ASCII<{"escape\\\t\f\v"}>
// CHECK{LITERAL}: ASCII<Str<char, 11>{"escape\\\t\f\v"}>
new ASCII<"escape\\\t\f\v">;
// CHECK{LITERAL}: ASCII<{"escape\a\bc"}>
// CHECK{LITERAL}: ASCII<Str<char, 10>{"escape\a\bc"}>
new ASCII<"escape\a\b\c">;
// CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}>
// CHECK{LITERAL}: ASCII<Str<char, 5>{{110, 111, 116, 17, 0}}>
new ASCII<"not\x11">;
// CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}>
// CHECK{LITERAL}: ASCII<Str<char, 10>{{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}}>
// CHECK{LITERAL}: ASCII<Str<char, 11>{{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"}>
// CHECK{LITERAL}: ASCII<Str<char, 32>{"print more characters as string"}>
new ASCII<"print more characters as string">;
// CHECK{LITERAL}: ASCII<{"print more characters as string, no uplimit"}>
// CHECK{LITERAL}: ASCII<Str<char, 44>{"print more characters as string, no uplimit"}>
new ASCII<"print more characters as string, no uplimit">;
}

void wide() {
// CHECK{LITERAL}: ASCII<{L""}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 1>{L""}>
new ASCII<L"">;
// CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 26>{L"the quick brown fox jumps"}>
new ASCII<L"the quick brown fox jumps">;
// CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 29>{L"OVER THE LAZY DOG 0123456789"}>
new ASCII<L"OVER THE LAZY DOG 0123456789">;
// CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 33>{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
new ASCII<LR"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
// CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 8>{{101, 115, 99, 97, 112, 101, 0, 0}}>
new ASCII<L"escape\0">;
// CHECK{LITERAL}: ASCII<{L"escape\r\n"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 9>{L"escape\r\n"}>
new ASCII<L"escape\r\n">;
// CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 11>{L"escape\\\t\f\v"}>
new ASCII<L"escape\\\t\f\v">;
// CHECK{LITERAL}: ASCII<{L"escape\a\bc"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 10>{L"escape\a\bc"}>
new ASCII<L"escape\a\b\c">;
// CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 5>{{110, 111, 116, 17, 0}}>
new ASCII<L"not\x11">;
// CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 10>{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}>
new ASCII<L"\x12\x14\xff\x597d\x88 abc">;
// CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, 0}}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 11>{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, 0}}>
new ASCII<L"\x12\x14\xff\x597d\x88 abcd">;
// CHECK{LITERAL}: ASCII<{L"print more characters as string"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 32>{L"print more characters as string"}>
new ASCII<L"print more characters as string">;
// CHECK{LITERAL}: ASCII<{L"print more characters as string, no uplimit"}>
// CHECK{LITERAL}: ASCII<Str<wchar_t, 44>{L"print more characters as string, no uplimit"}>
new ASCII<L"print more characters as string, no uplimit">;
}

void utf8() {
// CHECK{LITERAL}: ASCII<{u8""}>
// CHECK{LITERAL}: ASCII<Str<char8_t, 1>{u8""}>
new ASCII<u8"">;
// CHECK{LITERAL}: ASCII<{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
// CHECK{LITERAL}: ASCII<Str<char8_t, 33>{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
new ASCII<u8R"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
// CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}>
// CHECK{LITERAL}: ASCII<Str<char8_t, 8>{{101, 115, 99, 97, 112, 101, 0, 0}}>
new ASCII<u8"escape\0">;
// CHECK{LITERAL}: ASCII<{u8"escape\r\n"}>
// CHECK{LITERAL}: ASCII<Str<char8_t, 9>{u8"escape\r\n"}>
new ASCII<u8"escape\r\n">;
// CHECK{LITERAL}: ASCII<{{229, 165, 189, 239, 191, 189, 0}}>
// CHECK{LITERAL}: ASCII<Str<char8_t, 7>{{229, 165, 189, 239, 191, 189, 0}}>
new ASCII<u8"\u597d\ufffd">;
// CHECK{LITERAL}: ASCII<{u8"print more characters as string, no uplimit"}>
// CHECK{LITERAL}: ASCII<Str<char8_t, 44>{u8"print more characters as string, no uplimit"}>
new ASCII<u8"print more characters as string, no uplimit">;
}

void utf16() {
// CHECK{LITERAL}: ASCII<{u""}>
// CHECK{LITERAL}: ASCII<Str<char16_t, 1>{u""}>
new ASCII<u"">;
// CHECK{LITERAL}: ASCII<{u"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
// CHECK{LITERAL}: ASCII<Str<char16_t, 33>{u"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
new ASCII<uR"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
// CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}>
// CHECK{LITERAL}: ASCII<Str<char16_t, 8>{{101, 115, 99, 97, 112, 101, 0, 0}}>
new ASCII<u"escape\0">;
// CHECK{LITERAL}: ASCII<{u"escape\r\n"}>
// CHECK{LITERAL}: ASCII<Str<char16_t, 9>{u"escape\r\n"}>
new ASCII<u"escape\r\n">;
// CHECK{LITERAL}: ASCII<{{22909, 65533, 0}}>
// CHECK{LITERAL}: ASCII<Str<char16_t, 3>{{22909, 65533, 0}}>
new ASCII<u"\u597d\ufffd">;
// CHECK{LITERAL}: ASCII<{u"print more characters as string, no uplimit"}>
// CHECK{LITERAL}: ASCII<Str<char16_t, 44>{u"print more characters as string, no uplimit"}>
new ASCII<u"print more characters as string, no uplimit">;
}

void utf32() {
// CHECK{LITERAL}: ASCII<{U""}>
// CHECK{LITERAL}: ASCII<Str<char32_t, 1>{U""}>
new ASCII<U"">;
// CHECK{LITERAL}: ASCII<{U"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
// CHECK{LITERAL}: ASCII<Str<char32_t, 33>{U"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
new ASCII<UR"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
// CHECK{LITERAL}: ASCII<{{101, 115, 99, 97, 112, 101, 0, 0}}>
// CHECK{LITERAL}: ASCII<Str<char32_t, 8>{{101, 115, 99, 97, 112, 101, 0, 0}}>
new ASCII<U"escape\0">;
// CHECK{LITERAL}: ASCII<{U"escape\r\n"}>
// CHECK{LITERAL}: ASCII<Str<char32_t, 9>{U"escape\r\n"}>
new ASCII<U"escape\r\n">;
// CHECK{LITERAL}: ASCII<{{22909, 131358, 0}}>
// CHECK{LITERAL}: ASCII<Str<char32_t, 3>{{22909, 131358, 0}}>
new ASCII<U"\u597d\U0002011E">;
// CHECK{LITERAL}: ASCII<{U"print more characters as string, no uplimit"}>
// CHECK{LITERAL}: ASCII<Str<char32_t, 44>{U"print more characters as string, no uplimit"}>
new ASCII<U"print more characters as string, no uplimit">;
}
10 changes: 5 additions & 5 deletions clang/unittests/AST/StmtPrinterTest.cpp
Expand Up @@ -161,9 +161,9 @@ TEST(StmtPrinter, TestStringLiteralOperatorTemplate_Pack) {
}

TEST(StmtPrinter, TestStringLiteralOperatorTemplate_Class) {
ASSERT_TRUE(
PrintedStmtCXXMatches(StdVer::CXX20,
R"cpp(
ASSERT_TRUE(PrintedStmtCXXMatches(
StdVer::CXX20,
R"cpp(
struct C {
template <unsigned N> constexpr C(const char (&)[N]) : n(N) {}
unsigned n;
Expand All @@ -173,8 +173,8 @@ TEST(StmtPrinter, TestStringLiteralOperatorTemplate_Class) {
constexpr auto waldo = "abc"_c;
}
)cpp",
FunctionBodyMatcher("A"),
"constexpr auto waldo = operator\"\"_c<{4}>();\n"));
FunctionBodyMatcher("A"),
"constexpr auto waldo = operator\"\"_c<C{4}>();\n"));
}

TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
Expand Down
6 changes: 3 additions & 3 deletions clang/unittests/AST/TypePrinterTest.cpp
Expand Up @@ -48,7 +48,7 @@ TEST(TypePrinter, TemplateId) {
std::string Code = R"cpp(
namespace N {
template <typename> struct Type {};
template <typename T>
void Foo(const Type<T> &Param);
}
Expand Down Expand Up @@ -115,14 +115,14 @@ TEST(TypePrinter, TemplateIdWithNTTP) {

ASSERT_TRUE(PrintedTypeMatches(
Code, {"-std=c++20"}, Matcher,
R"(ASCII<{"this nontype template argument is [...]"}> &&)",
R"(ASCII<Str<52>{"this nontype template argument is [...]"}> &&)",
[](PrintingPolicy &Policy) {
Policy.EntireContentsOfLargeArray = false;
}));

ASSERT_TRUE(PrintedTypeMatches(
Code, {"-std=c++20"}, Matcher,
R"(ASCII<{"this nontype template argument is too long to print"}> &&)",
R"(ASCII<Str<52>{"this nontype template argument is too long to print"}> &&)",
[](PrintingPolicy &Policy) {
Policy.EntireContentsOfLargeArray = true;
}));
Expand Down

0 comments on commit 835b99e

Please sign in to comment.