From: Alex Lorenz Date: Thu, 18 May 2017 18:06:07 +0000 (+0000) Subject: [index] Avoid one more crash caused by infinite recursion that happens when X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b7f27dbfdd43a5f42cc6f263eb50c22677eb4cb6;p=clang [index] Avoid one more crash caused by infinite recursion that happens when looking up a dependent name in a record that derives from itself rdar://32273000 Differential Revision: https://reviews.llvm.org/D33324 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303366 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index a7961ebe8c..980608570f 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -127,7 +127,11 @@ class CXXBasePaths { /// class subobjects for that class type. The key of the map is /// the cv-unqualified canonical type of the base class subobject. llvm::SmallDenseMap, 8> ClassSubobjects; - + + /// VisitedDependentRecords - Records the dependent records that have been + /// already visited. + llvm::SmallDenseSet 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. diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 746602d47b..fc4d8b1373 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -57,6 +57,7 @@ bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { void CXXBasePaths::clear() { Paths.clear(); ClassSubobjects.clear(); + VisitedDependentRecords.clear(); ScratchPath.clear(); DetectedVirtual = nullptr; } @@ -67,6 +68,7 @@ void CXXBasePaths::swap(CXXBasePaths &Other) { 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 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, dyn_cast_or_null(TN.getAsTemplateDecl())) BaseRecord = TD->getTemplatedDecl(); } - if (BaseRecord && !BaseRecord->hasDefinition()) - BaseRecord = nullptr; + if (BaseRecord) { + if (!BaseRecord->hasDefinition() || + VisitedDependentRecords.count(BaseRecord)) { + BaseRecord = nullptr; + } else { + VisitedDependentRecords.insert(BaseRecord); + } + } } else { BaseRecord = cast( BaseSpec.getType()->castAs()->getDecl()); diff --git a/test/Index/Core/index-dependent-source.cpp b/test/Index/Core/index-dependent-source.cpp index 8c097b935a..59c6286cd3 100644 --- a/test/Index/Core/index-dependent-source.cpp +++ b/test/Index/Core/index-dependent-source.cpp @@ -141,3 +141,20 @@ void undefinedTemplateLookup2(UserOfUndefinedTemplateClass &x) { x.lookup; typename UserOfUndefinedTemplateClass::Type y; } + +template struct Dropper; + +template struct Trait; + +template +struct Recurse : Trait::Type> { }; + +template +struct Trait : Recurse { +}; + +template +void infiniteTraitRecursion(Trait &t) { +// Shouldn't crash! + t.lookup; +}