1//===--- Designator.h - Initialization Designator ---------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines interfaces used to represent designators (a la
10// C99 designated initializers) during parsing.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H
15#define LLVM_CLANG_SEMA_DESIGNATOR_H
16
17#include "clang/Basic/SourceLocation.h"
18#include "llvm/ADT/SmallVector.h"
19
20namespace clang {
21
22class Expr;
23class IdentifierInfo;
24
25/// Designator - A designator in a C99 designated initializer.
26///
27/// This class is a discriminated union which holds the various
28/// different sorts of designators possible. A Designation is an array of
29/// these.  An example of a designator are things like this:
30///
31///      [8] .field [47]        // C99 designation: 3 designators
32///      [8 ... 47]  field:     // GNU extensions: 2 designators
33///
34/// These occur in initializers, e.g.:
35///
36///      int a[10] = {2, 4, [8]=9, 10};
37///
38class Designator {
39  /// A field designator, e.g., ".x = 42".
40  struct FieldDesignatorInfo {
41    /// Refers to the field being initialized.
42    const IdentifierInfo *FieldName;
43
44    /// The location of the '.' in the designated initializer.
45    SourceLocation DotLoc;
46
47    /// The location of the field name in the designated initializer.
48    SourceLocation FieldLoc;
49
50    FieldDesignatorInfo(const IdentifierInfo *FieldName, SourceLocation DotLoc,
51                        SourceLocation FieldLoc)
52        : FieldName(FieldName), DotLoc(DotLoc), FieldLoc(FieldLoc) {}
53  };
54
55  /// An array designator, e.g., "[42] = 0".
56  struct ArrayDesignatorInfo {
57    Expr *Index;
58
59    // The location of the '[' in the designated initializer.
60    SourceLocation LBracketLoc;
61
62    // The location of the ']' in the designated initializer.
63    mutable SourceLocation RBracketLoc;
64
65    ArrayDesignatorInfo(Expr *Index, SourceLocation LBracketLoc)
66        : Index(Index), LBracketLoc(LBracketLoc) {}
67  };
68
69  /// An array range designator, e.g. "[42 ... 50] = 1".
70  struct ArrayRangeDesignatorInfo {
71    Expr *Start;
72    Expr *End;
73
74    // The location of the '[' in the designated initializer.
75    SourceLocation LBracketLoc;
76
77    // The location of the '...' in the designated initializer.
78    SourceLocation EllipsisLoc;
79
80    // The location of the ']' in the designated initializer.
81    mutable SourceLocation RBracketLoc;
82
83    ArrayRangeDesignatorInfo(Expr *Start, Expr *End, SourceLocation LBracketLoc,
84                             SourceLocation EllipsisLoc)
85        : Start(Start), End(End), LBracketLoc(LBracketLoc),
86          EllipsisLoc(EllipsisLoc) {}
87  };
88
89  /// The kind of designator this describes.
90  enum DesignatorKind {
91    FieldDesignator,
92    ArrayDesignator,
93    ArrayRangeDesignator
94  };
95
96  DesignatorKind Kind;
97
98  union {
99    FieldDesignatorInfo FieldInfo;
100    ArrayDesignatorInfo ArrayInfo;
101    ArrayRangeDesignatorInfo ArrayRangeInfo;
102  };
103
104  Designator(DesignatorKind Kind) : Kind(Kind) {}
105
106public:
107  bool isFieldDesignator() const { return Kind == FieldDesignator; }
108  bool isArrayDesignator() const { return Kind == ArrayDesignator; }
109  bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
110
111  //===--------------------------------------------------------------------===//
112  // FieldDesignatorInfo
113
114  /// Creates a field designator.
115  static Designator CreateFieldDesignator(const IdentifierInfo *FieldName,
116                                          SourceLocation DotLoc,
117                                          SourceLocation FieldLoc) {
118    Designator D(FieldDesignator);
119    new (&D.FieldInfo) FieldDesignatorInfo(FieldName, DotLoc, FieldLoc);
120    return D;
121  }
122
123  const IdentifierInfo *getFieldDecl() const {
124    assert(isFieldDesignator() && "Invalid accessor");
125    return FieldInfo.FieldName;
126  }
127
128  SourceLocation getDotLoc() const {
129    assert(isFieldDesignator() && "Invalid accessor");
130    return FieldInfo.DotLoc;
131  }
132
133  SourceLocation getFieldLoc() const {
134    assert(isFieldDesignator() && "Invalid accessor");
135    return FieldInfo.FieldLoc;
136  }
137
138  //===--------------------------------------------------------------------===//
139  // ArrayDesignatorInfo:
140
141  /// Creates an array designator.
142  static Designator CreateArrayDesignator(Expr *Index,
143                                          SourceLocation LBracketLoc) {
144    Designator D(ArrayDesignator);
145    new (&D.ArrayInfo) ArrayDesignatorInfo(Index, LBracketLoc);
146    return D;
147  }
148
149  Expr *getArrayIndex() const {
150    assert(isArrayDesignator() && "Invalid accessor");
151    return ArrayInfo.Index;
152  }
153
154  SourceLocation getLBracketLoc() const {
155    assert((isArrayDesignator() || isArrayRangeDesignator()) &&
156           "Invalid accessor");
157    return isArrayDesignator() ? ArrayInfo.LBracketLoc
158                               : ArrayRangeInfo.LBracketLoc;
159  }
160
161  SourceLocation getRBracketLoc() const {
162    assert((isArrayDesignator() || isArrayRangeDesignator()) &&
163           "Invalid accessor");
164    return isArrayDesignator() ? ArrayInfo.RBracketLoc
165                               : ArrayRangeInfo.RBracketLoc;
166  }
167
168  //===--------------------------------------------------------------------===//
169  // ArrayRangeDesignatorInfo:
170
171  /// Creates a GNU array-range designator.
172  static Designator CreateArrayRangeDesignator(Expr *Start, Expr *End,
173                                               SourceLocation LBracketLoc,
174                                               SourceLocation EllipsisLoc) {
175    Designator D(ArrayRangeDesignator);
176    new (&D.ArrayRangeInfo)
177        ArrayRangeDesignatorInfo(Start, End, LBracketLoc, EllipsisLoc);
178    return D;
179  }
180
181  Expr *getArrayRangeStart() const {
182    assert(isArrayRangeDesignator() && "Invalid accessor");
183    return ArrayRangeInfo.Start;
184  }
185
186  Expr *getArrayRangeEnd() const {
187    assert(isArrayRangeDesignator() && "Invalid accessor");
188    return ArrayRangeInfo.End;
189  }
190
191  SourceLocation getEllipsisLoc() const {
192    assert(isArrayRangeDesignator() && "Invalid accessor");
193    return ArrayRangeInfo.EllipsisLoc;
194  }
195
196  void setRBracketLoc(SourceLocation RBracketLoc) const {
197    assert((isArrayDesignator() || isArrayRangeDesignator()) &&
198           "Invalid accessor");
199    if (isArrayDesignator())
200      ArrayInfo.RBracketLoc = RBracketLoc;
201    else
202      ArrayRangeInfo.RBracketLoc = RBracketLoc;
203  }
204};
205
206/// Designation - Represent a full designation, which is a sequence of
207/// designators.  This class is mostly a helper for InitListDesignations.
208class Designation {
209  /// Designators - The actual designators for this initializer.
210  SmallVector<Designator, 2> Designators;
211
212public:
213  /// AddDesignator - Add a designator to the end of this list.
214  void AddDesignator(Designator D) { Designators.push_back(D); }
215
216  bool empty() const { return Designators.empty(); }
217
218  unsigned getNumDesignators() const { return Designators.size(); }
219  const Designator &getDesignator(unsigned Idx) const {
220    assert(Idx < Designators.size());
221    return Designators[Idx];
222  }
223};
224
225} // end namespace clang
226
227#endif
228