]> granicus.if.org Git - clang/commitdiff
When transforming a substituted template type parameter, try to
authorDouglas Gregor <dgregor@apple.com>
Sat, 5 Mar 2011 17:19:27 +0000 (17:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 5 Mar 2011 17:19:27 +0000 (17:19 +0000)
transform the type that replaces the template type parameter. In the
vast majority of cases, there's nothing to do, because most template
type parameters are replaced with something non-dependent that doesn't
need further transformation. However, when we're dealing with the
default template arguments of template template parameters, we might
end up replacing a template parameter (of the template template
parameter) with a template parameter of the enclosing template.

This addresses part of PR9016, but not within function
templates. That's a separate issue.

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

lib/Sema/TreeTransform.h
test/SemaTemplate/issue150.cpp

index 1a5a98a23e650ef22c5b4747bea79b2359b052a4..94aac52e5b0240e901ba0f60e48aeabcda134ded 100644 (file)
@@ -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>
index 0d7930723fca27111e390c3136f1aa7190d3afb5..2cfa8c5cb1e70ff9f67f6e4afe5036c40dd22a64 100644 (file)
@@ -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;
+  }
+}