[cfe-commits] r39074 - in /cfe/cfe/trunk: Parse/MinimalAction.cpp Parse/ParseDecl.cpp Parse/ParseStmt.cpp Parse/Parser.cpp include/clang/Parse/Action.h include/clang/Parse/Parser.h

snaroff at cs.uiuc.edu snaroff at cs.uiuc.edu
Wed Jul 11 09:27:19 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:27:19 2007
New Revision: 39074

URL: http://llvm.org/viewvc/llvm-project?rev=39074&view=rev
Log:

- Added basic structure for parsing top level Objective-C forms.
- Extended the typedef mechanism for classes, improved performance of the common case.
- Implemented @class in the parser.

Modified:
    cfe/cfe/trunk/Parse/MinimalAction.cpp
    cfe/cfe/trunk/Parse/ParseDecl.cpp
    cfe/cfe/trunk/Parse/ParseStmt.cpp
    cfe/cfe/trunk/Parse/Parser.cpp
    cfe/cfe/trunk/include/clang/Parse/Action.h
    cfe/cfe/trunk/include/clang/Parse/Parser.h

Modified: cfe/cfe/trunk/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/MinimalAction.cpp?rev=39074&r1=39073&r2=39074&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/MinimalAction.cpp (original)
+++ cfe/cfe/trunk/Parse/MinimalAction.cpp Wed Jul 11 11:27:19 2007
@@ -17,18 +17,24 @@
 using namespace llvm;
 using namespace clang;
 
-/// TypedefInfo - A link exists here for each scope that an identifier is
+/// TypeNameInfo - A link exists here for each scope that an identifier is
 /// defined.
-struct TypedefInfo {
-  TypedefInfo *Prev;
-  bool isTypedef;
+struct TypeNameInfo {
+  TypeNameInfo *Prev;
+  bool isTypeName;
+  
+  TypeNameInfo(bool istypename, TypeNameInfo *prev) {
+    isTypeName = istypename;
+	Prev = prev;
+  }
+    
 };
 
 /// isTypedefName - This looks at the IdentifierInfo::FETokenInfo field to
 /// determine whether the name is a typedef or not in this scope.
-bool EmptyAction::isTypedefName(const IdentifierInfo &II, Scope *S) const {
-  TypedefInfo *TI = II.getFETokenInfo<TypedefInfo>();
-  return TI != 0 && TI->isTypedef;
+bool EmptyAction::isTypeName(const IdentifierInfo &II, Scope *S) const {
+  TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>();
+  return TI != 0 && TI->isTypeName;
 }
 
 /// ParseDeclarator - If this is a typedef declarator, we modify the
@@ -37,20 +43,41 @@
 Action::DeclTy *
 EmptyAction::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
                              DeclTy *LastInGroup) {
+  IdentifierInfo *II = D.getIdentifier();
+  
   // If there is no identifier associated with this declarator, bail out.
-  if (D.getIdentifier() == 0) return 0;
+  if (II == 0) return 0;
   
-  // Remember whether or not this declarator is a typedef.
-  TypedefInfo *TI = new TypedefInfo();
-  TI->isTypedef = D.getDeclSpec().StorageClassSpec == DeclSpec::SCS_typedef;
-
-  // Add this to the linked-list hanging off the identifier.
-  IdentifierInfo &II = *D.getIdentifier();
-  TI->Prev = II.getFETokenInfo<TypedefInfo>();
-  II.setFETokenInfo(TI);
+  TypeNameInfo *weCurrentlyHaveTypeInfo = II->getFETokenInfo<TypeNameInfo>();
+  bool isTypeName = D.getDeclSpec().StorageClassSpec == DeclSpec::SCS_typedef;
+
+  // this check avoids creating TypeNameInfo objects for the common case.
+  // It does need to handle the uncommon case of shadowing a typedef name with a 
+  // non-typedef name. e.g. { typedef int a; a xx; { int a; } }
+  if (weCurrentlyHaveTypeInfo || isTypeName) {
+    TypeNameInfo *TI = new TypeNameInfo(isTypeName, weCurrentlyHaveTypeInfo);
+
+    II->setFETokenInfo(TI);
+  
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(II);
+  } 
+  return 0;
+}
+
+// Scope will always be top level file scope. 
+
+Action::DeclTy *
+EmptyAction::ParsedClassDeclaration(Scope *S,
+									IdentifierInfo **identList, unsigned nElements) {
+  for (unsigned i = 0; i < nElements; i++) {
+    TypeNameInfo *TI = new TypeNameInfo(1, identList[i]->getFETokenInfo<TypeNameInfo>());
+
+    identList[i]->setFETokenInfo(TI);
   
-  // Remember that this needs to be removed when the scope is popped.
-  S->AddDecl(&II);
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(identList[i]);
+  }
   return 0;
 }
 
@@ -60,12 +87,14 @@
   for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
        I != E; ++I) {
     IdentifierInfo &II = *static_cast<IdentifierInfo*>(*I);
-    TypedefInfo *TI = II.getFETokenInfo<TypedefInfo>();
+    TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>();
     assert(TI && "This decl didn't get pushed??");
-
-    TypedefInfo *Next = TI->Prev;
-    delete TI;
     
-    II.setFETokenInfo(Next);
+	if (TI) {
+      TypeNameInfo *Next = TI->Prev;
+      delete TI;
+    
+      II.setFETokenInfo(Next);
+	}
   }
 }

Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=39074&r1=39073&r2=39074&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:27:19 2007
@@ -262,7 +262,7 @@
           DS.TypeSpecComplex == DeclSpec::TSC_unspecified &&
           DS.TypeSpecSign == DeclSpec::TSS_unspecified &&
           // It has to be available as a typedef too!
-          Actions.isTypedefName(*Tok.getIdentifierInfo(), CurScope)) {
+          Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
         isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef, PrevSpec);
         break;
       }
@@ -645,7 +645,7 @@
     
     // typedef-name
   case tok::identifier:
-    return Actions.isTypedefName(*Tok.getIdentifierInfo(), CurScope);
+    return Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope);
     
     // TODO: Attributes.
   }
@@ -698,7 +698,7 @@
     
     // typedef-name
   case tok::identifier:
-    return Actions.isTypedefName(*Tok.getIdentifierInfo(), CurScope);
+    return Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope);
     // TODO: Attributes.
   }
 }
@@ -923,7 +923,7 @@
     HasPrototype = false;
     IsEmpty      = true;
   } else if (Tok.getKind() == tok::identifier &&
-             !Actions.isTypedefName(*Tok.getIdentifierInfo(), CurScope)) {
+             !Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
     // Identifier list.  Note that '(' identifier-list ')' is only allowed for
     // normal declarators, not for abstract-declarators.
     assert(D.isPastIdentifier() && "Identifier (if present) must be passed!");

Modified: cfe/cfe/trunk/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseStmt.cpp?rev=39074&r1=39073&r2=39074&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseStmt.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseStmt.cpp Wed Jul 11 11:27:19 2007
@@ -205,7 +205,7 @@
   
   // Check to see if this is a declaration.
   if (!OnlyStatement &&
-      Actions.isTypedefName(*IdentTok.getIdentifierInfo(), CurScope)) {
+      Actions.isTypeName(*IdentTok.getIdentifierInfo(), CurScope)) {
     // Handle this.  Warn/disable if in middle of block and !C99.
     DeclSpec DS;
     

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

==============================================================================
--- cfe/cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/cfe/trunk/Parse/Parser.cpp Wed Jul 11 11:27:19 2007
@@ -287,6 +287,15 @@
                      "top-level asm block");
     // TODO: Invoke action for top-level asm.
     return 0;
+  case tok::at:
+    ObjCParseAtDirectives();
+    return 0;
+  case tok::minus:
+    ObjCParseInstanceMethodDeclaration();
+	return 0;
+  case tok::plus:
+    ObjCParseClassMethodDeclaration();
+    return 0;
   default:
     // We can't tell whether this is a function-definition or declaration yet.
     return ParseDeclarationOrFunctionDefinition();
@@ -443,3 +452,69 @@
   
   MatchRHSPunctuation(tok::r_paren, Loc);
 }
+
+void Parser::ObjCParseAtDirectives() {
+  SourceLocation atLoc = ConsumeToken(); // the "@"
+
+  IdentifierInfo *II = Tok.getIdentifierInfo();
+  if (II == 0) return;  // Not an identifier.
+      
+  switch (II->getObjCKeywordID()) {
+    case tok::objc_class:
+	  ObjCParseClassDeclaration(atLoc);
+    case tok::objc_interface:
+	  ObjCParseInterfaceDeclaration();
+    case tok::objc_protocol:
+	  ObjCParseProtocolDeclaration();
+    case tok::objc_implementation:
+	  ObjCParseImplementationDeclaration();
+    case tok::objc_end:
+	  ObjCParseEndDeclaration();
+    case tok::objc_compatibility_alias:
+	  ObjCParseAliasDeclaration();
+	default:
+	  ; // TODO: need to issue a diagnostic...
+  }
+}
+
+///
+/// objc-class-declaration: 
+///    @class identifier-list ;
+///  
+void Parser::ObjCParseClassDeclaration(SourceLocation atLoc) {
+  ConsumeToken(); // the identifier "class"
+  SmallVector<IdentifierInfo *, 8> classNames;
+  
+  while (1) {
+    if (Tok.getKind() == tok::identifier) {
+	  classNames.push_back(Tok.getIdentifierInfo());
+	} else {
+	  Diag(diag::err_expected_ident);
+	}
+	ConsumeToken();
+	if (Tok.getKind() == tok::comma)
+	  ConsumeToken();
+	else
+	  break;
+  }
+  if (Tok.getKind() == tok::semi) {
+    SourceLocation semiLoc = ConsumeToken();
+	Actions.ParsedClassDeclaration(CurScope,&classNames[0],classNames.size());
+  }
+}
+void Parser::ObjCParseInterfaceDeclaration() {
+}
+void Parser::ObjCParseProtocolDeclaration() {
+}
+void Parser::ObjCParseImplementationDeclaration() {
+}
+void Parser::ObjCParseEndDeclaration() {
+}
+void Parser::ObjCParseAliasDeclaration() {
+}
+
+void Parser::ObjCParseInstanceMethodDeclaration() {
+}
+
+void Parser::ObjCParseClassMethodDeclaration() {
+}

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Action.h Wed Jul 11 11:27:19 2007
@@ -35,7 +35,7 @@
 /// the parser has just done or is about to do when the method is called.  They
 /// are not requests that the actions module do the specified action.
 ///
-/// All of the methods here are optional except isTypedefName(), which must be
+/// All of the methods here are optional except isTypeName(), which must be
 /// specified in order for the parse to complete accurately.  The EmptyAction
 /// class does this bare-minimum of tracking to implement this functionality.
 class Action {
@@ -78,9 +78,9 @@
   // Symbol Table Tracking Callbacks.
   //===--------------------------------------------------------------------===//
   
-  /// isTypedefName - Return true if the specified identifier is a typedef name
+  /// isTypeName - Return true if the specified identifier is a typedef name
   /// in the current scope.
-  virtual bool isTypedefName(const IdentifierInfo &II, Scope *S) const = 0;
+  virtual bool isTypeName(const IdentifierInfo &II, Scope *S) const = 0;
   
   /// ParseDeclarator - This callback is invoked when a declarator is parsed and
   /// 'Init' specifies the initializer if any.  This is for things like:
@@ -111,6 +111,11 @@
   // 'External Declaration' (Top Level) Parsing Callbacks.
   //===--------------------------------------------------------------------===//
   
+  virtual DeclTy *ParsedClassDeclaration(Scope *S,
+                                         IdentifierInfo **identList, unsigned nElements) {
+    return 0;
+  }
+										 
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks.
   //===--------------------------------------------------------------------===//
@@ -271,9 +276,9 @@
 /// to reimplement all of the scoping rules.
 class EmptyAction : public Action {
 public:
-  /// isTypedefName - This looks at the IdentifierInfo::FETokenInfo field to
+  /// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
   /// determine whether the name is a typedef or not in this scope.
-  virtual bool isTypedefName(const IdentifierInfo &II, Scope *S) const;
+  virtual bool isTypeName(const IdentifierInfo &II, Scope *S) const;
   
   /// ParseDeclarator - If this is a typedef declarator, we modify the
   /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
@@ -284,6 +289,10 @@
   /// PopScope - When a scope is popped, if any typedefs are now out-of-scope,
   /// they are removed from the IdentifierInfo::FETokenInfo field.
   virtual void PopScope(SourceLocation Loc, Scope *S);
+  
+  virtual DeclTy *ParsedClassDeclaration(Scope *S,
+									IdentifierInfo **identList, unsigned nElements);
+
 };
   
 }  // end namespace clang

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:27:19 2007
@@ -231,7 +231,18 @@
   DeclTy *ParseFunctionDefinition(Declarator &D);
   void ParseSimpleAsm();
   void ParseAsmStringLiteral();
-  
+
+  // Objective-C External Declarations 
+  void ObjCParseAtDirectives(); 
+  void   ObjCParseClassDeclaration(SourceLocation atLoc);
+  void   ObjCParseInterfaceDeclaration();
+  void   ObjCParseProtocolDeclaration();
+  void   ObjCParseImplementationDeclaration();
+  void   ObjCParseEndDeclaration();
+  void   ObjCParseAliasDeclaration();
+  void ObjCParseInstanceMethodDeclaration();
+  void ObjCParseClassMethodDeclaration();
+
   //===--------------------------------------------------------------------===//
   // C99 6.5: Expressions.
 





More information about the cfe-commits mailing list