Skip to content

Commit 65b2c4c

Browse files
committed
Add pretty-printing for class template specializations, e.g.,
'struct A<double, int>' In the "template instantiation depth exceeded" message, print "-ftemplate-depth-N" rather than "-ftemplate-depth=N". An unnamed tag type that is declared with a typedef, e.g., typedef struct { int x, y; } Point; can be used as a template argument. Allow this, and check that we get sensible pretty-printing for such things. llvm-svn: 66560
1 parent 805dd4c commit 65b2c4c

File tree

7 files changed

+43
-16
lines changed

7 files changed

+43
-16
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ DIAG(err_template_spec_redecl_global_scope, ERROR,
643643
DIAG(err_template_recursion_depth_exceeded, ERROR,
644644
"recursive template instantiation exceeded maximum depth of %0")
645645
DIAG(note_template_recursion_depth, NOTE,
646-
"use -ftemplate-depth=N to increase recursive template "
646+
"use -ftemplate-depth-N to increase recursive template "
647647
"instantiation depth")
648648
DIAG(err_template_implicit_instantiate_undefined, ERROR,
649649
"implicit instantiation of undefined template %0")

clang/lib/AST/Type.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,33 +1287,34 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const {
12871287
InnerString = Name->getName() + InnerString;
12881288
}
12891289

1290-
void
1291-
ClassTemplateSpecializationType::
1292-
getAsStringInternal(std::string &InnerString) const {
1293-
std::string SpecString = Template->getNameAsString();
1290+
/// \brief Print a template argument list, including the '<' and '>'
1291+
/// enclosing the template arguments.
1292+
static std::string printTemplateArgumentList(const TemplateArgument *Args,
1293+
unsigned NumArgs) {
1294+
std::string SpecString;
12941295
SpecString += '<';
12951296
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
12961297
if (Arg)
12971298
SpecString += ", ";
12981299

12991300
// Print the argument into a string.
13001301
std::string ArgString;
1301-
switch (getArg(Arg).getKind()) {
1302+
switch (Args[Arg].getKind()) {
13021303
case TemplateArgument::Type:
1303-
getArg(Arg).getAsType().getAsStringInternal(ArgString);
1304+
Args[Arg].getAsType().getAsStringInternal(ArgString);
13041305
break;
13051306

13061307
case TemplateArgument::Declaration:
1307-
ArgString = cast<NamedDecl>(getArg(Arg).getAsDecl())->getNameAsString();
1308+
ArgString = cast<NamedDecl>(Args[Arg].getAsDecl())->getNameAsString();
13081309
break;
13091310

13101311
case TemplateArgument::Integral:
1311-
ArgString = getArg(Arg).getAsIntegral()->toString(10, true);
1312+
ArgString = Args[Arg].getAsIntegral()->toString(10, true);
13121313
break;
13131314

13141315
case TemplateArgument::Expression: {
13151316
llvm::raw_string_ostream s(ArgString);
1316-
getArg(Arg).getAsExpr()->printPretty(s);
1317+
Args[Arg].getAsExpr()->printPretty(s);
13171318
break;
13181319
}
13191320
}
@@ -1335,6 +1336,14 @@ getAsStringInternal(std::string &InnerString) const {
13351336

13361337
SpecString += '>';
13371338

1339+
return SpecString;
1340+
}
1341+
1342+
void
1343+
ClassTemplateSpecializationType::
1344+
getAsStringInternal(std::string &InnerString) const {
1345+
std::string SpecString = Template->getNameAsString();
1346+
SpecString += printTemplateArgumentList(getArgs(), getNumArgs());
13381347
if (InnerString.empty())
13391348
InnerString.swap(SpecString);
13401349
else
@@ -1395,6 +1404,16 @@ void TagType::getAsStringInternal(std::string &InnerString) const {
13951404
} else
13961405
ID = "<anonymous>";
13971406

1407+
// If this is a class template specialization, print the template
1408+
// arguments.
1409+
if (ClassTemplateSpecializationDecl *Spec
1410+
= dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
1411+
std::string TemplateArgs
1412+
= printTemplateArgumentList(Spec->getTemplateArgs(),
1413+
Spec->getNumTemplateArgs());
1414+
InnerString = TemplateArgs + InnerString;
1415+
}
1416+
13981417
if (Kind)
13991418
InnerString = std::string(Kind) + " " + ID + InnerString;
14001419
else

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,8 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
10061006
if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod())
10071007
return Diag(ArgLoc, diag::err_template_arg_local_type)
10081008
<< QualType(Tag, 0);
1009-
else if (Tag && !Tag->getDecl()->getDeclName()) {
1009+
else if (Tag && !Tag->getDecl()->getDeclName() &&
1010+
!Tag->getDecl()->getTypedefForAnonDecl()) {
10101011
Diag(ArgLoc, diag::err_template_arg_unnamed_type);
10111012
Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
10121013
return true;

clang/test/SemaTemplate/class-template-id-2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace N {
44

55
template<> class A<int> { };
66

7-
template<> class A<float>; // expected-note{{forward declaration of 'class A'}}
7+
template<> class A<float>; // expected-note{{forward declaration of 'class A<float>'}}
88

99
class B : public A<int> { };
1010
}

clang/test/SemaTemplate/class-template-spec.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ int test_incomplete_specs(A<double, double> *a1,
1919
A<double> *a2)
2020
{
2121
(void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
22-
(void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A'}}
22+
(void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
2323
}
2424

2525
typedef float FLOAT;

clang/test/SemaTemplate/instantiation-backtrace.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// RUN: clang -fsyntax-only -verify %s
2-
template<typename T> struct A; // expected-note{{template is declared here}}
2+
template<typename T> struct A; // expected-note 2{{template is declared here}}
33

4-
template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}}
4+
template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \
5+
// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}}
56

67
template<typename T> struct C : B<T> { } ; // expected-note{{instantiation of template class}}
78

@@ -14,3 +15,9 @@ template<typename T> struct F : E<T(T)> { }; // expected-note{{instantiation of
1415
void f() {
1516
(void)sizeof(F<int>); // expected-note{{instantiation of template class}}
1617
}
18+
19+
typedef struct { } X;
20+
21+
void g() {
22+
(void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}}
23+
}

clang/test/SemaTemplate/instantiation-depth.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: clang -fsyntax-only -ftemplate-depth=5 -verify %s
22

33
template<typename T> struct X : X<T*> { }; // expected-error{{recursive template instantiation exceeded maximum depth of 5}} \
4-
// expected-note{{use -ftemplate-depth=N to increase recursive template instantiation depth}} \
4+
// expected-note{{use -ftemplate-depth-N to increase recursive template instantiation depth}} \
55
// expected-note 5 {{instantiation of template class}}
66

77
void test() {

0 commit comments

Comments
 (0)