[cfe-commits] r149535 - in /cfe/trunk: include/clang/AST/ASTImporter.h lib/AST/ASTImporter.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 1 13:00:38 PST 2012


Author: dgregor
Date: Wed Feb  1 15:00:38 2012
New Revision: 149535

URL: http://llvm.org/viewvc/llvm-project?rev=149535&view=rev
Log:
Make sure that imported definitions get completed before we add
anything into the corresponding DeclContext. Co-hacked with Sean;
fixes <rdar://problem/10768928>.

Modified:
    cfe/trunk/include/clang/AST/ASTImporter.h
    cfe/trunk/lib/AST/ASTImporter.cpp

Modified: cfe/trunk/include/clang/AST/ASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=149535&r1=149534&r2=149535&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)
+++ cfe/trunk/include/clang/AST/ASTImporter.h Wed Feb  1 15:00:38 2012
@@ -255,6 +255,12 @@
     
     /// \brief Return the set of declarations that we know are not equivalent.
     NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
+
+    /// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl.
+    /// Mark the Decl as complete, filling it in as much as possible.
+    ///
+    /// \param D A declaration in the "to" context.
+    virtual void CompleteDecl(Decl* D);
     
     /// \brief Note that we have imported the "from" declaration by mapping it
     /// to the (potentially-newly-created) "to" declaration.

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=149535&r1=149534&r2=149535&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Feb  1 15:00:38 2012
@@ -86,7 +86,7 @@
     void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
                                   DeclarationNameInfo& To);
     void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
-                            
+                        
     /// \brief What we should import from the definition.
     enum ImportDefinitionKind { 
       /// \brief Import the default subset of the definition, which might be
@@ -100,14 +100,19 @@
       IDK_Basic
     };
 
+    bool shouldForceImportDeclContext(ImportDefinitionKind IDK) {
+      return IDK == IDK_Everything ||
+             (IDK == IDK_Default && !Importer.isMinimalImport());
+    }
+
     bool ImportDefinition(RecordDecl *From, RecordDecl *To, 
                           ImportDefinitionKind Kind = IDK_Default);
     bool ImportDefinition(EnumDecl *From, EnumDecl *To,
-                          bool ForceImport = false);
+                          ImportDefinitionKind Kind = IDK_Default);
     bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
-                          bool ForceImport = false);
+                          ImportDefinitionKind Kind = IDK_Default);
     bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To,
-                          bool ForceImport = false);
+                          ImportDefinitionKind Kind = IDK_Default);
     TemplateParameterList *ImportTemplateParameterList(
                                                  TemplateParameterList *Params);
     TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
@@ -1793,7 +1798,7 @@
   llvm_unreachable("Unknown name kind.");
 }
 
-void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
+void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {  
   if (Importer.isMinimalImport() && !ForceImport) {
     Importer.ImportContext(FromDC);
     return;
@@ -1892,8 +1897,7 @@
       ToCXX->setBases(Bases.data(), Bases.size());
   }
   
-  if (Kind == IDK_Everything || 
-      (Kind == IDK_Default && !Importer.isMinimalImport()))
+  if (shouldForceImportDeclContext(Kind))
     ImportDeclContext(From, /*ForceImport=*/true);
   
   To->completeDefinition();
@@ -1901,9 +1905,12 @@
 }
 
 bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, 
-                                       bool ForceImport) {
-  if (To->getDefinition() || To->isBeingDefined())
+                                       ImportDefinitionKind Kind) {
+  if (To->getDefinition() || To->isBeingDefined()) {
+    if (Kind == IDK_Everything)
+      ImportDeclContext(From, /*ForceImport=*/true);
     return false;
+  }
   
   To->startDefinition();
 
@@ -1914,8 +1921,9 @@
   QualType ToPromotionType = Importer.Import(From->getPromotionType());
   if (ToPromotionType.isNull())
     return true;
-  
-  ImportDeclContext(From, ForceImport);
+
+  if (shouldForceImportDeclContext(Kind))
+    ImportDeclContext(From, /*ForceImport=*/true);
   
   // FIXME: we might need to merge the number of positive or negative bits
   // if the enumerator lists don't match.
@@ -3125,9 +3133,10 @@
 
 bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, 
                                        ObjCProtocolDecl *To,
-                                       bool ForceImport) {
+                                       ImportDefinitionKind Kind) {
   if (To->getDefinition()) {
-    ImportDeclContext(From);
+    if (shouldForceImportDeclContext(Kind))
+      ImportDeclContext(From);
     return false;
   }
 
@@ -3155,8 +3164,10 @@
   To->setProtocolList(Protocols.data(), Protocols.size(),
                       ProtocolLocs.data(), Importer.getToContext());
 
-  // Import all of the members of this protocol.
-  ImportDeclContext(From);
+  if (shouldForceImportDeclContext(Kind)) {
+    // Import all of the members of this protocol.
+    ImportDeclContext(From, /*ForceImport=*/true);
+  }
   return false;
 }
 
@@ -3211,7 +3222,7 @@
 
 bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, 
                                        ObjCInterfaceDecl *To,
-                                       bool ForceImport) {
+                                       ImportDefinitionKind Kind) {
   if (To->getDefinition()) {
     // Check consistency of superclass.
     ObjCInterfaceDecl *FromSuper = From->getSuperClass();
@@ -3242,7 +3253,8 @@
                           diag::note_odr_objc_missing_superclass);        
     }
     
-    ImportDeclContext(From);
+    if (shouldForceImportDeclContext(Kind))
+      ImportDeclContext(From);
     return false;
   }
   
@@ -3298,9 +3310,10 @@
     To->setImplementation(Impl);
   }
 
-  // Import all of the members of this class.
-  ImportDeclContext(From);
-  
+  if (shouldForceImportDeclContext(Kind)) {
+    // Import all of the members of this class.
+    ImportDeclContext(From, /*ForceImport=*/true);
+  }
   return false;
 }
 
@@ -4190,15 +4203,51 @@
     return FromDC;
 
   DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
-  if (RecordDecl *ToRecord = dyn_cast_or_null<RecordDecl>(ToDC)) {
-    // When we're using a record declaration as a context, we need it to have
-    // a definition.
-    ASTNodeImporter Importer(*this);
-    
+  if (!ToDC)
+    return 0;
+  
+  // When we're using a record/enum/Objective-C class/protocol as a context, we 
+  // need it to have a definition.
+  if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
     RecordDecl *FromRecord = cast<RecordDecl>(FromDC);
-    if (FromRecord->isCompleteDefinition())
-      Importer.ImportDefinition(FromRecord, ToRecord,
-                                ASTNodeImporter::IDK_Basic);
+    if (ToRecord->isCompleteDefinition()) {
+      // Do nothing.
+    } else if (FromRecord->isCompleteDefinition()) {
+      ASTNodeImporter(*this).ImportDefinition(FromRecord, ToRecord,
+                                              ASTNodeImporter::IDK_Basic);
+    } else {
+      CompleteDecl(ToRecord);
+    }
+  } else if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
+    EnumDecl *FromEnum = cast<EnumDecl>(FromDC);
+    if (ToEnum->isCompleteDefinition()) {
+      // Do nothing.
+    } else if (FromEnum->isCompleteDefinition()) {
+      ASTNodeImporter(*this).ImportDefinition(FromEnum, ToEnum,
+                                              ASTNodeImporter::IDK_Basic);
+    } else {
+      CompleteDecl(ToEnum);
+    }    
+  } else if (ObjCInterfaceDecl *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) {
+    ObjCInterfaceDecl *FromClass = cast<ObjCInterfaceDecl>(FromDC);
+    if (ToClass->getDefinition()) {
+      // Do nothing.
+    } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) {
+      ASTNodeImporter(*this).ImportDefinition(FromDef, ToClass,
+                                              ASTNodeImporter::IDK_Basic);
+    } else {
+      CompleteDecl(ToClass);
+    }
+  } else if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) {
+    ObjCProtocolDecl *FromProto = cast<ObjCProtocolDecl>(FromDC);
+    if (ToProto->getDefinition()) {
+      // Do nothing.
+    } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) {
+      ASTNodeImporter(*this).ImportDefinition(FromDef, ToProto,
+                                              ASTNodeImporter::IDK_Basic);
+    } else {
+      CompleteDecl(ToProto);
+    }    
   }
   
   return ToDC;
@@ -4450,7 +4499,7 @@
     if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) {
       if (!ToEnum->getDefinition()) {
         Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum, 
-                                  /*ForceImport=*/true);
+                                  ASTNodeImporter::IDK_Everything);
         return;
       }      
     }
@@ -4458,7 +4507,7 @@
     if (ObjCInterfaceDecl *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
       if (!ToIFace->getDefinition()) {
         Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace,
-                                  /*ForceImport=*/true);
+                                  ASTNodeImporter::IDK_Everything);
         return;
       }
     }
@@ -4466,7 +4515,7 @@
     if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
       if (!ToProto->getDefinition()) {
         Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto,
-                                  /*ForceImport=*/true);
+                                  ASTNodeImporter::IDK_Everything);
         return;
       }
     }
@@ -4565,6 +4614,26 @@
   return FromContext.getDiagnostics().Report(Loc, DiagID);
 }
 
+void ASTImporter::CompleteDecl (Decl *D) {
+  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+    if (!ID->getDefinition())
+      ID->startDefinition();
+  }
+  else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+    if (!PD->getDefinition())
+      PD->startDefinition();
+  }
+  else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    if (!TD->getDefinition() && !TD->isBeingDefined()) {
+      TD->startDefinition();
+      TD->setCompleteDefinition(true);
+    }
+  }
+  else {
+    assert (0 && "CompleteDecl called on a Decl that can't be completed");
+  }
+}
+
 Decl *ASTImporter::Imported(Decl *From, Decl *To) {
   ImportedDecls[From] = To;
   return To;





More information about the cfe-commits mailing list