From a5674729b27dfaea7169f8737bca4811b31de91c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 7 Jul 2015 06:20:12 +0000 Subject: [PATCH] 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 --- include/clang/AST/DeclObjC.h | 13 +++++++++++++ lib/AST/ASTImporter.cpp | 14 ++++++++++---- lib/AST/DeclObjC.cpp | 35 ++++++++++++++++++++++------------- 3 files changed, 45 insertions(+), 17 deletions(-) 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 -- 2.50.1