From: Douglas Gregor Date: Wed, 17 Feb 2010 16:12:00 +0000 (+0000) Subject: AST import for Objective-C protocols X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2e2a400383c7a64a927f61eeed596b08928e1d4b;p=clang AST import for Objective-C protocols git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96478 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index a6e565d507..7b3fb00543 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -94,6 +94,7 @@ namespace { Decl *VisitVarDecl(VarDecl *D); Decl *VisitParmVarDecl(ParmVarDecl *D); Decl *VisitObjCMethodDecl(ObjCMethodDecl *D); + Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); // Importing statements @@ -2130,6 +2131,70 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { return ToMethod; } +Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + // Import the major distinguishing characteristics of an @protocol. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + return 0; + + ObjCProtocolDecl *MergeWithProtocol = 0; + for (DeclContext::lookup_result Lookup = DC->lookup(Name); + Lookup.first != Lookup.second; + ++Lookup.first) { + if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) + continue; + + if ((MergeWithProtocol = dyn_cast(*Lookup.first))) + break; + } + + ObjCProtocolDecl *ToProto = MergeWithProtocol; + if (!ToProto || ToProto->isForwardDecl()) { + if (!ToProto) { + ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo()); + ToProto->setForwardDecl(D->isForwardDecl()); + ToProto->setLexicalDeclContext(LexicalDC); + LexicalDC->addDecl(ToProto); + } + Importer.Imported(D, ToProto); + + // Import protocols + llvm::SmallVector Protocols; + llvm::SmallVector ProtocolLocs; + ObjCProtocolDecl::protocol_loc_iterator + FromProtoLoc = D->protocol_loc_begin(); + for (ObjCProtocolDecl::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. + ToProto->setProtocolList(Protocols.data(), Protocols.size(), + ProtocolLocs.data(), Importer.getToContext()); + } else { + Importer.Imported(D, ToProto); + } + + // 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); + + return ToProto; +} + Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Import the major distinguishing characteristics of an @interface. DeclContext *DC, *LexicalDC; @@ -2158,6 +2223,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Importer.Import(D->getClassLoc()), D->isForwardDecl(), D->isImplicitInterfaceDecl()); + ToIface->setForwardDecl(D->isForwardDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(ToIface); } @@ -2246,7 +2312,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ToIface->setImplementation(Impl); } - return 0; + return ToIface; } //---------------------------------------------------------------------------- diff --git a/test/ASTMerge/Inputs/interface1.m b/test/ASTMerge/Inputs/interface1.m index bde667475d..a508bc159b 100644 --- a/test/ASTMerge/Inputs/interface1.m +++ b/test/ASTMerge/Inputs/interface1.m @@ -45,3 +45,26 @@ - (int)foo; + (int)bar:(float)x; @end + +// Matching protocol +@protocol P0 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with mismatching method +@protocol P1 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Interface with protocol +@interface I9 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with protocol +@protocol P2 +- (float)wibble:(int)a1 second:(int)a2; +@end diff --git a/test/ASTMerge/Inputs/interface2.m b/test/ASTMerge/Inputs/interface2.m index 1d5bebd996..d79f77d92a 100644 --- a/test/ASTMerge/Inputs/interface2.m +++ b/test/ASTMerge/Inputs/interface2.m @@ -44,3 +44,26 @@ - (int)foo; + (int)bar:(float)x, ...; @end + +// Matching protocol +@protocol P0 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with mismatching method +@protocol P1 ++ (int)foo; +- (int)bar:(double)x; +@end + +// Interface with protocol +@interface I9 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with protocol +@protocol P2 +- (float)wibble:(int)a1 second:(int)a2; +@end diff --git a/test/ASTMerge/interface.m b/test/ASTMerge/interface.m index 465077b420..47e4e05269 100644 --- a/test/ASTMerge/interface.m +++ b/test/ASTMerge/interface.m @@ -13,5 +13,7 @@ // CHECK: interface1.m:40:17: note: declared here with type 'int' // CHECK: interface2.m:45:1: error: class method 'bar:' is variadic in one translation unit and not variadic in another // CHECK: interface1.m:46:1: note: class method 'bar:' also declared here -// CHECK: 11 diagnostics generated +// CHECK: interface2.m:57:20: error: instance method 'bar:' has a parameter with a different types in different translation units ('double' vs. 'float') +// CHECK: interface1.m:58:19: note: declared here with type 'float' +// CHECK: 13 diagnostics generated