]> granicus.if.org Git - clang/commitdiff
Add pretty-printing for class template specializations, e.g.,
authorDouglas Gregor <dgregor@apple.com>
Tue, 10 Mar 2009 18:33:27 +0000 (18:33 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 10 Mar 2009 18:33:27 +0000 (18:33 +0000)
  '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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66560 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/AST/Type.cpp
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/class-template-id-2.cpp
test/SemaTemplate/class-template-spec.cpp
test/SemaTemplate/instantiation-backtrace.cpp
test/SemaTemplate/instantiation-depth.cpp

index dbba5ab18abf941ee35e652b783c84b1dd019f7b..46d81445b673e3d6c935f56d7c8e21b165a20e7e 100644 (file)
@@ -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")
index f9cf847ee9e01d80c85ddfa52393fe7177de5569..205ebef20b59fd4e541d544004c4d91a01f5bc8f 100644 (file)
@@ -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<NamedDecl>(getArg(Arg).getAsDecl())->getNameAsString();
+      ArgString = cast<NamedDecl>(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 = "<anonymous>";
 
+  // If this is a class template specialization, print the template
+  // arguments.
+  if (ClassTemplateSpecializationDecl *Spec 
+        = dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
+    std::string TemplateArgs 
+      = printTemplateArgumentList(Spec->getTemplateArgs(),
+                                  Spec->getNumTemplateArgs());
+    InnerString = TemplateArgs + InnerString;
+  }
+
   if (Kind)
     InnerString = std::string(Kind) + " " + ID + InnerString;
   else
index 281984de2c9810864f021fb20f8bc884864080f1..fc1173d9d16dac6ca27f53d464642a552cd189c8 100644 (file)
@@ -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;
index 3014208b6eacf34017d8e7d2cbd0093985e40793..5499c50a949f930b5762542442fba396b0e52c71 100644 (file)
@@ -4,7 +4,7 @@ namespace N {
 
   template<> class A<int> { };
 
-  template<> class A<float>; // expected-note{{forward declaration of 'class A'}}
+  template<> class A<float>; // expected-note{{forward declaration of 'class A<float>'}}
 
   class B : public A<int> { };
 }
index 023ba381ec4fbce48b706fb2d1712ee2d23cb0c5..90ab39f32e90815ddcbd53137d30661ca4d50c3e 100644 (file)
@@ -19,7 +19,7 @@ int test_incomplete_specs(A<double, double> *a1,
                           A<double> *a2)
 {
   (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
-  (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A'}}
+  (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
 }
 
 typedef float FLOAT;
index 4c8ea13a8d7f19739b32ac450182f091f26633ad..f8aabff0973f9afdd3cc27fbdbf59ae252a875ba 100644 (file)
@@ -1,7 +1,8 @@
 // RUN: clang -fsyntax-only -verify %s
-template<typename T> struct A; // expected-note{{template is declared here}}
+template<typename T> struct A; // expected-note 2{{template is declared here}}
 
-template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}}
+template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \
+// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}}
 
 template<typename T> struct C : B<T> { } ; // expected-note{{instantiation of template class}}
 
@@ -14,3 +15,9 @@ template<typename T> struct F : E<T(T)> { }; // expected-note{{instantiation of
 void f() {
  (void)sizeof(F<int>); // expected-note{{instantiation of template class}}
 }
+
+typedef struct { } X;
+
+void g() {
+  (void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}}
+}
index 25c40fce4d1afafdadfd4d7f1ebb59162803ff51..06317d88d485054e29d583900825f85e6ae861b7 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: clang -fsyntax-only -ftemplate-depth=5 -verify %s
 
 template<typename T> struct X : X<T*> { }; // 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() {