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!");
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]);
#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"
// ObjC
void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
+ void VisitObjCProtocolExpr(ObjCProtocolExpr *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
//===----------------------------------------------------------------------===//
#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"
OS << ")";
}
+void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
+ OS << "@protocol(";
+ OS << Node->getProtocol()->getName();
+ OS << ")";
+}
+
void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
OS << "[";
Expr *receiver = Mess->getReceiver();
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
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) {
/// 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
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,
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) {
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:
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; }
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();
};
+/// 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 };
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
"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,
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
--- /dev/null
+// 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);
+}
+
--- /dev/null
+// 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'}}
+}
+