r270016 - Fix PR27601 by reverting [r267453] - Refactor traversal of bases in deduction of template parameters from base

Faisal Vali via cfe-commits cfe-commits at lists.llvm.org
Wed May 18 19:28:21 PDT 2016


Author: faisalv
Date: Wed May 18 21:28:21 2016
New Revision: 270016

URL: http://llvm.org/viewvc/llvm-project?rev=270016&view=rev
Log:
Fix PR27601 by reverting [r267453] - Refactor traversal of bases in deduction of template parameters from base

This reversal is being done with r267453's author's (i.e. Richard Smith's) permission.

This fixes https://llvm.org/bugs/show_bug.cgi?id=27601 

Also, per Richard's request the examples from the bug report have been added to our test suite.


Modified:
    cfe/trunk/lib/AST/CXXInheritance.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/test/SemaTemplate/deduction.cpp

Modified: cfe/trunk/lib/AST/CXXInheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=270016&r1=270015&r2=270016&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CXXInheritance.cpp (original)
+++ cfe/trunk/lib/AST/CXXInheritance.cpp Wed May 18 21:28:21 2016
@@ -137,7 +137,6 @@ CXXRecordDecl::isCurrentInstantiation(co
 bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
                                 bool AllowShortCircuit) const {
   SmallVector<const CXXRecordDecl*, 8> Queue;
-  llvm::SmallPtrSet<const CXXRecordDecl*, 8> Enqueued;
 
   const CXXRecordDecl *Record = this;
   bool AllMatches = true;
@@ -159,14 +158,12 @@ bool CXXRecordDecl::forallBases(ForallBa
         AllMatches = false;
         continue;
       }
-
-      if (Enqueued.insert(Base).second) {
-        Queue.push_back(Base);
-        if (!BaseMatches(Base)) {
-          if (AllowShortCircuit) return false;
-          AllMatches = false;
-          continue;
-        }
+      
+      Queue.push_back(Base);
+      if (!BaseMatches(Base)) {
+        if (AllowShortCircuit) return false;
+        AllMatches = false;
+        continue;
       }
     }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=270016&r1=270015&r2=270016&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed May 18 21:28:21 2016
@@ -1454,35 +1454,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema
       //   otherwise fail. If they yield more than one possible deduced A, the
       //   type deduction fails.
 
+      // Reset the incorrectly deduced argument from above.
+      Deduced = DeducedOrig;
+
+      // Use data recursion to crawl through the list of base classes.
+      // Visited contains the set of nodes we have already visited, while
+      // ToVisit is our stack of records that we still need to visit.
+      llvm::SmallPtrSet<const RecordType *, 8> Visited;
+      SmallVector<const RecordType *, 8> ToVisit;
+      ToVisit.push_back(RecordT);
       bool Successful = false;
-      RecordT->getAsCXXRecordDecl()->forallBases([&](
-          const CXXRecordDecl *Base) {
-        // Start with a fresh copy of the old deduced arguments.
-        SmallVector<DeducedTemplateArgument, 8> DeducedBase(DeducedOrig.begin(),
-                                                            DeducedOrig.end());
-
-        TemplateDeductionInfo BaseInfo(Info.getLocation());
-        Sema::TemplateDeductionResult BaseResult =
-            DeduceTemplateArguments(S, TemplateParams, SpecParam,
-                                    S.Context.getRecordType(Base),
-                                    BaseInfo, DeducedBase);
-
-        // If template argument deduction for this base was successful,
-        // note that we had some success. Otherwise, ignore any deductions
-        // from this base class.
-        if (BaseResult == Sema::TDK_Success) {
-          // FIXME: If we've already been successful, deduction should fail
-          // due to ambiguity.
-          Successful = true;
-          Deduced.swap(DeducedBase);
-          Info.Param = BaseInfo.Param;
-          Info.FirstArg = BaseInfo.FirstArg;
-          Info.SecondArg = BaseInfo.SecondArg;
+      while (!ToVisit.empty()) {
+        // Retrieve the next class in the inheritance hierarchy.
+        const RecordType *NextT = ToVisit.pop_back_val();
+
+        // If we have already seen this type, skip it.
+        if (!Visited.insert(NextT).second)
+          continue;
+
+        // If this is a base class, try to perform template argument
+        // deduction from it.
+        if (NextT != RecordT) {
+          TemplateDeductionInfo BaseInfo(Info.getLocation());
+          Sema::TemplateDeductionResult BaseResult =
+              DeduceTemplateArguments(S, TemplateParams, SpecParam,
+                                      QualType(NextT, 0), BaseInfo, Deduced);
+
+          // If template argument deduction for this base was successful,
+          // note that we had some success. Otherwise, ignore any deductions
+          // from this base class.
+          if (BaseResult == Sema::TDK_Success) {
+            Successful = true;
+            DeducedOrig.clear();
+            DeducedOrig.append(Deduced.begin(), Deduced.end());
+            Info.Param = BaseInfo.Param;
+            Info.FirstArg = BaseInfo.FirstArg;
+            Info.SecondArg = BaseInfo.SecondArg;
+          } else
+            Deduced = DeducedOrig;
         }
 
-        // Keep going.
-        return true;
-      });
+        // Visit base classes
+        CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
+        for (const auto &Base : Next->bases()) {
+          assert(Base.getType()->isRecordType() &&
+                 "Base class that isn't a record?");
+          ToVisit.push_back(Base.getType()->getAs<RecordType>());
+        }
+      }
 
       if (Successful)
         return Sema::TDK_Success;

Modified: cfe/trunk/test/SemaTemplate/deduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/deduction.cpp?rev=270016&r1=270015&r2=270016&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/deduction.cpp (original)
+++ cfe/trunk/test/SemaTemplate/deduction.cpp Wed May 18 21:28:21 2016
@@ -218,3 +218,50 @@ namespace NonDeducedNestedNameSpecifier
   template<typename T> int f(A<T>, typename A<T>::template B<T>);
   int k = f(A<int>(), 0);
 }
+
+namespace PR27601_RecursivelyInheritedBaseSpecializationsDeductionAmbiguity {
+namespace ns1 {
+
+template<class...> struct B { };
+template<class H, class ... Ts> struct B<H, Ts...> : B<> { };
+template<class ... Ts> struct D : B<Ts...> { };
+
+template<class T, class ... Ts> void f(B<T, Ts...> &) { }
+
+int main() {
+  D<int, char> d;
+  f<int>(d);
+}
+} //end ns1
+
+namespace ns2 {
+
+template <int i, typename... Es> struct tup_impl;
+
+template <int i> struct tup_impl<i> {}; // empty tail
+
+template <int i, typename Head, typename... Tail>
+struct tup_impl<i, Head, Tail...> : tup_impl<i + 1, Tail...> {
+  using value_type = Head;
+  Head head;
+};
+
+template <typename... Es> struct tup : tup_impl<0, Es...> {};
+
+template <typename Head, int i, typename... Tail>
+Head &get_helper(tup_impl<i, Head, Tail...> &t) {
+  return t.head;
+}
+
+template <typename Head, int i, typename... Tail>
+Head const &get_helper(tup_impl<i, Head, Tail...> const &t) {
+  return t.head;
+}
+
+int main() {
+  tup<int, double, char> t;
+  get_helper<double>(t);
+  return 0;
+}
+} // end ns2 
+}
\ No newline at end of file




More information about the cfe-commits mailing list