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