[PATCH] D33324: [index] Avoid infinite recursion when looking up a dependent name

Alex Lorenz via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu May 18 10:13:50 PDT 2017


arphaman created this revision.

This is a regression introduced by r302632 .


Repository:
  rL LLVM

https://reviews.llvm.org/D33324

Files:
  include/clang/AST/CXXInheritance.h
  lib/AST/CXXInheritance.cpp
  test/Index/Core/index-dependent-source.cpp


Index: test/Index/Core/index-dependent-source.cpp
===================================================================
--- test/Index/Core/index-dependent-source.cpp
+++ test/Index/Core/index-dependent-source.cpp
@@ -141,3 +141,20 @@
   x.lookup;
   typename UserOfUndefinedTemplateClass<T>::Type y;
 }
+
+template<typename T> struct Dropper;
+
+template<typename T> struct Trait;
+
+template<typename T>
+struct Recurse : Trait<typename Dropper<T>::Type> { };
+
+template<typename T>
+struct Trait : Recurse<T> {
+};
+
+template<typename T>
+void infiniteTraitRecursion(Trait<T> &t) {
+// Shouldn't crash!
+  t.lookup;
+}
Index: lib/AST/CXXInheritance.cpp
===================================================================
--- lib/AST/CXXInheritance.cpp
+++ lib/AST/CXXInheritance.cpp
@@ -57,6 +57,7 @@
 void CXXBasePaths::clear() {
   Paths.clear();
   ClassSubobjects.clear();
+  VisitedDependentRecords.clear();
   ScratchPath.clear();
   DetectedVirtual = nullptr;
 }
@@ -67,6 +68,7 @@
   std::swap(Origin, Other.Origin);
   Paths.swap(Other.Paths);
   ClassSubobjects.swap(Other.ClassSubobjects);
+  VisitedDependentRecords.swap(Other.VisitedDependentRecords);
   std::swap(FindAmbiguities, Other.FindAmbiguities);
   std::swap(RecordPaths, Other.RecordPaths);
   std::swap(DetectVirtual, Other.DetectVirtual);
@@ -278,8 +280,14 @@
                   dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
             BaseRecord = TD->getTemplatedDecl();
         }
-        if (BaseRecord && !BaseRecord->hasDefinition())
-          BaseRecord = nullptr;
+        if (BaseRecord) {
+          if (!BaseRecord->hasDefinition())
+            BaseRecord = nullptr;
+          else if (VisitedDependentRecords.count(BaseRecord))
+            BaseRecord = nullptr;
+          else
+            VisitedDependentRecords.insert(BaseRecord);
+        }
       } else {
         BaseRecord = cast<CXXRecordDecl>(
             BaseSpec.getType()->castAs<RecordType>()->getDecl());
Index: include/clang/AST/CXXInheritance.h
===================================================================
--- include/clang/AST/CXXInheritance.h
+++ include/clang/AST/CXXInheritance.h
@@ -127,7 +127,11 @@
   /// class subobjects for that class type. The key of the map is
   /// the cv-unqualified canonical type of the base class subobject.
   llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
-  
+
+  /// VisitedDependentRecords - Records the dependent records that have been
+  /// already visited.
+  llvm::SmallDenseSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
+
   /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
   /// ambiguous paths while it is looking for a path from a derived
   /// type to a base type.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33324.99456.patch
Type: text/x-patch
Size: 2760 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170518/b4fb4ed3/attachment.bin>


More information about the cfe-commits mailing list