Index: clang/lib/AST/TemplateBase.cpp =================================================================== --- clang/lib/AST/TemplateBase.cpp +++ clang/lib/AST/TemplateBase.cpp @@ -80,6 +80,35 @@ } } +static unsigned getPointerDepth(QualType type) { + if (type.isNull()) + return 0; + unsigned count = 0; + while (const auto *ptrType = type->getAs()) { + count++; + type = ptrType->getPointeeType(); + } + return count; +} + +static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType, + ASTContext &Ctx) { + if (paramType->isReferenceType()) + return false; + if (Ctx.hasSameType(argType, paramType)) + return false; + if (argType->isFunctionType() && paramType->isPointerType()) + return true; + if (argType->isArrayType() || argType->isFunctionType()) { + if (!paramType->getPointeeType()->isArrayType()) + return (getPointerDepth(QualType(argType->getArrayElementTypeNoTypeQual(), + 0)) > getPointerDepth(paramType)); + else + return !Ctx.hasSameType(Ctx.getDecayedType(argType), paramType); + } + return true; +} + //===----------------------------------------------------------------------===// // TemplateArgument Implementation //===----------------------------------------------------------------------===// @@ -363,8 +392,11 @@ break; } } - if (!getParamTypeForDecl()->isReferenceType()) - Out << '&'; + if (auto *VD = dyn_cast(ND)) { + if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType(), + ND->getASTContext())) + Out << "&"; + } ND->printQualifiedName(Out); break; } Index: clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp =================================================================== --- clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp +++ clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -86,6 +86,12 @@ template void fn_tmpl(); // CHECK-DAG: "fn_tmpl" +template +void fn_tmpl_typecheck() {} + +template void fn_tmpl_typecheck(); +// CHECK-DAG: "fn_tmpl_typecheck" + template struct ClassTemplate { A a; B b; C c; }; ClassTemplate > f; // This will only show up in normal debug builds. The space in `> >` is Index: clang/test/CodeGenCXX/debug-info-template.cpp =================================================================== --- clang/test/CodeGenCXX/debug-info-template.cpp +++ clang/test/CodeGenCXX/debug-info-template.cpp @@ -1,6 +1,6 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++20 | FileCheck %s -// CHECK: @tci = dso_local global %"struct.TC::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] +// CHECK: @tci = dso_local global %"struct.TC::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] // CHECK: @tcn = dso_local global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]] // CHECK: @nn = dso_local global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]] @@ -31,7 +31,7 @@ // CHECK: ![[TCNESTED]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "nested", // CHECK-SAME: scope: ![[TC:[0-9]+]], -// CHECK: ![[TC]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TC" +// CHECK: ![[TC]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TC" // CHECK-SAME: templateParams: [[TCARGS:![0-9]*]] TC // CHECK: [[TCARGS]] = !{[[TCARG1:![0-9]*]], [[TCARG2:![0-9]*]], [[TCARG3:![0-9]*]], [[TCARG4:![0-9]*]], [[TCARG5:![0-9]*]], [[TCARG6:![0-9]*]], [[TCARG7:![0-9]*]]} Index: clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp =================================================================== --- clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp +++ clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp @@ -77,3 +77,33 @@ }; void f(C ca) { ca.f({}, 0); } } + +using FourChars = const char[4]; +constexpr FourChars kEta = "Eta"; +constexpr const char kDes[4] = "Des"; +constexpr const char *kNull = "Phi"; + +template class Column {}; +template class Dolumn {}; +template class Folumn {}; +template class Golumn {}; +template class Holumn {}; + +constexpr const char **kZero[] = {}; +template class Jolumn {}; +template class Iolumn {}; + +void lookup() { + Column().ls(); // expected-error {{().ls(); // expected-error {{().ls(); // expected-error {{().ls(); // expected-error {{().ls(); // expected-error {{().ls(); // expected-error {{<&kEta,}} + Folumn<&kDes, double>().ls(); // expected-error {{<&kDes,}} + Golumn<&kEta, double>().ls(); // expected-error {{<&kEta,}} + Golumn<&kDes, double>().ls(); // expected-error {{<&kDes,}} + Holumn<&kNull, double>().ls(); // expected-error {{<&kNull,}} + Jolumn().ls(); // expected-error {{().ls(); // expected-error {{<&kZero,}} +}