From ea7a98d8d65b469c6bcef302eb675b4fcdbff38c Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 5 Oct 2007 21:01:53 +0000 Subject: [PATCH] This is the first patch toward supporting protocol conforming objective-c types. It also removes use of Scope* parameter in getObjCProtocolDecl. llvm-svn: 42649 --- clang/Parse/ParseDecl.cpp | 4 +++ clang/Sema/Sema.h | 5 ++++ clang/Sema/SemaDecl.cpp | 28 +++++++++++++++++-- clang/clang.xcodeproj/project.pbxproj | 3 +- clang/include/clang/Basic/DiagnosticKinds.def | 2 ++ clang/include/clang/Parse/Action.h | 11 ++++++++ clang/test/Sema/undefined-protocol-type-1.m | 9 ++++++ 7 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/undefined-protocol-type-1.m diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp index db568df26e1a..8bdcd4e652ac 100644 --- a/clang/Parse/ParseDecl.cpp +++ b/clang/Parse/ParseDecl.cpp @@ -409,6 +409,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { if (Tok.getKind() == tok::less) { llvm::SmallVector ProtocolRefs; ParseObjCProtocolReferences(ProtocolRefs); + Actions.ActOnFindProtocolDeclaration(CurScope, + Loc, + &ProtocolRefs[0], + ProtocolRefs.size()); } continue; } diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 7a6d62fac252..6d38e629e383 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -429,6 +429,11 @@ public: SourceLocation AtProtocolLoc, IdentifierInfo **IdentList, unsigned NumElts); + + virtual DeclTy **ActOnFindProtocolDeclaration(Scope *S, + SourceLocation TypeLoc, + IdentifierInfo **ProtocolId, + unsigned NumProtocols); virtual void ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *ClassDecl, DeclTy **allMethods, unsigned allNum); diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index b827732b872c..8f743789e841 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -104,8 +104,14 @@ ObjcProtocolDecl *Sema::getObjCProtocolDecl(Scope *S, IdentifierInfo *Id, SourceLocation IdLoc) { // Note that Protocols have their own namespace. - ScopedDecl *PrDecl = LookupScopedDecl(Id, Decl::IDNS_Protocol, - IdLoc, S); + ScopedDecl *PrDecl = NULL; + for (ScopedDecl *D = Id->getFETokenInfo(); D; D = D->getNext()) { + if (D->getIdentifierNamespace() == Decl::IDNS_Protocol) { + PrDecl = D; + break; + } + } + if (PrDecl && !isa(PrDecl)) PrDecl = 0; return cast_or_null(static_cast(PrDecl)); @@ -1007,6 +1013,24 @@ Sema::DeclTy *Sema::ActOnStartProtocolInterface(Scope* S, return PDecl; } +/// ActOnFindProtocolDeclaration - This routine looks for a previously +/// declared protocol and returns it. If not found, issues diagnostic. +/// Will build a list of previously protocol declarations found in the list. +Action::DeclTy ** +Sema::ActOnFindProtocolDeclaration(Scope *S, + SourceLocation TypeLoc, + IdentifierInfo **ProtocolId, + unsigned NumProtocols) { + for (unsigned i = 0; i != NumProtocols; ++i) { + ObjcProtocolDecl *PDecl = getObjCProtocolDecl(S, ProtocolId[i], + TypeLoc); + if (!PDecl) + Diag(TypeLoc, diag::err_undeclared_protocol, + ProtocolId[i]->getName()); + } + return 0; +} + /// ActOnForwardProtocolDeclaration - /// Scope will always be top level file scope. Action::DeclTy * diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index e36c1442208f..09ddf1c7e7f5 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -242,7 +242,7 @@ DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = ""; }; DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = ""; }; DE06D42F0A8BB52D0050E87E /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = Parse/Parser.cpp; sourceTree = ""; }; - DE06E8130A8FF9330050E87E /* Action.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Parse/Action.h; sourceTree = ""; }; + DE06E8130A8FF9330050E87E /* Action.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Parse/Action.h; sourceTree = ""; tabWidth = 8; usesTabs = 0; }; DE0FCA620A95859D00248FD5 /* Expr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Expr.h; path = clang/AST/Expr.h; sourceTree = ""; }; DE0FCB330A9C21F100248FD5 /* Expr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Expr.cpp; path = AST/Expr.cpp; sourceTree = ""; }; DE1732FF0B068B700080B521 /* ASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTContext.cpp; path = AST/ASTContext.cpp; sourceTree = ""; }; @@ -737,6 +737,7 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */; + compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* clang */; projectDirPath = ""; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 389238bf0522..9238e23e6374 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -442,6 +442,8 @@ DIAG(error_duplicate_method_decl, ERROR, "duplicate declaration of method '%0'") DIAG(err_previous_declaration, ERROR, "previous declaration is here") +DIAG(err_undeclared_protocol, ERROR, + "cannot find protocol declaration for '%0'") //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 515935c4f090..204bd6cfb589 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -555,6 +555,17 @@ public: return 0; } + /// ActOnFindProtocolDeclaration - This routine looks for a previously + /// declared protocol and returns it. If not found, issues diagnostic. + /// Will build a list of previously protocol declarations found in the list. + virtual DeclTy **ActOnFindProtocolDeclaration(Scope *S, + SourceLocation TypeLoc, + IdentifierInfo **ProtocolId, + unsigned NumProtocols) { + return 0; + } + + //===----------------------- Obj-C Expressions --------------------------===// virtual ExprResult ParseObjCStringLiteral(ExprTy *string) { return 0; diff --git a/clang/test/Sema/undefined-protocol-type-1.m b/clang/test/Sema/undefined-protocol-type-1.m new file mode 100644 index 000000000000..117f418ab1c1 --- /dev/null +++ b/clang/test/Sema/undefined-protocol-type-1.m @@ -0,0 +1,9 @@ +// RUN: clang -fsyntax-only -verify %s + +@protocol p1, p4; +@protocol p2 @end + +@interface T +- (T*) meth; // expected-error {{cannot find protocol declaration for 'p3'}} +- (T*) meth; // expected-error {{cannot find protocol declaration for 'p3'}} +@end