[cfe-commits] r43915 - in /cfe/trunk: Parse/ParseObjc.cpp Parse/Parser.cpp Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaType.cpp include/clang/Parse/Action.h include/clang/Parse/Parser.h

Fariborz Jahanian fjahanian at apple.com
Thu Nov 8 15:49:50 PST 2007


Author: fjahanian
Date: Thu Nov  8 17:49:49 2007
New Revision: 43915

URL: http://llvm.org/viewvc/llvm-project?rev=43915&view=rev
Log:
First patch toward rewriting of method definitions. This is work in progress.

Modified:
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/Parse/Parser.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/Sema/SemaType.cpp
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h

Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Thu Nov  8 17:49:49 2007
@@ -1146,38 +1146,37 @@
 
 ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
 ///
-void Parser::ParseObjCInstanceMethodDefinition() {
+Parser::DeclTy *Parser::ParseObjCInstanceMethodDefinition() {
   assert(Tok.is(tok::minus) && "Method definitions should start with '-'");
-  
+  DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl);
   // FIXME: @optional/@protocol??
-  AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
+  AllImplMethods.push_back(MDecl);
   // parse optional ';'
   if (Tok.is(tok::semi))
     ConsumeToken();
 
   if (Tok.isNot(tok::l_brace)) {
     Diag (Tok, diag::err_expected_lbrace);
-    return;
+    return 0;
   }
-    
-  StmtResult FnBody = ParseCompoundStatementBody();
+  return ObjcParseFunctionDefinition(MDecl);
 }
 
 ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
 ///
-void Parser::ParseObjCClassMethodDefinition() {
+Parser::DeclTy *Parser::ParseObjCClassMethodDefinition() {
   assert(Tok.is(tok::plus) && "Class method definitions should start with '+'");
+  DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl);
   // FIXME: @optional/@protocol??
-  AllImplMethods.push_back(ParseObjCMethodPrototype(ObjcImpDecl));
+  AllImplMethods.push_back(MDecl);
   // parse optional ';'
   if (Tok.is(tok::semi))
     ConsumeToken();
   if (Tok.isNot(tok::l_brace)) {
     Diag (Tok, diag::err_expected_lbrace);
-    return;
+    return 0;
   }
-  
-  StmtResult FnBody = ParseCompoundStatementBody();
+  return ObjcParseFunctionDefinition(MDecl);
 }
 
 Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {

Modified: cfe/trunk/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/Parser.cpp?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/trunk/Parse/Parser.cpp Thu Nov  8 17:49:49 2007
@@ -331,7 +331,7 @@
     return ParseObjCAtDirectives();
   case tok::minus:
     if (getLang().ObjC1) {
-      ParseObjCInstanceMethodDefinition();
+      return ParseObjCInstanceMethodDefinition();
     } else {
       Diag(Tok, diag::err_expected_external_declaration);
       ConsumeToken();
@@ -339,7 +339,7 @@
     return 0;
   case tok::plus:
     if (getLang().ObjC1) {
-      ParseObjCClassMethodDefinition();
+      return ParseObjCClassMethodDefinition();
     } else {
       Diag(Tok, diag::err_expected_external_declaration);
       ConsumeToken();
@@ -465,6 +465,31 @@
   return ParseFunctionStatementBody(Res, BraceLoc, BraceLoc);  
 }
 
+Parser::DeclTy *Parser::ObjcParseFunctionDefinition(DeclTy *D) {
+  // We should have an opening brace now.
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_fn_body);
+    
+    // Skip over garbage, until we get to '{'.  Don't eat the '{'.
+    SkipUntil(tok::l_brace, true, true);
+    
+    // If we didn't find the '{', bail out.
+    if (Tok.isNot(tok::l_brace))
+      return 0;
+  }
+  
+  SourceLocation BraceLoc = Tok.getLocation();
+  
+  // Enter a scope for the function body.
+  EnterScope(Scope::FnScope|Scope::DeclScope);
+  
+  // Tell the actions module that we have entered a function definition with the
+  // specified Declarator for the function.
+  DeclTy *Res = Actions.ObjcActOnStartOfFunctionDef(CurScope, D);
+  
+  return ParseFunctionStatementBody(Res, BraceLoc, BraceLoc);  
+}
+
 /// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
 /// types for a function with a K&R-style identifier list for arguments.
 void Parser::ParseKNRParamDeclarations(Declarator &D) {

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Nov  8 17:49:49 2007
@@ -172,6 +172,9 @@
   //
   QualType GetTypeForDeclarator(Declarator &D, Scope *S);
   
+  QualType ObjcGetTypeForDeclarator(DeclTy *D, Scope *S);
+
+  
   virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
   
   virtual TypeResult ActOnParamDeclaratorType(Scope *S, Declarator &D);
@@ -181,10 +184,12 @@
   //
   virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
   virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup);
+  virtual DeclTy *ObjcActOnDeclarator(Scope *S, DeclTy *D, DeclTy *LastInGroup);
   void AddInitializerToDecl(DeclTy *dcl, ExprTy *init);
   virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
 
   virtual DeclTy *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
+  virtual DeclTy *ObjcActOnStartOfFunctionDef(Scope *S, DeclTy *D);
   virtual DeclTy *ActOnFunctionDefBody(DeclTy *Decl, StmtTy *Body);
   
   /// Scope actions.
@@ -226,6 +231,8 @@
   /// More parsing and symbol table subroutines...
   ParmVarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
                                     Scope *FnBodyScope);
+  ParmVarDecl *ObjcParseParamDeclarator(ParmVarDecl *param, Scope *FnBodyScope);
+  
   ScopedDecl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, 
                                SourceLocation IdLoc, Scope *S);
   ScopedDecl *LookupInterfaceDecl(IdentifierInfo *II);

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Thu Nov  8 17:49:49 2007
@@ -545,6 +545,42 @@
 }
 
 Sema::DeclTy *
+Sema::ObjcActOnDeclarator(Scope *S, DeclTy *D, DeclTy *lastDecl) {
+  ObjcMethodDecl *MDecl = dyn_cast<ObjcMethodDecl>(static_cast<Decl *>(D));
+  
+  ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
+  const char *name = MDecl->getSelector().getName().c_str();
+  IdentifierInfo *II = &Context.Idents.get(name);
+  assert (II && "ObjcActOnDeclarator - selector name is missing");
+  
+  // The scope passed in may not be a decl scope.  Zip up the scope tree until
+  // we find one that is.
+  while ((S->getFlags() & Scope::DeclScope) == 0)
+    S = S->getParent();
+  
+  ScopedDecl *New;
+  QualType R = ObjcGetTypeForDeclarator(MDecl, S);
+  assert(!R.isNull() && "ObjcGetTypeForDeclarator() returned null type");
+    
+  FunctionDecl *NewFD = new FunctionDecl(MDecl->getLocation(), II, R, 
+                                         FunctionDecl::Static,
+                                         false, LastDeclarator);
+  New = NewFD;
+  
+  // If this has an identifier, add it to the scope stack.
+  if (II) {
+    New->setNext(II->getFETokenInfo<ScopedDecl>());
+    II->setFETokenInfo(New);
+    S->AddDecl(New);
+  }
+  
+  if (S->getParent() == 0)
+    AddTopLevelDecl(New, LastDeclarator);
+  
+  return New;
+}
+
+Sema::DeclTy *
 Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
   ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
   IdentifierInfo *II = D.getIdentifier();
@@ -853,7 +889,64 @@
 
   return New;
 }
+
+// Called from Sema::ObjcParseStartOfFunctionDef().
+ParmVarDecl *
+Sema::ObjcParseParamDeclarator(ParmVarDecl *PI, Scope *FnScope) {
+  
+  IdentifierInfo *II = PI->getIdentifier();
+  // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
+  // Can this happen for params?  We already checked that they don't conflict
+  // among each other.  Here they can only shadow globals, which is ok.
+  if (/*Decl *PrevDecl = */LookupScopedDecl(II, Decl::IDNS_Ordinary,
+                                            PI->getLocation(), FnScope)) {
+    
+  }
+  
+  // FIXME: Handle storage class (auto, register). No declarator?
+  // TODO: Chain to previous parameter with the prevdeclarator chain?
+  
+  // Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
+  // Doing the promotion here has a win and a loss. The win is the type for
+  // both Decl's and DeclRefExpr's will match (a convenient invariant for the
+  // code generator). The loss is the orginal type isn't preserved. For example:
+  //
+  // void func(int parmvardecl[5]) { // convert "int [5]" to "int *"
+  //    int blockvardecl[5];
+  //    sizeof(parmvardecl);  // size == 4
+  //    sizeof(blockvardecl); // size == 20
+  // }
+  //
+  // For expressions, all implicit conversions are captured using the
+  // ImplicitCastExpr AST node (we have no such mechanism for Decl's).
+  //
+  // FIXME: If a source translation tool needs to see the original type, then
+  // we need to consider storing both types (in ParmVarDecl)...
+  // 
+  QualType parmDeclType = PI->getType();
+  if (const ArrayType *AT = parmDeclType->getAsArrayType())
+    parmDeclType = Context.getPointerType(AT->getElementType());
+  else if (parmDeclType->isFunctionType())
+    parmDeclType = Context.getPointerType(parmDeclType);
+  
+  ParmVarDecl *New = new ParmVarDecl(PI->getLocation(), II, parmDeclType, 
+                                     VarDecl::None, 0);
+  // FIXME: need to check for invalid type.
+  /**
+  if (PI.InvalidType)
+    New->setInvalidDecl();
+   */
   
+  // If this has an identifier, add it to the scope stack.
+  if (II) {
+    New->setNext(II->getFETokenInfo<ScopedDecl>());
+    II->setFETokenInfo(New);
+    FnScope->AddDecl(New);
+  }
+  
+  return New;
+}
+
 
 Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
   assert(CurFunctionDecl == 0 && "Function parsing confused");
@@ -938,6 +1031,30 @@
   return FD;
 }
 
+Sema::DeclTy *Sema::ObjcActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
+  assert(CurFunctionDecl == 0 && "Function parsing confused");
+  ObjcMethodDecl *MDecl = dyn_cast<ObjcMethodDecl>(static_cast<Decl *>(D));
+  
+  assert(MDecl != 0 && "Not a method declarator!");
+  
+  Scope *GlobalScope = FnBodyScope->getParent();
+  
+  FunctionDecl *FD =
+  static_cast<FunctionDecl*>(ObjcActOnDeclarator(GlobalScope, D, 0));
+  CurFunctionDecl = FD;
+  
+  // Create Decl objects for each parameter, adding them to the FunctionDecl.
+  llvm::SmallVector<ParmVarDecl*, 16> Params;
+  
+  for (int i = 0; i <  MDecl->getNumParams(); i++) {
+    ParmVarDecl *PDecl = MDecl->getParamDecl(i);
+    Params.push_back(ObjcParseParamDeclarator(PDecl, FnBodyScope));
+  }
+
+  FD->setParams(&Params[0], Params.size());
+  
+  return FD;
+}
 
 /// ImplicitlyDefineFunction - An undeclared identifier was used in a function
 /// call, forming a call to an implicitly defined function (per C99 6.5.1p2).

Modified: cfe/trunk/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaType.cpp?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaType.cpp (original)
+++ cfe/trunk/Sema/SemaType.cpp Thu Nov  8 17:49:49 2007
@@ -325,6 +325,42 @@
   return T;
 }
 
+/// GetTypeForDeclarator - Convert the type for the specified declarator to Type
+/// instances.
+QualType Sema::ObjcGetTypeForDeclarator(DeclTy *D, Scope *S) {
+  ObjcMethodDecl *MDecl = dyn_cast<ObjcMethodDecl>(static_cast<Decl *>(D));
+  QualType T = MDecl->getResultType();
+  llvm::SmallVector<QualType, 16> ArgTys;
+  
+  for (int i = 0; i <  MDecl->getNumParams(); i++) {
+    ParmVarDecl *PDecl = MDecl->getParamDecl(i);
+    QualType ArgTy = PDecl->getType();
+    assert(!ArgTy.isNull() && "Couldn't parse type?");
+    //
+    // Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
+    // This matches the conversion that is done in 
+    // Sema::ParseParamDeclarator(). Without this conversion, the
+    // argument type in the function prototype *will not* match the
+    // type in ParmVarDecl (which makes the code generator unhappy).
+    //
+    // FIXME: We still apparently need the conversion in 
+    // Sema::ParseParamDeclarator(). This doesn't make any sense, since
+    // it should be driving off the type being created here.
+    // 
+    // FIXME: If a source translation tool needs to see the original type,
+    // then we need to consider storing both types somewhere...
+    // 
+    if (const ArrayType *AT = ArgTy->getAsArrayType())
+      ArgTy = Context.getPointerType(AT->getElementType());
+    else if (ArgTy->isFunctionType())
+      ArgTy = Context.getPointerType(ArgTy);
+    ArgTys.push_back(ArgTy);
+  }
+  T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
+                              false);
+  return T;
+}
+
 Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
   // C99 6.7.6: Type names have no identifier.  This is already validated by
   // the parser.

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Nov  8 17:49:49 2007
@@ -107,6 +107,9 @@
     return 0;
   }
 
+  virtual DeclTy *ObjcActOnDeclarator(Scope *S, DeclTy *D,DeclTy *LastInGroup) {
+    return 0;
+  }
   /// AddInitializerToDecl - This action is called immediately after 
   /// ParseDeclarator (when an initializer is present). The code is factored 
   /// this way to make sure we are able to handle the following:
@@ -131,6 +134,11 @@
     return ActOnDeclarator(FnBodyScope, D, 0);
   }
 
+  virtual DeclTy *ObjcActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
+    // Default to ActOnDeclarator.
+    return ObjcActOnDeclarator(FnBodyScope, D, 0);
+  }
+  
   /// ActOnFunctionDefBody - This is called when a function body has completed
   /// parsing.  Decl is the DeclTy returned by ParseStartOfFunctionDef.
   virtual DeclTy *ActOnFunctionDefBody(DeclTy *Decl, StmtTy *Body) {

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=43915&r1=43914&r2=43915&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Nov  8 17:49:49 2007
@@ -250,6 +250,7 @@
   DeclTy *ParseExternalDeclaration();
   DeclTy *ParseDeclarationOrFunctionDefinition();
   DeclTy *ParseFunctionDefinition(Declarator &D);
+  DeclTy *ObjcParseFunctionDefinition(DeclTy *D);
   void ParseKNRParamDeclarations(Declarator &D);
   void ParseSimpleAsm();
   void ParseAsmStringLiteral();
@@ -300,8 +301,8 @@
   void ParseObjCPropertyAttribute(ObjcDeclSpec &DS);
   DeclTy *ParseObjCPropertyDecl(DeclTy *interfaceDecl, SourceLocation AtLoc);
   
-  void ParseObjCInstanceMethodDefinition();
-  void ParseObjCClassMethodDefinition();
+  DeclTy *ParseObjCInstanceMethodDefinition();
+  DeclTy *ParseObjCClassMethodDefinition();
   
   //===--------------------------------------------------------------------===//
   // C99 6.5: Expressions.





More information about the cfe-commits mailing list