r267453 - Refactor traversal of bases in deduction of template parameters from base

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 25 12:28:09 PDT 2016


Author: rsmith
Date: Mon Apr 25 14:28:08 2016
New Revision: 267453

URL: http://llvm.org/viewvc/llvm-project?rev=267453&view=rev
Log:
Refactor traversal of bases in deduction of template parameters from base
classes of an argument to use CXXRecordDecl::forallBases. Fix forallBases to
only visit each base class once.

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

Modified: cfe/trunk/lib/AST/CXXInheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=267453&r1=267452&r2=267453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CXXInheritance.cpp (original)
+++ cfe/trunk/lib/AST/CXXInheritance.cpp Mon Apr 25 14:28:08 2016
@@ -137,6 +137,7 @@ 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;
@@ -158,12 +159,14 @@ bool CXXRecordDecl::forallBases(ForallBa
         AllMatches = false;
         continue;
       }
-      
-      Queue.push_back(Base);
-      if (!BaseMatches(Base)) {
-        if (AllowShortCircuit) return false;
-        AllMatches = false;
-        continue;
+
+      if (Enqueued.insert(Base).second) {
+        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=267453&r1=267452&r2=267453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Apr 25 14:28:08 2016
@@ -1454,54 +1454,35 @@ 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;
-      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;
+      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;
         }
 
-        // 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>());
-        }
-      }
+        // Keep going.
+        return true;
+      });
 
       if (Successful)
         return Sema::TDK_Success;




More information about the cfe-commits mailing list