]> granicus.if.org Git - clang/commitdiff
The AST importer had a bug where it would enter into an infinite recursion
authorDouglas Gregor <dgregor@apple.com>
Tue, 7 Jul 2015 06:20:12 +0000 (06:20 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 7 Jul 2015 06:20:12 +0000 (06:20 +0000)
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.

<rdar://problem/20315663>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241556 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
lib/AST/ASTImporter.cpp
lib/AST/DeclObjC.cpp

index fc8e958846955f82682c01dec0ad4533ed42b84f..7262253115799626f1bd6a3587a3306d224c9039 100644 (file)
@@ -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);
 
index 8460030b4b2002bb67ad7af9bc8486c3d61905c6..35c0f690db82210c53031c416d4e6a296dbe983a 100644 (file)
@@ -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<ObjCProtocolDecl *, 4> 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;
index da4bc549cf4275db0374d4d96c660e834c42f0ec..b540e37cd076dec6f3db6cf74e4acf24b66fae84 100644 (file)
@@ -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