--- /dev/null
+//===--- 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
//
//===----------------------------------------------------------------------===//
+#include "clang/Parse/Designator.h"
#include "clang/Parse/Parser.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
/// 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()) {
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();
- }
}
}
}
/// 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();
// 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) {
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) {
// 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.
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]);