aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/TreeTransform.h23
-rw-r--r--test/SemaTemplate/issue150.cpp26
2 files changed, 48 insertions, 1 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 1a5a98a23e..94aac52e5b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -4126,7 +4126,28 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
TypeLocBuilder &TLB,
SubstTemplateTypeParmTypeLoc TL) {
- return TransformTypeSpecType(TLB, TL);
+ const SubstTemplateTypeParmType *T = TL.getTypePtr();
+
+ // Substitute into the replacement type, which itself might involve something
+ // that needs to be transformed. This only tends to occur with default
+ // template arguments of template template parameters.
+ TemporaryBase Rebase(*this, TL.getNameLoc(), DeclarationName());
+ QualType Replacement = getDerived().TransformType(T->getReplacementType());
+ if (Replacement.isNull())
+ return QualType();
+
+ // Always canonicalize the replacement type.
+ Replacement = SemaRef.Context.getCanonicalType(Replacement);
+ QualType Result
+ = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(),
+ Replacement);
+
+ // Propagate type-source information.
+ SubstTemplateTypeParmTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+
}
template<typename Derived>
diff --git a/test/SemaTemplate/issue150.cpp b/test/SemaTemplate/issue150.cpp
index 0d7930723f..2cfa8c5cb1 100644
--- a/test/SemaTemplate/issue150.cpp
+++ b/test/SemaTemplate/issue150.cpp
@@ -69,3 +69,29 @@ namespace MultiReplacePartial {
int check0[is_same<X<int, int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1];
}
+
+namespace PR9016 {
+ template<typename > struct allocator ;
+ template<typename > struct less ;
+
+ template<class T, template<class> class Compare, class Default,
+ template<class> class Alloc>
+ struct interval_set { };
+
+ template <class X, template<class> class = less> struct interval_type_default {
+ typedef X type;
+ };
+
+ template <class T,
+ template<class _T, template<class> class Compare = less,
+ class = typename interval_type_default<_T,Compare>::type,
+ template<class> class = allocator> class IntervalSet>
+ struct ZZZ
+ {
+ IntervalSet<T> IntervalSetT;
+ };
+
+ void test() {
+ ZZZ<int, interval_set> zzz;
+ }
+}