From a12d294db5bd59cd8836b9bd0dafadaaa2e3dd8a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 16 Feb 2010 01:20:57 +0000 Subject: [PATCH] Skeleton for importing Objective-C classes git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96306 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 98 ++++++++++++++++++++++++++++++- test/ASTMerge/Inputs/interface1.m | 7 +++ test/ASTMerge/Inputs/interface2.m | 7 +++ test/ASTMerge/interface.m | 6 ++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 test/ASTMerge/Inputs/interface1.m create mode 100644 test/ASTMerge/Inputs/interface2.m create mode 100644 test/ASTMerge/interface.m diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 129d91be25..dee0d2b342 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -92,7 +92,8 @@ namespace { Decl *VisitFieldDecl(FieldDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitParmVarDecl(ParmVarDecl *D); - + Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); + // Importing statements Stmt *VisitStmt(Stmt *S); @@ -1963,6 +1964,101 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { return Importer.Imported(D, ToParm); } +Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + // Import the major distinguishing characteristics of an @interface. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + return 0; + + ObjCInterfaceDecl *MergeWithIface = 0; + for (DeclContext::lookup_result Lookup = DC->lookup(Name); + Lookup.first != Lookup.second; + ++Lookup.first) { + if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + continue; + + if ((MergeWithIface = dyn_cast(*Lookup.first))) + break; + } + + ObjCInterfaceDecl *ToIface = MergeWithIface; + if (!ToIface || ToIface->isForwardDecl()) { + if (!ToIface) { + ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), + DC, Loc, + Name.getAsIdentifierInfo(), + Importer.Import(D->getClassLoc()), + D->isForwardDecl(), + D->isImplicitInterfaceDecl()); + ToIface->setLexicalDeclContext(LexicalDC); + LexicalDC->addDecl(ToIface); + } + Importer.Imported(D, ToIface); + + // Import superclass + // FIXME: If we're merging, make sure that both decls have the same + // superclass. + if (D->getSuperClass()) { + ObjCInterfaceDecl *Super + = cast_or_null(Importer.Import(D->getSuperClass())); + if (!Super) + return 0; + + ToIface->setSuperClass(Super); + ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc())); + } + + // Import protocols + llvm::SmallVector Protocols; + llvm::SmallVector ProtocolLocs; + ObjCInterfaceDecl::protocol_loc_iterator + FromProtoLoc = D->protocol_loc_begin(); + for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(), + FromProtoEnd = D->protocol_end(); + FromProto != FromProtoEnd; + ++FromProto, ++FromProtoLoc) { + ObjCProtocolDecl *ToProto + = cast_or_null(Importer.Import(*FromProto)); + if (!ToProto) + return 0; + Protocols.push_back(ToProto); + ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + } + + // FIXME: If we're merging, make sure that the protocol list is the same. + ToIface->setProtocolList(Protocols.data(), Protocols.size(), + ProtocolLocs.data(), Importer.getToContext()); + + // FIXME: Import categories + + // Import @end range + ToIface->setAtEndRange(Importer.Import(D->getAtEndRange())); + } else { + Importer.Imported(D, ToIface); + } + + // Import all of the members of this class. + for (DeclContext::decl_iterator FromMem = D->decls_begin(), + FromMemEnd = D->decls_end(); + FromMem != FromMemEnd; + ++FromMem) + Importer.Import(*FromMem); + + // If we have an @implementation, import it as well. + if (D->getImplementation()) { + ObjCImplementationDecl *Impl + = cast(Importer.Import(D->getImplementation())); + if (!Impl) + return 0; + + ToIface->setImplementation(Impl); + } + + return 0; +} + //---------------------------------------------------------------------------- // Import Statements //---------------------------------------------------------------------------- diff --git a/test/ASTMerge/Inputs/interface1.m b/test/ASTMerge/Inputs/interface1.m new file mode 100644 index 0000000000..1aa1c3b894 --- /dev/null +++ b/test/ASTMerge/Inputs/interface1.m @@ -0,0 +1,7 @@ +// Matches +@interface I1 +@end + +// Matches +@interface I2 : I1 +@end diff --git a/test/ASTMerge/Inputs/interface2.m b/test/ASTMerge/Inputs/interface2.m new file mode 100644 index 0000000000..1aa1c3b894 --- /dev/null +++ b/test/ASTMerge/Inputs/interface2.m @@ -0,0 +1,7 @@ +// Matches +@interface I1 +@end + +// Matches +@interface I2 : I1 +@end diff --git a/test/ASTMerge/interface.m b/test/ASTMerge/interface.m new file mode 100644 index 0000000000..d6af2f4b16 --- /dev/null +++ b/test/ASTMerge/interface.m @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/interface1.m +// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/interface2.m +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 + +// FIXME: FileCheck! + -- 2.40.0