Index: clang/lib/AST/TemplateBase.cpp =================================================================== --- clang/lib/AST/TemplateBase.cpp +++ clang/lib/AST/TemplateBase.cpp @@ -80,6 +80,26 @@ } } +static unsigned getArrayDepth(QualType type) { + unsigned count = 0; + while (const auto *arrayType = type->getAsArrayTypeUnsafe()) { + count++; + type = arrayType->getElementType(); + } + return count; +} + +static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) { + // Generally, if the parameter type is a pointer, we must be taking the + // address of something and need a &. However, if the argument is an array, + // this could be implicit via array-to-pointer decay. + if (!paramType->isPointerType()) + return paramType->isMemberPointerType(); + if (argType->isArrayType()) + return getArrayDepth(argType) == getArrayDepth(paramType->getPointeeType()); + return true; +} + //===----------------------------------------------------------------------===// // TemplateArgument Implementation //===----------------------------------------------------------------------===// @@ -363,8 +383,10 @@ break; } } - if (!getParamTypeForDecl()->isReferenceType()) - Out << '&'; + if (auto *VD = dyn_cast(ND)) { + if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType())) + 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/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,40 @@ }; 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"; +constexpr const char **kZero[] = {}; + +template class Column {}; +template class Dolumn {}; +template class Folumn {}; +template class Golumn {}; +template class Holumn {}; +template class Jolumn {}; +template class Iolumn {}; + +class container { +public: + int a; +}; +template class Kolumn {}; + +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,}} + Kolumn<&container::a>().ls(); // expected-error {{<&container::a}} + Kolumn().ls(); // expected-error {{