Author: Pratyush Das Date: 2021-05-01T18:50:09Z New Revision: 8518742104ab075296722ef6151f65aee7a0646d
URL: https://github.com/llvm/llvm-project/commit/8518742104ab075296722ef6151f65aee7a0646d DIFF: https://github.com/llvm/llvm-project/commit/8518742104ab075296722ef6151f65aee7a0646d.diff LOG: Fix type printing of array template args The code example: ``` constexpr const char kEta[] = "Eta"; template <const char*, typename T> class Column {}; using quick = Column<kEta,double>; void lookup() { quick c1; c1.ls(); } ``` emits error: no member named 'ls' in 'Column<&kEta, double>'. The patch fixes the printed type name by not printing the ampersand for array types. Differential Revision: https://reviews.llvm.org/D36368 Added: Modified: clang/lib/AST/TemplateBase.cpp clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index baf62bd115a85..b1816ff8aeb16 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -80,6 +80,26 @@ static void printIntegral(const TemplateArgument &TemplArg, } } +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 @@ void TemplateArgument::print(const PrintingPolicy &Policy, break; } } - if (!getParamTypeForDecl()->isReferenceType()) - Out << '&'; + if (auto *VD = dyn_cast<ValueDecl>(ND)) { + if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType())) + Out << "&"; + } ND->printQualifiedName(Out); break; } diff --git a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp index 4f85effdc700f..055ac64b9955d 100644 --- a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp +++ b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -86,6 +86,12 @@ void fn_tmpl() {} template void fn_tmpl<int, freefunc>(); // CHECK-DAG: "fn_tmpl<int,&freefunc>" +template <typename T, void (*)(void)> +void fn_tmpl_typecheck() {} + +template void fn_tmpl_typecheck<int, &freefunc>(); +// CHECK-DAG: "fn_tmpl_typecheck<int,&freefunc>" + template <typename A, typename B, typename C> struct ClassTemplate { A a; B b; C c; }; ClassTemplate<char, short, ClassTemplate<int, int, int> > f; // This will only show up in normal debug builds. The space in `> >` is diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp index 522835f33454c..5752cbac0291d 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp @@ -77,3 +77,40 @@ namespace ReferenceToConstexpr { }; void f(C<a> 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 <const char *, typename T> class Column {}; +template <const char[], typename T> class Dolumn {}; +template <const char (*)[4], typename T> class Folumn {}; +template <FourChars *, typename T> class Golumn {}; +template <const char *const *, typename T> class Holumn {}; +template <const char *const *const *, typename T> class Jolumn {}; +template <const char **const (*)[0], typename T> class Iolumn {}; + +class container { +public: + int a; +}; +template <int container::*> class Kolumn {}; + +void lookup() { + Column<kEta, double>().ls(); // expected-error {{<kEta,}} + Column<kDes, double>().ls(); // expected-error {{<kDes,}} + Column<nullptr, double>().ls(); // expected-error {{<nullptr,}} + Dolumn<kEta, double>().ls(); // expected-error {{<kEta,}} + Dolumn<kDes, double>().ls(); // expected-error {{<kDes,}} + Folumn<&kEta, double>().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<kZero, double>().ls(); // expected-error {{<kZero,}} + Iolumn<&kZero, double>().ls(); // expected-error {{<&kZero,}} + Kolumn<&container::a>().ls(); // expected-error {{<&container::a}} + Kolumn<nullptr>().ls(); // expected-error {{<nullptr}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits