diff options
-rw-r--r-- | clang/AST/ASTContext.cpp | 11 | ||||
-rw-r--r-- | clang/AST/Expr.cpp | 4 | ||||
-rw-r--r-- | clang/AST/StmtDumper.cpp | 8 | ||||
-rw-r--r-- | clang/AST/StmtPrinter.cpp | 7 | ||||
-rw-r--r-- | clang/Parse/ParseObjc.cpp | 7 | ||||
-rw-r--r-- | clang/Sema/Sema.cpp | 18 | ||||
-rw-r--r-- | clang/Sema/Sema.h | 10 | ||||
-rw-r--r-- | clang/Sema/SemaExpr.cpp | 14 | ||||
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 7 | ||||
-rw-r--r-- | clang/include/clang/AST/Expr.h | 31 | ||||
-rw-r--r-- | clang/include/clang/AST/StmtNodes.def | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticKinds.def | 2 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 7 | ||||
-rw-r--r-- | clang/test/Sema/protocol-expr-1.m | 17 | ||||
-rw-r--r-- | clang/test/Sema/protocol-expr-neg-1.m | 19 |
15 files changed, 159 insertions, 6 deletions
diff --git a/clang/AST/ASTContext.cpp b/clang/AST/ASTContext.cpp index 4c06e7c88cb..cf617d190ee 100644 --- a/clang/AST/ASTContext.cpp +++ b/clang/AST/ASTContext.cpp @@ -870,6 +870,17 @@ void ASTContext::setObjcSelType(TypedefDecl *TD) SelStructType = rec; } +void ASTContext::setObjcProtoType(TypedefDecl *TD) +{ + assert(ObjcProtoType.isNull() && "'Protocol' type already set!"); + + // typedef struct Protocol Protocol; + ObjcProtoType = TD->getUnderlyingType(); + // Protocol * type + ObjcProtoType = getPointerType(ObjcProtoType); + ProtoStructType = TD->getUnderlyingType()->getAsStructureType(); +} + void ASTContext::setObjcConstantStringInterface(ObjcInterfaceDecl *Decl) { assert(ObjcConstantStringType.isNull() && "'NSConstantString' type already set!"); diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 1b989a4a61c..d69133258a1 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -1084,6 +1084,10 @@ Stmt::child_iterator ObjCEncodeExpr::child_end() { return NULL; } Stmt::child_iterator ObjCSelectorExpr::child_begin() { return NULL; } Stmt::child_iterator ObjCSelectorExpr::child_end() { return NULL; } +// ObjCProtocolExpr +Stmt::child_iterator ObjCProtocolExpr::child_begin() { return NULL; } +Stmt::child_iterator ObjCProtocolExpr::child_end() { return NULL; } + // ObjCMessageExpr Stmt::child_iterator ObjCMessageExpr::child_begin() { return reinterpret_cast<Stmt**>(&SubExprs[0]); diff --git a/clang/AST/StmtDumper.cpp b/clang/AST/StmtDumper.cpp index 39d2effd5a3..62886981b23 100644 --- a/clang/AST/StmtDumper.cpp +++ b/clang/AST/StmtDumper.cpp @@ -14,6 +14,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjc.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" @@ -129,6 +130,7 @@ namespace { // ObjC void VisitObjCEncodeExpr(ObjCEncodeExpr *Node); void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); + void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); }; } @@ -415,6 +417,12 @@ void StmtDumper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { fprintf(F, "%s", selector.getName().c_str()); } +void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { + DumpExpr(Node); + + fprintf(F, " "); + fprintf(F, "%s", Node->getProtocol()->getName()); +} //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/clang/AST/StmtPrinter.cpp b/clang/AST/StmtPrinter.cpp index a19ad37a0c3..90c5ef21598 100644 --- a/clang/AST/StmtPrinter.cpp +++ b/clang/AST/StmtPrinter.cpp @@ -14,6 +14,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjc.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/IdentifierTable.h" @@ -627,6 +628,12 @@ void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { OS << ")"; } +void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { + OS << "@protocol("; + OS << Node->getProtocol()->getName(); + OS << ")"; +} + void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { OS << "["; Expr *receiver = Mess->getReceiver(); diff --git a/clang/Parse/ParseObjc.cpp b/clang/Parse/ParseObjc.cpp index 0b6f303a489..f7ab990d29e 100644 --- a/clang/Parse/ParseObjc.cpp +++ b/clang/Parse/ParseObjc.cpp @@ -1297,14 +1297,13 @@ Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) Diag(Tok, diag::err_expected_ident); return true; } - - // FIXME: Do something with the protocol name + IdentifierInfo *protocolId = Tok.getIdentifierInfo(); ConsumeToken(); SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - // FIXME - return 0; + return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, + LParenLoc, RParenLoc); } /// objc-selector-expression diff --git a/clang/Sema/Sema.cpp b/clang/Sema/Sema.cpp index dc68eb03d85..5bd5df5539e 100644 --- a/clang/Sema/Sema.cpp +++ b/clang/Sema/Sema.cpp @@ -63,6 +63,24 @@ QualType Sema::GetObjcSelType(SourceLocation Loc) { return Context.getObjcSelType(); } +/// GetObjcProtoType - See comments for Sema::GetObjcIdType above; replace "id" +/// with "Protocol". +QualType Sema::GetObjcProtoType(SourceLocation Loc) { + assert(TUScope && "GetObjcProtoType(): Top-level scope is null"); + if (Context.getObjcProtoType().isNull()) { + IdentifierInfo *ProtoIdent = &Context.Idents.get("Protocol"); + ScopedDecl *ProtoDecl = LookupScopedDecl(ProtoIdent, Decl::IDNS_Ordinary, + SourceLocation(), TUScope); + TypedefDecl *ObjcProtoTypedef = dyn_cast_or_null<TypedefDecl>(ProtoDecl); + if (!ObjcProtoTypedef) { + Diag(Loc, diag::err_missing_proto_definition); + return QualType(); + } + Context.setObjcProtoType(ObjcProtoTypedef); + } + return Context.getObjcProtoType(); +} + Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup) : PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) { diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index abe9250f040..596173dda2d 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -280,6 +280,9 @@ private: /// GetObjcSelType - Getter for the build-in "SEL" type. QualType GetObjcSelType(SourceLocation Loc = SourceLocation()); + /// GetObjcSelType - Getter for the build-in "Protocol *" type. + QualType GetObjcProtoType(SourceLocation Loc = SourceLocation()); + /// AddInstanceMethodToGlobalPool - All instance methods in a translation /// unit are added to a global pool. This allows us to efficiently associate /// a selector with a method declaraation for purposes of typechecking @@ -452,6 +455,13 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc); + // ParseObjCProtocolExpression - Build protocol expression for @protocol + virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + // Objective-C declarations. virtual DeclTy *ActOnStartClassInterface( SourceLocation AtInterafceLoc, diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index a6a47adddbc..6aebd1626ac 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -1929,6 +1929,20 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc); } +Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + ObjcProtocolDecl* PDecl = ObjcProtocols[ProtocolId]; + if (!PDecl) { + Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName()); + return true; + } + + QualType t = GetObjcProtoType(AtLoc); + return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); +} bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, ObjcMethodDecl *Method) { diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ec9b91b3aed..3881b6316b4 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -54,6 +54,10 @@ class ASTContext { QualType ObjcSelType; const RecordType *SelStructType; + /// ObjcProtoType - another psuedo built-in typedef type (set by Sema). + QualType ObjcProtoType; + const RecordType *ProtoStructType; + QualType ObjcConstantStringType; RecordDecl *CFConstantStringTypeDecl; public: @@ -175,6 +179,9 @@ public: void setObjcSelType(TypedefDecl *Decl); QualType getObjcSelType() const { return ObjcSelType; } + void setObjcProtoType(TypedefDecl *Decl); + QualType getObjcProtoType() const { return ObjcProtoType; } + void setBuiltinVaListType(QualType T); QualType getBuiltinVaListType() const { return BuiltinVaListType; } diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 64e47b4fe07..99f17751950 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1119,7 +1119,7 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSelectorExprClass; } - static bool classof(const ObjCEncodeExpr *) { return true; } + static bool classof(const ObjCSelectorExpr *) { return true; } // Iterators virtual child_iterator child_begin(); @@ -1127,6 +1127,35 @@ public: }; +/// ObjCProtocolExpr used for protocol in Objective-C. +class ObjCProtocolExpr : public Expr { + + ObjcProtocolDecl *Protocol; + + SourceLocation AtLoc, RParenLoc; + public: + ObjCProtocolExpr(QualType T, ObjcProtocolDecl *protocol, + SourceLocation at, SourceLocation rp) + : Expr(ObjCProtocolExprClass, T), Protocol(protocol), + AtLoc(at), RParenLoc(rp) {} + + ObjcProtocolDecl *getProtocol() const { return Protocol; } + + SourceLocation getAtLoc() const { return AtLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCProtocolExprClass; + } + static bool classof(const ObjCProtocolExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + +}; + class ObjCMessageExpr : public Expr { enum { RECEIVER=0, ARGS_START=1 }; diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index 76eb8491394..c8b822139c2 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/include/clang/AST/StmtNodes.def @@ -83,8 +83,9 @@ STMT(70, ObjCStringLiteral , Expr) STMT(71, ObjCEncodeExpr , Expr) STMT(72, ObjCMessageExpr , Expr) STMT(73, ObjCSelectorExpr , Expr) +STMT(74, ObjCProtocolExpr , Expr) -LAST_EXPR(73) +LAST_EXPR(74) #undef STMT #undef FIRST_STMT diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index eae6c22b88e..6581e5d7ed4 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -448,6 +448,8 @@ DIAG(err_missing_sel_definition, ERROR, "cannot find definition of 'SEL'") DIAG(err_missing_id_definition, ERROR, "cannot find definition of 'id'") +DIAG(err_missing_proto_definition, ERROR, + "cannot find definition of 'Protocol'") DIAG(warn_previous_alias_decl, WARNING, "previously declared alias is ignored") DIAG(warn_previous_declaration, WARNING, diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index d68850582fd..e8c943d6246 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -603,6 +603,13 @@ public: return 0; } + virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return 0; + } }; /// MinimalAction - Minimal actions are used by light-weight clients of the diff --git a/clang/test/Sema/protocol-expr-1.m b/clang/test/Sema/protocol-expr-1.m new file mode 100644 index 00000000000..23cb5dd903d --- /dev/null +++ b/clang/test/Sema/protocol-expr-1.m @@ -0,0 +1,17 @@ +// RUN: clang -fsyntax-only -verify %s + +typedef struct Protocol Protocol; + +@protocol fproto; + +@protocol p1 +@end + +@class cl; + +int main() +{ + Protocol *proto = @protocol(p1); + Protocol *fproto = @protocol(fproto); +} + diff --git a/clang/test/Sema/protocol-expr-neg-1.m b/clang/test/Sema/protocol-expr-neg-1.m new file mode 100644 index 00000000000..d59d83fd78c --- /dev/null +++ b/clang/test/Sema/protocol-expr-neg-1.m @@ -0,0 +1,19 @@ +// RUN: clang -fsyntax-only -verify %s + +typedef struct Protocol Protocol; + +@protocol fproto; + +@protocol p1 +@end + +@class cl; + +int main() +{ + Protocol *proto = @protocol(p1); + Protocol *fproto = @protocol(fproto); + Protocol *pp = @protocol(i); // expected-error {{cannot find protocol declaration for 'i'}} + Protocol *p1p = @protocol(cl); // expected-error {{cannot find protocol declaration for 'cl'}} +} + |