]> granicus.if.org Git - clang/commitdiff
When producing a name of a partial specialization in a diagnostic, use the
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 24 Dec 2016 04:09:05 +0000 (04:09 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 24 Dec 2016 04:09:05 +0000 (04:09 +0000)
template arguments as written rather than the canonical template arguments,
so we print more user-friendly names for template parameters.

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

include/clang/AST/TemplateBase.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/DeclTemplate.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
test/Modules/cxx-templates.cpp
test/SemaTemplate/deduction.cpp
test/SemaTemplate/instantiation-default-1.cpp
test/SemaTemplate/ms-class-specialization-class-scope.cpp

index 553956259a55660ccaa8b8d11e7a7da63f7b2dcb..7f289862578da545d7b148fb95cd67400cc19839 100644 (file)
@@ -596,6 +596,10 @@ public:
     return getTrailingObjects<TemplateArgumentLoc>();
   }
 
+  llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
+    return llvm::makeArrayRef(getTemplateArgs(), NumTemplateArgs);
+  }
+
   const TemplateArgumentLoc &operator[](unsigned I) const {
     return getTemplateArgs()[I];
   }
index 3b43a6474fb67c61fa38c7717ec6cb980edbf59a..da8f532f3a89f9eb354d56f2ba85a042c0df0be0 100644 (file)
@@ -4103,9 +4103,9 @@ def note_template_class_instantiation_was_here : Note<
 def note_template_class_explicit_specialization_was_here : Note<
   "class template %0 was explicitly specialized here">;
 def note_template_class_instantiation_here : Note<
-  "in instantiation of template class %0 requested here">;
+  "in instantiation of template class %q0 requested here">;
 def note_template_member_class_here : Note<
-  "in instantiation of member class %0 requested here">;
+  "in instantiation of member class %q0 requested here">;
 def note_template_member_function_here : Note<
   "in instantiation of member function %q0 requested here">;
 def note_function_template_spec_here : Note<
index 1b3cddbb10357de61150823763117f519eb43ac5..8643cbfcd960accf50613c7743a0dd1999d8d590 100644 (file)
@@ -725,9 +725,16 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic(
     raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
   NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
 
-  const TemplateArgumentList &TemplateArgs = getTemplateArgs();
-  TemplateSpecializationType::PrintTemplateArgumentList(
-      OS, TemplateArgs.asArray(), Policy);
+  auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
+  if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
+          PS ? PS->getTemplateArgsAsWritten() : nullptr) {
+    TemplateSpecializationType::PrintTemplateArgumentList(
+        OS, ArgsAsWritten->arguments(), Policy);
+  } else {
+    const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+    TemplateSpecializationType::PrintTemplateArgumentList(
+        OS, TemplateArgs.asArray(), Policy);
+  }
 }
 
 ClassTemplateDecl *
@@ -1057,9 +1064,16 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
     raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
   NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
 
-  const TemplateArgumentList &TemplateArgs = getTemplateArgs();
-  TemplateSpecializationType::PrintTemplateArgumentList(
-      OS, TemplateArgs.asArray(), Policy);
+  auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
+  if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
+          PS ? PS->getTemplateArgsAsWritten() : nullptr) {
+    TemplateSpecializationType::PrintTemplateArgumentList(
+        OS, ArgsAsWritten->arguments(), Policy);
+  } else {
+    const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+    TemplateSpecializationType::PrintTemplateArgumentList(
+        OS, TemplateArgs.asArray(), Policy);
+  }
 }
 
 VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
index 80567c309c5e976df78d8de81e4523e488410e15..bbf1965eef40f3265ba866d8183dcc6c2a34add9 100644 (file)
@@ -6638,8 +6638,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
       TUK = TUK_Declaration;
     } else if (Def) {
       SourceRange Range(TemplateNameLoc, RAngleLoc);
-      Diag(TemplateNameLoc, diag::err_redefinition)
-        << Context.getTypeDeclType(Specialization) << Range;
+      Diag(TemplateNameLoc, diag::err_redefinition) << Specialization << Range;
       Diag(Def->getLocation(), diag::note_previous_definition);
       Specialization->setInvalidDecl();
       return true;
index 4e3862a14d65bed44c2bfbd59db7ba163e917c34..382c23ce87f004d767352710ae02737ad40dfb22 100644 (file)
@@ -423,8 +423,7 @@ void Sema::PrintInstantiationStack() {
         if (isa<ClassTemplateSpecializationDecl>(Record))
           DiagID = diag::note_template_class_instantiation_here;
         Diags.Report(Active->PointOfInstantiation, DiagID)
-          << Context.getTypeDeclType(Record)
-          << Active->InstantiationRange;
+          << Record << Active->InstantiationRange;
       } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
         unsigned DiagID;
         if (Function->getPrimaryTemplate())
@@ -490,7 +489,7 @@ void Sema::PrintInstantiationStack() {
             dyn_cast<ClassTemplatePartialSpecializationDecl>(Active->Entity)) {
         Diags.Report(Active->PointOfInstantiation,
                      diag::note_partial_spec_deduct_instantiation_here)
-          << Context.getTypeDeclType(PartialSpec)
+          << PartialSpec
           << getTemplateArgumentBindingsText(
                                          PartialSpec->getTemplateParameters(), 
                                              Active->TemplateArgs, 
index 1af47a0ed56f066f5bce91426a40645995ac14b0..ec2e380864bff74084ff5688f7907bbdd243b61d 100644 (file)
@@ -283,7 +283,7 @@ namespace spec_vs_expl_inst {
     template <typename STRING_TYPE> class BasicStringPiece {};
     template class BasicStringPiece<int>;  // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}}
     extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
-    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece<int>'}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'BasicStringPiece<int>'}}
   }
 
   namespace DIS_WithDefinedTemplate {
@@ -313,14 +313,14 @@ namespace spec_vs_expl_inst {
     template <typename STRING_TYPE> class BasicStringPiece;
     template <> class BasicStringPiece<int> { };  // expected-note {{previous definition is here}} expected-note {{previous}}
     template class BasicStringPiece<int>; // expected-warning {{has no effect}}
-    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece<int>'}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'BasicStringPiece<int>'}}
   }
 
   namespace SDS {
     template <typename STRING_TYPE> class BasicStringPiece;
     template <> class BasicStringPiece<int> { };  // expected-note {{previous definition is here}}
     extern template class BasicStringPiece<int>;
-    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece<int>'}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'BasicStringPiece<int>'}}
   }
 
   namespace SDIS {
@@ -328,7 +328,7 @@ namespace spec_vs_expl_inst {
     template <> class BasicStringPiece<int> { };  // expected-note {{previous definition is here}}
     extern template class BasicStringPiece<int>;
     template class BasicStringPiece<int>;
-    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece<int>'}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'BasicStringPiece<int>'}}
   }
 
 }
index c2d38497dd7b0ce0205e6936bc04ca47bd93134a..401b7704900ba93d82dcaf5d7c3ff6cb4102e152 100644 (file)
@@ -195,8 +195,8 @@ namespace hidden_specializations {
     cls<void>::nested_cls_t<int> *nk2; // ok
     cls<void>::nested_cls_t<char> *nk3; // ok
     cls<int> uk1; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}}
-    cls<int*> uk3; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} expected-error 1+{{definition of}}
-    cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} expected-error 1+{{definition of}}
+    cls<int*> uk3; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
+    cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
     cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
     cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
     cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
@@ -211,8 +211,8 @@ namespace hidden_specializations {
     (void)sizeof(var<void>); // ok
     (void)sizeof(var<char>); // ok
     (void)sizeof(var<int>); // expected-error 1+{{explicit specialization of 'var<int>' must be imported}}
-    (void)sizeof(var<int*>); // expected-error 1+{{partial specialization of 'var<type-parameter-0-0 *>' must be imported}}
-    (void)sizeof(var<char*>); // expected-error 1+{{partial specialization of 'var<type-parameter-0-0 *>' must be imported}}
+    (void)sizeof(var<int*>); // expected-error 1+{{partial specialization of 'var<T *>' must be imported}}
+    (void)sizeof(var<char*>); // expected-error 1+{{partial specialization of 'var<T *>' must be imported}}
     (void)sizeof(cls<void>::nested_var); // ok
     (void)cls<void>::nested_var; // expected-error 1+{{explicit specialization of 'nested_var' must be imported}}
     (void)sizeof(cls<void>::nested_var_t<int>); // expected-error 1+{{explicit specialization of 'nested_var_t' must be imported}}
@@ -224,10 +224,10 @@ namespace hidden_specializations {
   int cls<int>::nested_var; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}}
   enum cls<int>::nested_enum : int {}; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}}
 
-  template<typename T> void cls<T*>::nested_fn() {} // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
-  template<typename T> struct cls<T*>::nested_cls {}; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
-  template<typename T> int cls<T*>::nested_var; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
-  template<typename T> enum cls<T*>::nested_enum : int {}; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
+  template<typename T> void cls<T*>::nested_fn() {} // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
+  template<typename T> struct cls<T*>::nested_cls {}; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
+  template<typename T> int cls<T*>::nested_var; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
+  template<typename T> enum cls<T*>::nested_enum : int {}; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
 }
 
 namespace Std {
index 2713ac1d43ef233df96d6f73c3b460ecd7d9dfdf..8cd4331755a132b1eaec649e95f851648af26a5c 100644 (file)
@@ -336,3 +336,18 @@ namespace member_pointer {
   };
   C<B<int, &A::f>> c;
 }
+
+namespace deduction_substitution_failure {
+  template<typename T> struct Fail { typedef typename T::error error; }; // expected-error {{prior to '::'}}
+
+  template<typename T, typename U> struct A {};
+  template<typename T> struct A<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}
+  A<int, int> ai; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}}
+
+  // FIXME: This tickles an assertion.
+#if 0
+  template<typename T, typename U> int B; // expected-warning 0-1 {{extension}}
+  template<typename T> int B<T, typename Fail<T>::error> {};
+  int bi = B<char, char>;
+#endif
+}
index 99154a5cc46066aadf2d69d458491ae81a2d5181..ab9eca75e239bc637cc1f1a7a0fd8ab688162f21 100644 (file)
@@ -36,7 +36,7 @@ typedef int& int_ref_t;
 Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
 
 
-template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<const int>'}}
+template<> struct Def1<const int> { }; // expected-error{{redefinition of 'Def1<const int, const int>'}}
 
 template<typename T, typename T2 = T&> struct Def3;
 
index 3ebb1c9c555ea2eb7ada2260ea4f2dcdcfbedafa..fc51c23a34e9107bc5dcc83df7115265492c18f8 100644 (file)
@@ -19,7 +19,7 @@ public:
   X<double>::y c;
 
   template<> struct X<float> {}; // expected-note {{previous definition is here}}
-  template<> struct X<float> {}; // expected-error {{redefinition of 'A::X<float>'}}
+  template<> struct X<float> {}; // expected-error {{redefinition of 'X<float>'}}
 };
 
 A::X<void>::x axv;