Hi rsmith,

Substituted type template parameters should hold the original parameter
and the canonical type that was used for instantiation. We were missing
a canonicalization step and some extra sugar would have leaked through
into the instantiation.

Test case reduced from PR19372. It could use improvement if anyone has a
better idea for how to inject type sugar into this codepath.

http://reviews.llvm.org/D6237

Files:
  lib/Sema/SemaTemplateInstantiate.cpp
  test/SemaTemplate/crash-pr19372.cpp
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -1399,6 +1399,9 @@
 
     QualType Replacement = Arg.getAsType();
 
+    // Always canonicalize the replacement type.
+    Replacement = getSema().Context.getCanonicalType(Replacement);
+
     // TODO: only do this uniquing once, at the start of instantiation.
     QualType Result
       = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
@@ -1444,6 +1447,9 @@
   Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
   QualType Result = Arg.getAsType();
 
+  // Always canonicalize the replacement type.
+  Result = SemaRef.Context.getCanonicalType(Result);
+
   Result = getSema().Context.getSubstTemplateTypeParmType(
                                       TL.getTypePtr()->getReplacedParameter(),
                                                           Result);
Index: test/SemaTemplate/crash-pr19372.cpp
===================================================================
--- /dev/null
+++ test/SemaTemplate/crash-pr19372.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 %s -std=c++11 -verify
+
+// Reduced from user code in http://llvm.org/PR19372
+
+// expected-no-diagnostics
+
+template <typename _Tp, _Tp __v> struct integral_constant {
+  static constexpr _Tp value = __v;
+};
+template <template <typename...> class C, typename... Us>
+struct meta_bind_back {
+  template <typename... Ts> using apply = C<Ts..., Us...>;
+};
+template <template <typename...> class C, typename... As>
+using meta_apply = typename C<As...>::type;
+template <typename List> struct typelist_front {
+  using type = List;
+};
+template <template <typename...> class Fun> struct typelist_find_if {
+  struct type { };
+};
+template <template <typename...> class Fun, typename List>
+using typelist_find_if_t = typename typelist_find_if<Fun>::type;
+template <typename Concept, typename... Ts> struct models_;
+template <typename... Ts> using models = decltype(models_<Ts...>{});
+template <typename Concepts, typename... Ts>
+struct most_refined : typelist_front<typelist_find_if_t<
+                          meta_bind_back<models, Ts...>::template apply, int>> {
+};
+template <typename Concepts, typename... Ts>
+using most_refined_t = meta_apply<most_refined, Concepts, Ts...>;
+most_refined_t<int, int> x;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to