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 
20 namespace clang {
21 
22 class Expr;
23 class 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 ///
38 class 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 
106 public:
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.
208 class Designation {
209   /// Designators - The actual designators for this initializer.
210   SmallVector<Designator, 2> Designators;
211 
212 public:
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