[cfe-commits] r58205 - in /cfe/trunk: clang.xcodeproj/project.pbxproj include/clang/Parse/Action.h include/clang/Parse/DeclSpec.h include/clang/Parse/Designator.h include/clang/Parse/Parser.h lib/Parse/ParseInit.cpp

Chris Lattner sabre at nondot.org
Sun Oct 26 15:36:07 PDT 2008


Author: lattner
Date: Sun Oct 26 17:36:07 2008
New Revision: 58205

URL: http://llvm.org/viewvc/llvm-project?rev=58205&view=rev
Log:
This patch continues parser-level implementation of designators:

1. It introduces new parser level abstractions for designators
   that are used to communicate between parser and sema.
2. This fixes a FIXME where "identifier ':'" was considered to be
   a designator even if it wasn't the first in a designator list.
3. In the "identifier ':'" case, it actually builds the designator
   representation.


Added:
    cfe/trunk/include/clang/Parse/Designator.h
Modified:
    cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseInit.cpp

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=58205&r1=58204&r2=58205&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Sun Oct 26 17:36:07 2008
@@ -441,6 +441,7 @@
 		DE3986F30CB8D50C00223765 /* IdentifierTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentifierTable.cpp; sourceTree = "<group>"; };
 		DE3B90DE0EAC5EF200D01046 /* ExtensionRAIIObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtensionRAIIObject.h; path = lib/Parse/ExtensionRAIIObject.h; sourceTree = "<group>"; };
 		DE3B921C0EB1A81400D01046 /* SemaInherit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaInherit.h; path = lib/Sema/SemaInherit.h; sourceTree = "<group>"; };
+		DE3B92230EB5152000D01046 /* Designator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Designator.h; path = clang/Parse/Designator.h; sourceTree = "<group>"; };
 		DE41211D0D7F1BBE0080F80A /* GRWorkList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRWorkList.h; path = clang/Analysis/PathSensitive/GRWorkList.h; sourceTree = "<group>"; };
 		DE41211E0D7F1BBE0080F80A /* SymbolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolManager.h; path = clang/Analysis/PathSensitive/SymbolManager.h; sourceTree = "<group>"; };
 		DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRBlockCounter.h; path = clang/Analysis/PathSensitive/GRBlockCounter.h; sourceTree = "<group>"; };
@@ -764,6 +765,7 @@
 				84D9A88B0C1A581300AC7ABC /* AttributeList.h */,
 				DE06E8130A8FF9330050E87E /* Action.h */,
 				DE17336F0B068DC60080B521 /* DeclSpec.h */,
+				DE3B92230EB5152000D01046 /* Designator.h */,
 				DE1F22020A7D852A00FBF588 /* Parser.h */,
 				DE06BECA0A854E4B0050E87E /* Scope.h */,
 			);

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Oct 26 17:36:07 2008
@@ -29,6 +29,7 @@
   class Scope;
   class Action;
   class Selector;
+  class InitListDesignations;
   // Lex.
   class Token;
 

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

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Sun Oct 26 17:36:07 2008
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_PARSE_SEMADECLSPEC_H
-#define LLVM_CLANG_PARSE_SEMADECLSPEC_H
+#ifndef LLVM_CLANG_PARSE_DECLSPEC_H
+#define LLVM_CLANG_PARSE_DECLSPEC_H
 
 #include "clang/Parse/Action.h"
 #include "clang/Parse/AttributeList.h"

Added: cfe/trunk/include/clang/Parse/Designator.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Designator.h?rev=58205&view=auto

==============================================================================
--- cfe/trunk/include/clang/Parse/Designator.h (added)
+++ cfe/trunk/include/clang/Parse/Designator.h Sun Oct 26 17:36:07 2008
@@ -0,0 +1,209 @@
+//===--- Designator.h - Initialization Designator ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces used to represent Designators in the parser and
+// is the input to Actions module.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H
+#define LLVM_CLANG_PARSE_DESIGNATOR_H
+
+#include "clang/Parse/Action.h"
+
+namespace clang {
+
+/// Designator - This class is a discriminated union which holds the various
+/// different sorts of designators possible.  A Designation is an array of
+/// these.  An example of a designator are things like this:
+///     [8] .field [47]        // C99 designation: 3 designators
+///     [8 ... 47]  field:     // GNU extensions: 2 designators
+/// These occur in initializers, e.g.:
+///  int a[10] = {2, 4, [8]=9, 10};
+///
+class Designator {
+public:
+  enum DesignatorKind {
+    FieldDesignator, ArrayDesignator, ArrayRangeDesignator
+  };
+private:
+  DesignatorKind Kind;
+  
+  struct FieldDesignatorInfo {
+    const IdentifierInfo *II;
+  };
+  struct ArrayDesignatorInfo {
+    Action::ExprTy *Index;
+  };
+  struct ArrayRangeDesignatorInfo {
+    Action::ExprTy *Start, *End;
+  };
+  
+  union {
+    FieldDesignatorInfo FieldInfo;
+    ArrayDesignatorInfo ArrayInfo;
+    ArrayRangeDesignatorInfo ArrayRangeInfo;
+  };
+  
+public:
+  
+  DesignatorKind getKind() const { return Kind; }
+  bool isFieldDesignator() const { return Kind == FieldDesignator; }
+  bool isArrayDesignator() const { return Kind == ArrayDesignator; }
+  bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
+
+  const IdentifierInfo *getField() const {
+    assert(isFieldDesignator() && "Invalid accessor");
+    return FieldInfo.II;
+  }
+  
+  Action::ExprTy *getArrayIndex() const {
+    assert(isArrayDesignator() && "Invalid accessor");
+    return ArrayInfo.Index;
+  }
+
+  Action::ExprTy *getArrayRangeStart() const {
+    assert(isArrayRangeDesignator() && "Invalid accessor");
+    return ArrayRangeInfo.Start;
+  }
+  Action::ExprTy *getArrayRangeEnd() const {
+    assert(isArrayRangeDesignator() && "Invalid accessor");
+    return ArrayRangeInfo.End;
+  }
+  
+  
+  static Designator getField(const IdentifierInfo *II) {
+    Designator D;
+    D.Kind = FieldDesignator;
+    D.FieldInfo.II = II;
+    return D;
+  }
+
+  static Designator getArray(Action::ExprTy *Index) {
+    Designator D;
+    D.Kind = ArrayDesignator;
+    D.ArrayInfo.Index = Index;
+    return D;
+  }
+  
+  static Designator getArrayRange(Action::ExprTy *Start, Action::ExprTy *End) {
+    Designator D;
+    D.Kind = ArrayRangeDesignator;
+    D.ArrayRangeInfo.Start = Start;
+    D.ArrayRangeInfo.End = End;
+    return D;
+  }
+  
+  /// ClearExprs - Null out any expression references, which prevents them from
+  /// being 'delete'd later.
+  void ClearExprs(Action &Actions) {
+    switch (Kind) {
+    case FieldDesignator: return;
+    case ArrayDesignator:
+      ArrayInfo.Index = 0;
+      return;
+    case ArrayRangeDesignator:
+      ArrayRangeInfo.Start = 0;
+      ArrayRangeInfo.End = 0;
+      return;
+    }
+  }
+  
+  /// FreeExprs - Release any unclaimed memory for the expressions in this
+  /// designator.
+  void FreeExprs(Action &Actions) {
+    switch (Kind) {
+    case FieldDesignator: return; // nothing to free.
+    case ArrayDesignator:
+      Actions.DeleteExpr(getArrayIndex());
+      return;
+    case ArrayRangeDesignator:
+      Actions.DeleteExpr(getArrayRangeStart());
+      Actions.DeleteExpr(getArrayRangeEnd());
+      return;
+    }
+  }
+};
+
+  
+/// Designation - Represent a full designation, which is a sequence of
+/// designators.  This class is mostly a helper for InitListDesignations.
+class Designation {
+  friend class InitListDesignations;
+  
+  /// InitIndex - The index of the initializer expression this is for.  For
+  /// example, if the initializer were "{ A, .foo=B, C }" a Designation would
+  /// exist with InitIndex=1, because element #1 has a designation.
+  unsigned InitIndex;
+  
+  /// Designators - The actual designators for this initializer.
+  llvm::SmallVector<Designator, 2> Designators;
+  
+  Designation(unsigned Idx) : InitIndex(Idx) {}
+public:
+  
+  /// AddDesignator - Add a designator to the end of this list.
+  void AddDesignator(Designator D) {
+    Designators.push_back(D);
+  }  
+  
+  /// ClearExprs - Null out any expression references, which prevents them from
+  /// being 'delete'd later.
+  void ClearExprs(Action &Actions) {
+    for (unsigned i = 0, e = Designators.size(); i != e; ++i)
+      Designators[i].ClearExprs(Actions);
+  }
+  
+  /// FreeExprs - Release any unclaimed memory for the expressions in this
+  /// designation.
+  void FreeExprs(Action &Actions) {
+    for (unsigned i = 0, e = Designators.size(); i != e; ++i)
+      Designators[i].FreeExprs(Actions);
+  }
+};
+  
+  
+/// InitListDesignations - This contains all the designators for an
+/// initializer list.  This is somewhat like a two dimensional array of
+/// Designators, but is optimized for the cases when designators are not
+/// present.
+class InitListDesignations {
+  Action &Actions;
+  
+  /// Designations - All of the designators in this init list.  These are kept
+  /// in order sorted by their InitIndex.
+  llvm::SmallVector<Designation, 3> Designations;
+  
+  InitListDesignations(const InitListDesignations&); // DO NOT IMPLEMENT
+  void operator=(const InitListDesignations&);      // DO NOT IMPLEMENT
+public:
+  InitListDesignations(Action &A) : Actions(A) {}
+  
+  ~InitListDesignations() {
+    // Release any unclaimed memory for the expressions in this init list.
+    for (unsigned i = 0, e = Designations.size(); i != e; ++i)
+      Designations[i].FreeExprs(Actions);
+  }
+  
+  bool hasAnyDesignators() const {
+    return Designations.empty();
+  }
+  
+  Designation &CreateDesignation(unsigned Idx) {
+    assert((Designations.empty() || Designations.back().InitIndex < Idx) &&
+           "not sorted by InitIndex!");
+    Designations.push_back(Designation(Idx));
+    return Designations.back();
+  }
+  
+};
+
+} // end namespace clang
+
+#endif

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Oct 26 17:36:07 2008
@@ -480,7 +480,8 @@
   //===--------------------------------------------------------------------===//
   // C99 6.7.8: Initialization.
   ExprResult ParseInitializer();
-  ExprResult ParseInitializerWithPotentialDesignator();
+  ExprResult ParseInitializerWithPotentialDesignator(InitListDesignations &D,
+                                                     unsigned InitNum);
   
   //===--------------------------------------------------------------------===//
   // clang Expressions

Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=58205&r1=58204&r2=58205&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Sun Oct 26 17:36:07 2008
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Parse/Designator.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/SmallString.h"
@@ -54,7 +55,32 @@
 /// initializer (because it is an expression).  We need to consider this case
 /// when parsing array designators.
 ///
-Parser::ExprResult Parser::ParseInitializerWithPotentialDesignator() {
+Parser::ExprResult Parser::
+ParseInitializerWithPotentialDesignator(InitListDesignations &Designations,
+                                        unsigned InitNum) {
+  
+  // If this is the old-style GNU extension:
+  //   designation ::= identifier ':'
+  // Handle it as a field designator.  Otherwise, this must be the start of a
+  // normal expression.
+  if (Tok.is(tok::identifier)) {
+    if (NextToken().is(tok::colon)) {
+      Diag(Tok, diag::ext_gnu_old_style_field_designator);
+
+      Designation &D = Designations.CreateDesignation(InitNum);
+      D.AddDesignator(Designator::getField(Tok.getIdentifierInfo()));
+      ConsumeToken(); // Eat the identifier.
+      
+      assert(Tok.is(tok::colon) && "NextToken() not working properly!");
+      ConsumeToken();
+      return ParseInitializer();
+    }
+    
+    // Otherwise, parse the assignment-expression.
+    return ParseAssignmentExpression();
+  }
+  
+  
   // Parse each designator in the designator list until we find an initializer.
   while (1) {
     switch (Tok.getKind()) {
@@ -138,25 +164,6 @@
       MatchRHSPunctuation(tok::r_square, StartLoc);
       break;
     }
-    case tok::identifier: {
-      // Due to the GNU "designation: identifier ':'" extension, we don't know
-      // whether something starting with an identifier is an
-      // assignment-expression or if it is an old-style structure field
-      // designator.
-      // TODO: Check that this is the first designator.
-      
-      // If this is the gross GNU extension, handle it now.
-      if (NextToken().is(tok::colon)) {
-        Diag(Tok, diag::ext_gnu_old_style_field_designator);
-        ConsumeToken(); // The identifier.
-        assert(Tok.is(tok::colon) && "NextToken() not working properly!");
-        ConsumeToken();
-        return ParseInitializer();
-      }
-      
-      // Otherwise, parse the assignment-expression.
-      return ParseAssignmentExpression();
-    }
     }
   }
 }
@@ -174,6 +181,8 @@
 ///         initializer-list ',' designation[opt] initializer
 ///
 Parser::ExprResult Parser::ParseInitializer() {
+  // TODO: Split this up into ParseInitializer + ParseBraceInitializer, make
+  // ParseInitializer inline so that the non-brace case is short-cut.
   if (Tok.isNot(tok::l_brace))
     return ParseAssignmentExpression();
 
@@ -186,7 +195,15 @@
     // Match the '}'.
     return Actions.ActOnInitList(LBraceLoc, 0, 0, ConsumeBrace());
   }
+  
+  /// InitExprs - This is the actual list of expressions contained in the
+  /// initializer.
   llvm::SmallVector<ExprTy*, 8> InitExprs;
+  
+  /// ExprDesignators - For each initializer, keep track of the designator that
+  /// was specified for it, if any.
+  InitListDesignations InitExprDesignations(Actions);
+
   bool InitExprsOk = true;
   
   while (1) {
@@ -198,7 +215,8 @@
     if (!MayBeDesignationStart(Tok.getKind()))
       SubElt = ParseInitializer();
     else
-      SubElt = ParseInitializerWithPotentialDesignator();
+      SubElt = ParseInitializerWithPotentialDesignator(InitExprDesignations,
+                                                       InitExprs.size());
 
     // If we couldn't parse the subelement, bail out.
     if (!SubElt.isInvalid) {
@@ -220,7 +238,7 @@
     // If we don't have a comma continued list, we're done.
     if (Tok.isNot(tok::comma)) break;
     
-    // FIXME: save comma locations.
+    // TODO: save comma locations if some client cares.
     ConsumeToken();
     
     // Handle trailing comma.
@@ -230,7 +248,7 @@
     return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(), 
                                  ConsumeBrace());
   
-  // Delete any parsed subexpressions.
+  // On error, delete any parsed subexpressions.
   for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
     Actions.DeleteExpr(InitExprs[i]);
   





More information about the cfe-commits mailing list