From: Douglas Gregor Date: Tue, 10 Mar 2009 18:33:27 +0000 (+0000) Subject: Add pretty-printing for class template specializations, e.g., X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=98137534e612c274ba270af99d73429043957e53;p=clang Add pretty-printing for class template specializations, e.g., 'struct A' 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66560 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index dbba5ab18a..46d81445b6 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -643,7 +643,7 @@ DIAG(err_template_spec_redecl_global_scope, ERROR, DIAG(err_template_recursion_depth_exceeded, ERROR, "recursive template instantiation exceeded maximum depth of %0") DIAG(note_template_recursion_depth, NOTE, - "use -ftemplate-depth=N to increase recursive template " + "use -ftemplate-depth-N to increase recursive template " "instantiation depth") DIAG(err_template_implicit_instantiate_undefined, ERROR, "implicit instantiation of undefined template %0") diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index f9cf847ee9..205ebef20b 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1287,10 +1287,11 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const { InnerString = Name->getName() + InnerString; } -void -ClassTemplateSpecializationType:: -getAsStringInternal(std::string &InnerString) const { - std::string SpecString = Template->getNameAsString(); +/// \brief Print a template argument list, including the '<' and '>' +/// enclosing the template arguments. +static std::string printTemplateArgumentList(const TemplateArgument *Args, + unsigned NumArgs) { + std::string SpecString; SpecString += '<'; for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { if (Arg) @@ -1298,22 +1299,22 @@ getAsStringInternal(std::string &InnerString) const { // Print the argument into a string. std::string ArgString; - switch (getArg(Arg).getKind()) { + switch (Args[Arg].getKind()) { case TemplateArgument::Type: - getArg(Arg).getAsType().getAsStringInternal(ArgString); + Args[Arg].getAsType().getAsStringInternal(ArgString); break; case TemplateArgument::Declaration: - ArgString = cast(getArg(Arg).getAsDecl())->getNameAsString(); + ArgString = cast(Args[Arg].getAsDecl())->getNameAsString(); break; case TemplateArgument::Integral: - ArgString = getArg(Arg).getAsIntegral()->toString(10, true); + ArgString = Args[Arg].getAsIntegral()->toString(10, true); break; case TemplateArgument::Expression: { llvm::raw_string_ostream s(ArgString); - getArg(Arg).getAsExpr()->printPretty(s); + Args[Arg].getAsExpr()->printPretty(s); break; } } @@ -1335,6 +1336,14 @@ getAsStringInternal(std::string &InnerString) const { SpecString += '>'; + return SpecString; +} + +void +ClassTemplateSpecializationType:: +getAsStringInternal(std::string &InnerString) const { + std::string SpecString = Template->getNameAsString(); + SpecString += printTemplateArgumentList(getArgs(), getNumArgs()); if (InnerString.empty()) InnerString.swap(SpecString); else @@ -1395,6 +1404,16 @@ void TagType::getAsStringInternal(std::string &InnerString) const { } else ID = ""; + // If this is a class template specialization, print the template + // arguments. + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(getDecl())) { + std::string TemplateArgs + = printTemplateArgumentList(Spec->getTemplateArgs(), + Spec->getNumTemplateArgs()); + InnerString = TemplateArgs + InnerString; + } + if (Kind) InnerString = std::string(Kind) + " " + ID + InnerString; else diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 281984de2c..fc1173d9d1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1006,7 +1006,8 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) return Diag(ArgLoc, diag::err_template_arg_local_type) << QualType(Tag, 0); - else if (Tag && !Tag->getDecl()->getDeclName()) { + else if (Tag && !Tag->getDecl()->getDeclName() && + !Tag->getDecl()->getTypedefForAnonDecl()) { Diag(ArgLoc, diag::err_template_arg_unnamed_type); Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here); return true; diff --git a/test/SemaTemplate/class-template-id-2.cpp b/test/SemaTemplate/class-template-id-2.cpp index 3014208b6e..5499c50a94 100644 --- a/test/SemaTemplate/class-template-id-2.cpp +++ b/test/SemaTemplate/class-template-id-2.cpp @@ -4,7 +4,7 @@ namespace N { template<> class A { }; - template<> class A; // expected-note{{forward declaration of 'class A'}} + template<> class A; // expected-note{{forward declaration of 'class A'}} class B : public A { }; } diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp index 023ba381ec..90ab39f32e 100644 --- a/test/SemaTemplate/class-template-spec.cpp +++ b/test/SemaTemplate/class-template-spec.cpp @@ -19,7 +19,7 @@ int test_incomplete_specs(A *a1, A *a2) { (void)a1->x; // expected-error{{incomplete definition of type 'A'}} - (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A'}} + (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A'}} } typedef float FLOAT; diff --git a/test/SemaTemplate/instantiation-backtrace.cpp b/test/SemaTemplate/instantiation-backtrace.cpp index 4c8ea13a8d..f8aabff097 100644 --- a/test/SemaTemplate/instantiation-backtrace.cpp +++ b/test/SemaTemplate/instantiation-backtrace.cpp @@ -1,7 +1,8 @@ // RUN: clang -fsyntax-only -verify %s -template struct A; // expected-note{{template is declared here}} +template struct A; // expected-note 2{{template is declared here}} -template struct B : A { }; // expected-error{{implicit instantiation of undefined template}} +template struct B : A { }; // expected-error{{implicit instantiation of undefined template}} \ +// expected-error{{implicit instantiation of undefined template 'struct A'}} template struct C : B { } ; // expected-note{{instantiation of template class}} @@ -14,3 +15,9 @@ template struct F : E { }; // expected-note{{instantiation of void f() { (void)sizeof(F); // expected-note{{instantiation of template class}} } + +typedef struct { } X; + +void g() { + (void)sizeof(B); // expected-note{{in instantiation of template class 'struct B' requested here}} +} diff --git a/test/SemaTemplate/instantiation-depth.cpp b/test/SemaTemplate/instantiation-depth.cpp index 25c40fce4d..06317d88d4 100644 --- a/test/SemaTemplate/instantiation-depth.cpp +++ b/test/SemaTemplate/instantiation-depth.cpp @@ -1,7 +1,7 @@ // RUN: clang -fsyntax-only -ftemplate-depth=5 -verify %s template struct X : X { }; // expected-error{{recursive template instantiation exceeded maximum depth of 5}} \ -// expected-note{{use -ftemplate-depth=N to increase recursive template instantiation depth}} \ +// expected-note{{use -ftemplate-depth-N to increase recursive template instantiation depth}} \ // expected-note 5 {{instantiation of template class}} void test() {