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 class Sema;
25 
26 /// Designator - A designator in a C99 designated initializer.
27 ///
28 /// This class is a discriminated union which holds the various
29 /// different sorts of designators possible.  A Designation is an array of
30 /// these.  An example of a designator are things like this:
31 ///     [8] .field [47]        // C99 designation: 3 designators
32 ///     [8 ... 47]  field:     // GNU extensions: 2 designators
33 /// These occur in initializers, e.g.:
34 ///  int a[10] = {2, 4, [8]=9, 10};
35 ///
36 class Designator {
37 public:
38   enum DesignatorKind {
39     FieldDesignator, ArrayDesignator, ArrayRangeDesignator
40   };
41 private:
42   DesignatorKind Kind;
43 
44   struct FieldDesignatorInfo {
45     const IdentifierInfo *II;
46     unsigned DotLoc;
47     unsigned NameLoc;
48   };
49   struct ArrayDesignatorInfo {
50     Expr *Index;
51     unsigned LBracketLoc;
52     mutable unsigned  RBracketLoc;
53   };
54   struct ArrayRangeDesignatorInfo {
55     Expr *Start, *End;
56     unsigned LBracketLoc, EllipsisLoc;
57     mutable unsigned RBracketLoc;
58   };
59 
60   union {
61     FieldDesignatorInfo FieldInfo;
62     ArrayDesignatorInfo ArrayInfo;
63     ArrayRangeDesignatorInfo ArrayRangeInfo;
64   };
65 
66 public:
67 
68   DesignatorKind getKind() const { return Kind; }
69   bool isFieldDesignator() const { return Kind == FieldDesignator; }
70   bool isArrayDesignator() const { return Kind == ArrayDesignator; }
71   bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
72 
73   const IdentifierInfo *getField() const {
74     assert(isFieldDesignator() && "Invalid accessor");
75     return FieldInfo.II;
76   }
77 
78   SourceLocation getDotLoc() const {
79     assert(isFieldDesignator() && "Invalid accessor");
80     return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc);
81   }
82 
83   SourceLocation getFieldLoc() const {
84     assert(isFieldDesignator() && "Invalid accessor");
85     return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc);
86   }
87 
88   Expr *getArrayIndex() const {
89     assert(isArrayDesignator() && "Invalid accessor");
90     return ArrayInfo.Index;
91   }
92 
93   Expr *getArrayRangeStart() const {
94     assert(isArrayRangeDesignator() && "Invalid accessor");
95     return ArrayRangeInfo.Start;
96   }
97   Expr *getArrayRangeEnd() const {
98     assert(isArrayRangeDesignator() && "Invalid accessor");
99     return ArrayRangeInfo.End;
100   }
101 
102   SourceLocation getLBracketLoc() const {
103     assert((isArrayDesignator() || isArrayRangeDesignator()) &&
104            "Invalid accessor");
105     if (isArrayDesignator())
106       return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc);
107     else
108       return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc);
109   }
110 
111   SourceLocation getRBracketLoc() const {
112     assert((isArrayDesignator() || isArrayRangeDesignator()) &&
113            "Invalid accessor");
114     if (isArrayDesignator())
115       return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc);
116     else
117       return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc);
118   }
119 
120   SourceLocation getEllipsisLoc() const {
121     assert(isArrayRangeDesignator() && "Invalid accessor");
122     return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc);
123   }
124 
125   static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc,
126                              SourceLocation NameLoc) {
127     Designator D;
128     D.Kind = FieldDesignator;
129     D.FieldInfo.II = II;
130     D.FieldInfo.DotLoc = DotLoc.getRawEncoding();
131     D.FieldInfo.NameLoc = NameLoc.getRawEncoding();
132     return D;
133   }
134 
135   static Designator getArray(Expr *Index,
136                              SourceLocation LBracketLoc) {
137     Designator D;
138     D.Kind = ArrayDesignator;
139     D.ArrayInfo.Index = Index;
140     D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding();
141     D.ArrayInfo.RBracketLoc = 0;
142     return D;
143   }
144 
145   static Designator getArrayRange(Expr *Start,
146                                   Expr *End,
147                                   SourceLocation LBracketLoc,
148                                   SourceLocation EllipsisLoc) {
149     Designator D;
150     D.Kind = ArrayRangeDesignator;
151     D.ArrayRangeInfo.Start = Start;
152     D.ArrayRangeInfo.End = End;
153     D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding();
154     D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding();
155     D.ArrayRangeInfo.RBracketLoc = 0;
156     return D;
157   }
158 
159   void setRBracketLoc(SourceLocation RBracketLoc) const {
160     assert((isArrayDesignator() || isArrayRangeDesignator()) &&
161            "Invalid accessor");
162     if (isArrayDesignator())
163       ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding();
164     else
165       ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
166   }
167 
168   /// ClearExprs - Null out any expression references, which prevents
169   /// them from being 'delete'd later.
170   void ClearExprs(Sema &Actions) {}
171 
172   /// FreeExprs - Release any unclaimed memory for the expressions in
173   /// this designator.
174   void FreeExprs(Sema &Actions) {}
175 };
176 
177 
178 /// Designation - Represent a full designation, which is a sequence of
179 /// designators.  This class is mostly a helper for InitListDesignations.
180 class Designation {
181   /// Designators - The actual designators for this initializer.
182   SmallVector<Designator, 2> Designators;
183 
184 public:
185   /// AddDesignator - Add a designator to the end of this list.
186   void AddDesignator(Designator D) {
187     Designators.push_back(D);
188   }
189 
190   bool empty() const { return Designators.empty(); }
191 
192   unsigned getNumDesignators() const { return Designators.size(); }
193   const Designator &getDesignator(unsigned Idx) const {
194     assert(Idx < Designators.size());
195     return Designators[Idx];
196   }
197 
198   /// ClearExprs - Null out any expression references, which prevents them from
199   /// being 'delete'd later.
200   void ClearExprs(Sema &Actions) {}
201 
202   /// FreeExprs - Release any unclaimed memory for the expressions in this
203   /// designation.
204   void FreeExprs(Sema &Actions) {}
205 };
206 
207 } // end namespace clang
208 
209 #endif
210