Skip to content

Commit

Permalink
Fix type printing of array template args
Browse files Browse the repository at this point in the history
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
  • Loading branch information
reikdas authored and vgvassilev committed May 1, 2021
1 parent be8ad4e commit 8518742
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
26 changes: 24 additions & 2 deletions clang/lib/AST/TemplateBase.cpp
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
Expand Up @@ -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}}
}

0 comments on commit 8518742

Please sign in to comment.