From: Douglas Gregor Date: Tue, 7 Jul 2015 06:20:12 +0000 (+0000) Subject: The AST importer had a bug where it would enter into an infinite recursion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a5674729b27dfaea7169f8737bca4811b31de91c;p=clang The AST importer had a bug where it would enter into an infinite recursion when importing type parameter lists. The reason is that type parameters have their DeclContexts set to the interface that is parameterized with those types, and the importer would follow that loop and blow the stack out. I've changed the way this works so that the type parameters are only imported after the interface that contains them has been registered via the Imported() function. This is tested by LLDB. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241556 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index fc8e958846..7262253115 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -956,6 +956,12 @@ public: /// has type parameters, skipping any declarations that do not. ObjCTypeParamList *getTypeParamList() const; + /// Set the type parameters of this class. + /// + /// This function is used by the AST importer, which must import the type + /// parameters after creating their DeclContext to avoid loops. + void setTypeParamList(ObjCTypeParamList *TPL); + /// Retrieve the type parameters written on this particular declaration of /// the class. ObjCTypeParamList *getTypeParamListAsWritten() const { @@ -1963,6 +1969,13 @@ public: /// extension. ObjCTypeParamList *getTypeParamList() const { return TypeParamList; } + /// Set the type parameters of this category. + /// + /// This function is used by the AST importer, which must import the type + /// parameters after creating their DeclContext to avoid loops. + void setTypeParamList(ObjCTypeParamList *TPL); + + ObjCCategoryImplDecl *getImplementation() const; void setImplementation(ObjCCategoryImplDecl *ImplD); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 8460030b4b..35c0f690db 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3491,13 +3491,16 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { Importer.Import(D->getCategoryNameLoc()), Name.getAsIdentifierInfo(), ToInterface, - ImportObjCTypeParamList( - D->getTypeParamList()), + /*TypeParamList=*/nullptr, Importer.Import(D->getIvarLBraceLoc()), Importer.Import(D->getIvarRBraceLoc())); ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); Importer.Imported(D, ToCategory); + // Import the type parameter list after calling Imported, to avoid + // loops when bringing in their DeclContext. + ToCategory->setTypeParamList(ImportObjCTypeParamList( + D->getTypeParamList())); // Import protocols SmallVector Protocols; @@ -3819,14 +3822,17 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), - ImportObjCTypeParamList( - D->getTypeParamListAsWritten()), + /*TypeParamList=*/nullptr, /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); } Importer.Imported(D, ToIface); + // Import the type parameter list after calling Imported, to avoid + // loops when bringing in their DeclContext. + ToIface->setTypeParamList(ImportObjCTypeParamList( + D->getTypeParamListAsWritten())); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface)) return nullptr; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index da4bc549cf..b540e37cd0 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -259,6 +259,15 @@ ObjCTypeParamList *ObjCInterfaceDecl::getTypeParamList() const { return nullptr; } +void ObjCInterfaceDecl::setTypeParamList(ObjCTypeParamList *TPL) { + TypeParamList = TPL; + if (!TPL) + return; + // Set the declaration context of each of the type parameters. + for (auto typeParam : *TypeParamList) + typeParam->setDeclContext(this); +} + ObjCInterfaceDecl *ObjCInterfaceDecl::getSuperClass() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -1302,7 +1311,7 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *PrevDecl, bool IsInternal) : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc), - redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(typeParamList), + redeclarable_base(C), TypeForDecl(nullptr), TypeParamList(nullptr), Data() { setPreviousDecl(PrevDecl); @@ -1312,11 +1321,7 @@ ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, setImplicit(IsInternal); - // Update the declaration context of the type parameters. - if (typeParamList) { - for (auto typeParam : *typeParamList) - typeParam->setDeclContext(this); - } + setTypeParamList(typeParamList); } void ObjCInterfaceDecl::LoadExternalDefinition() const { @@ -1799,16 +1804,11 @@ ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc, SourceLocation IvarLBraceLoc, SourceLocation IvarRBraceLoc) : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), - ClassInterface(IDecl), TypeParamList(typeParamList), + ClassInterface(IDecl), TypeParamList(nullptr), NextClassCategory(nullptr), CategoryNameLoc(CategoryNameLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { - // Set the declaration context of each of the type parameters. - if (typeParamList) { - for (auto typeParam : *typeParamList) { - typeParam->setDeclContext(this); - } - } + setTypeParamList(typeParamList); } ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, @@ -1853,6 +1853,15 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) { getASTContext().setObjCImplementation(this, ImplD); } +void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) { + TypeParamList = TPL; + if (!TPL) + return; + // Set the declaration context of each of the type parameters. + for (auto typeParam : *TypeParamList) + typeParam->setDeclContext(this); +} + //===----------------------------------------------------------------------===// // ObjCCategoryImplDecl