[cfe-commits] r159626 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseObjc.cpp lib/Parse/Parser.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/delay-parsing-cfunctions.m

Fariborz Jahanian fjahanian at apple.com
Mon Jul 2 16:37:09 PDT 2012


Author: fjahanian
Date: Mon Jul  2 18:37:09 2012
New Revision: 159626

URL: http://llvm.org/viewvc/llvm-project?rev=159626&view=rev
Log:
objective-c: just as we have done for method definitions,
c-functions declared in implementation should have their 
parsing delayed until the end so, they can access forward
declared private methods. // rdar://10387088

Added:
    cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m
Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=159626&r1=159625&r2=159626&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Jul  2 18:37:09 2012
@@ -1019,7 +1019,7 @@
   void ParseLexedMethodDef(LexedMethod &LM);
   void ParseLexedMemberInitializers(ParsingClass &Class);
   void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
-  Decl *ParseLexedObjCMethodDefs(LexedMethod &LM);
+  void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod);
   bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
   bool ConsumeAndStoreUntil(tok::TokenKind T1,
                             CachedTokens &Toks,
@@ -1084,11 +1084,12 @@
   struct ObjCImplParsingDataRAII {
     Parser &P;
     Decl *Dcl;
+    bool HasCFunction;
     typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer;
     LateParsedObjCMethodContainer LateParsedObjCMethods;
 
     ObjCImplParsingDataRAII(Parser &parser, Decl *D)
-      : P(parser), Dcl(D) {
+      : P(parser), Dcl(D), HasCFunction(false) {
       P.CurParsedObjCImpl = this;
       Finished = false;
     }
@@ -1101,6 +1102,7 @@
     bool Finished;
   };
   ObjCImplParsingDataRAII *CurParsedObjCImpl;
+  void StashAwayMethodOrFunctionBodyTokens(Decl *MDecl);
 
   DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc);
   DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=159626&r1=159625&r2=159626&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jul  2 18:37:09 2012
@@ -1317,7 +1317,11 @@
   void CheckForFunctionRedefinition(FunctionDecl *FD);
   Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
   Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
-  void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+  void ActOnStartOfObjCMethodOrCFunctionDef(Scope *S, Decl *D, 
+                                            bool parseMethod);
+  bool isObjCMethodDecl(Decl *D) {
+    return D && isa<ObjCMethodDecl>(D);
+  }
 
   void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope);
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=159626&r1=159625&r2=159626&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jul  2 18:37:09 2012
@@ -1379,6 +1379,14 @@
 
   bool ExpectSemi = Context != Declarator::ForContext;
 
+  if (CurParsedObjCImpl && D.isFunctionDeclarator() &&
+      Tok.is(tok::l_brace)) {
+    // Consume the tokens and store them for later parsing.
+    StashAwayMethodOrFunctionBodyTokens(FirstDecl);
+    CurParsedObjCImpl->HasCFunction = true;
+    ExpectSemi = false;
+  }
+  
   // If we don't have a comma, it is either the end of the list (a ';') or an
   // error, bail out.
   while (Tok.is(tok::comma)) {

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=159626&r1=159625&r2=159626&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Jul  2 18:37:09 2012
@@ -1575,10 +1575,16 @@
   assert(!Finished);
   P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl);
   for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
-    P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i]);
+    P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], 
+                               true/*Methods*/);
 
   P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd);
 
+  if (HasCFunction)
+    for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
+      P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], 
+                                 false/*c-functions*/);
+  
   /// \brief Clear and free the cached objc methods.
   for (LateParsedObjCMethodContainer::iterator
          I = LateParsedObjCMethods.begin(),
@@ -1915,6 +1921,19 @@
                                                 AutoreleasePoolBody.take());
 }
 
+/// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them 
+/// for later parsing.
+void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
+  LexedMethod* LM = new LexedMethod(this, MDecl);
+  CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
+  CachedTokens &Toks = LM->Toks;
+  // Begin by storing the '{' token.
+  Toks.push_back(Tok);
+  ConsumeBrace();
+  // Consume everything up to (and including) the matching right brace.
+  ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
+}
+
 ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
 ///
 Decl *Parser::ParseObjCMethodDefinition() {
@@ -1955,15 +1974,7 @@
 
   if (CurParsedObjCImpl) {
     // Consume the tokens and store them for later parsing.
-    LexedMethod* LM = new LexedMethod(this, MDecl);
-    CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
-    CachedTokens &Toks = LM->Toks;
-    // Begin by storing the '{' token.
-    Toks.push_back(Tok);
-    ConsumeBrace();
-    // Consume everything up to (and including) the matching right brace.
-    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
-
+    StashAwayMethodOrFunctionBodyTokens(MDecl);
   } else {
     ConsumeBrace();
     SkipUntil(tok::r_brace, /*StopAtSemi=*/false);
@@ -2821,8 +2832,15 @@
                                                    T.getCloseLocation()));
  }
 
-Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) {
-
+void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
+  // MCDecl might be null due to error in method or c-function  prototype, etc.
+  Decl *MCDecl = LM.D;
+  bool skip = MCDecl && 
+              ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) ||
+              (!parseMethod && Actions.isObjCMethodDecl(MCDecl)));
+  if (skip)
+    return;
+  
   // Save the current token position.
   SourceLocation OrigLoc = Tok.getLocation();
 
@@ -2832,24 +2850,25 @@
   LM.Toks.push_back(Tok);
   PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
   
-  // MDecl might be null due to error in method prototype, etc.
-  Decl *MDecl = LM.D;
   // Consume the previously pushed token.
   ConsumeAnyToken();
     
   assert(Tok.is(tok::l_brace) && "Inline objective-c method not starting with '{'");
   SourceLocation BraceLoc = Tok.getLocation();
-  // Enter a scope for the method body.
+  // Enter a scope for the method or c-fucntion body.
   ParseScope BodyScope(this,
-                       Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope);
+                       parseMethod
+                       ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
+                       : Scope::FnScope|Scope::DeclScope);
     
-  // Tell the actions module that we have entered a method definition with the
-  // specified Declarator for the method.
-  Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl);
+  // Tell the actions module that we have entered a method or c-function definition 
+  // with the specified Declarator for the method/function.
+  Actions.ActOnStartOfObjCMethodOrCFunctionDef(getCurScope(), MCDecl, parseMethod);
     
   if (SkipFunctionBodies && trySkippingFunctionBody()) {
     BodyScope.Exit();
-    return Actions.ActOnFinishFunctionBody(MDecl, 0);
+    (void)Actions.ActOnFinishFunctionBody(MCDecl, 0);
+    return;
   }
     
   StmtResult FnBody(ParseCompoundStatementBody());
@@ -2864,7 +2883,7 @@
   // Leave the function body scope.
   BodyScope.Exit();
     
-  MDecl = Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
+  (void)Actions.ActOnFinishFunctionBody(MCDecl, FnBody.take());
 
   if (Tok.getLocation() != OrigLoc) {
     // Due to parsing error, we either went over the cached tokens or
@@ -2878,5 +2897,5 @@
         ConsumeAnyToken();
   }
   
-  return MDecl;
+  return;
 }

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=159626&r1=159625&r2=159626&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Jul  2 18:37:09 2012
@@ -766,14 +766,16 @@
     if (KW.is(tok::kw_default) || KW.is(tok::kw_delete))
       return false;
   }
-
+  
   return Tok.is(tok::equal) ||      // int X()=  -> not a function def
     Tok.is(tok::comma) ||           // int X(),  -> not a function def
     Tok.is(tok::semi)  ||           // int X();  -> not a function def
     Tok.is(tok::kw_asm) ||          // int X() __asm__ -> not a function def
     Tok.is(tok::kw___attribute) ||  // int X() __attr__ -> not a function def
     (getLangOpts().CPlusPlus &&
-     Tok.is(tok::l_paren));         // int X(0) -> not a function def [C++]
+     Tok.is(tok::l_paren)) ||       // int X(0) -> not a function def [C++]
+    (CurParsedObjCImpl && 
+     Tok.is(tok::l_brace));        // C-function  nested in an @implementation
 }
 
 /// \brief Determine whether the current token, if it occurs after a

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=159626&r1=159625&r2=159626&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Jul  2 18:37:09 2012
@@ -265,12 +265,36 @@
     AddFactoryMethodToGlobalPool(MDecl, true);
 }
 
-/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
-/// and user declared, in the method definition's AST.
-void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
-  assert(getCurMethodDecl() == 0 && "Method parsing confused");
+/// ActOnStartOfObjCMethodOrCFunctionDef - This routine sets up parameters; invisible
+/// and user declared, in the method definition's AST. This routine is also  called
+/// for C-functions defined in an Objective-c class implementation.
+void Sema::ActOnStartOfObjCMethodOrCFunctionDef(Scope *FnBodyScope, Decl *D,
+                                                bool parseMethod) {
+  assert((getCurMethodDecl() == 0 && getCurFunctionDecl() == 0) &&
+         "Method/c-function parsing confused");
+  if (!parseMethod) {
+    FunctionDecl *FDecl = FDecl = dyn_cast_or_null<FunctionDecl>(D);
+    // If we don't have a valid c-function decl, simply return.
+    if (!FDecl)
+      return;
+    PushDeclContext(FnBodyScope, FDecl);
+    PushFunctionScope();
+    
+    for (FunctionDecl::param_const_iterator PI = FDecl->param_begin(),
+         E = FDecl->param_end(); PI != E; ++PI) {
+      ParmVarDecl *Param = (*PI);
+      if (!Param->isInvalidDecl() &&
+          RequireCompleteType(Param->getLocation(), Param->getType(),
+                              diag::err_typecheck_decl_incomplete_type))
+        Param->setInvalidDecl();
+      if ((*PI)->getIdentifier())
+        PushOnScopeChains(*PI, FnBodyScope);
+    }
+    return;
+  }
+  
   ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
-
+  
   // If we don't have a valid method decl, simply return.
   if (!MDecl)
     return;

Added: cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m?rev=159626&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m (added)
+++ cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m Mon Jul  2 18:37:09 2012
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1  -fsyntax-only -Werror -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -Werror -verify -Wno-objc-root-class %s
+// rdar://10387088
+
+ at interface MyClass
+- (void)someMethod;
+ at end
+
+ at implementation MyClass
+- (void)someMethod {
+    [self privateMethod];  // clang already does not warn here
+}
+
+int bar(MyClass * myObject) {
+    [myObject privateMethod]; 
+    return gorfbar(myObject);
+}
+- (void)privateMethod { }
+
+int gorfbar(MyClass * myObject) {
+    [myObject privateMethod]; 
+    [myObject privateMethod1]; 
+    return getMe + bar(myObject);
+}
+
+- (void)privateMethod1 {
+  getMe = getMe+1;
+}
+
+static int getMe;
+
+ at end





More information about the cfe-commits mailing list