]> granicus.if.org Git - clang/commitdiff
Implementation of AST for @protocol expression.
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 17 Oct 2007 16:58:11 +0000 (16:58 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 17 Oct 2007 16:58:11 +0000 (16:58 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43075 91177308-0d34-0410-b5e6-96231b3b80d8

15 files changed:
AST/ASTContext.cpp
AST/Expr.cpp
AST/StmtDumper.cpp
AST/StmtPrinter.cpp
Parse/ParseObjc.cpp
Sema/Sema.cpp
Sema/Sema.h
Sema/SemaExpr.cpp
include/clang/AST/ASTContext.h
include/clang/AST/Expr.h
include/clang/AST/StmtNodes.def
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Action.h
test/Sema/protocol-expr-1.m [new file with mode: 0644]
test/Sema/protocol-expr-neg-1.m [new file with mode: 0644]

index 4c06e7c88cb4fca586e963a6e3ce4341894497fb..cf617d190eebd873c47843f5ee4866a452d77b0e 100644 (file)
@@ -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!");
index 1b989a4a61c352fb7e25479bc39499a335733827..d69133258a1f329860b5d1bd3d9d3c065869fd19 100644 (file)
@@ -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]);
index 39d2effd5a39a05ae67dd5671c6f423966be7a89..62886981b234e01a6e345db13ab1cb651a5d85dc 100644 (file)
@@ -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
 //===----------------------------------------------------------------------===//
index a19ad37a0c3101cfbb059f090334e1f8eeb8d662..90c5ef2159809290973d6a82b0ca44fac36a9a21 100644 (file)
@@ -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();
index 0b6f303a4890d07d529204a6d3f4a77fda848fb2..f7ab990d29e9a8e8888674714da0e2709e9c70e1 100644 (file)
@@ -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
index dc68eb03d85586b5ee98ce09200e5f5f0f60c35b..5bd5df5539e9628516e74ad4fbc4b180f6b2c801 100644 (file)
@@ -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) {
   
index abe9250f040b7bc22fea46fb252e5011041b0fc8..596173dda2d41c78ebccaef9d1020e91009aee8f 100644 (file)
@@ -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,
index a6a47adddbcccaa127715f7e1cac638d9d42815e..6aebd1626ac7a6780278b1ae0a20422e858a2d58 100644 (file)
@@ -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) {
index ec9b91b3aed52e0405517629eea3b8cb4e549880..3881b6316b475c5670fd3c244bee6f6878d4aff0 100644 (file)
@@ -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; }
     
index 64e47b4fe07532ace206b3f25d4141b449a3c299..99f177519506f48ca3179ae950a0a539596c8de9 100644 (file)
@@ -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 };
 
index 76eb84913942bb0c047cf5b080169506d074a8d3..c8b822139c25c01cec388c907938a4e7cc7b0dd5 100644 (file)
@@ -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
index eae6c22b88ea23e857fab0dde52560f71b3b587a..6581e5d7ed4bac3d2d8f8c13db65afda4ff210e3 100644 (file)
@@ -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,
index d68850582fd8ed6ec1a3905c5ceb2f9609e7a51e..e8c943d62468bb8372bff5db3e3ea71fd52ccd7f 100644 (file)
@@ -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/test/Sema/protocol-expr-1.m b/test/Sema/protocol-expr-1.m
new file mode 100644 (file)
index 0000000..23cb5dd
--- /dev/null
@@ -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/test/Sema/protocol-expr-neg-1.m b/test/Sema/protocol-expr-neg-1.m
new file mode 100644 (file)
index 0000000..d59d83f
--- /dev/null
@@ -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'}}
+}
+