Implementation of AST for @protocol expression.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43075 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/Sema.cpp b/Sema/Sema.cpp
index dc68eb0..5bd5df5 100644
--- a/Sema/Sema.cpp
+++ b/Sema/Sema.cpp
@@ -63,6 +63,24 @@
   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/Sema/Sema.h b/Sema/Sema.h
index abe9250..596173d 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -280,6 +280,9 @@
   /// 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 @@
                                                  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/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index a6a47ad..6aebd16 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1929,6 +1929,20 @@
   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) {