1212795Sdim//===--- Designator.h - Initialization Designator ---------------*- C++ -*-===//
2212795Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6212795Sdim//
7212795Sdim//===----------------------------------------------------------------------===//
8212795Sdim//
9212795Sdim// This file defines interfaces used to represent designators (a la
10212795Sdim// C99 designated initializers) during parsing.
11212795Sdim//
12212795Sdim//===----------------------------------------------------------------------===//
13212795Sdim
14212795Sdim#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H
15212795Sdim#define LLVM_CLANG_SEMA_DESIGNATOR_H
16212795Sdim
17212795Sdim#include "clang/Basic/SourceLocation.h"
18212795Sdim#include "llvm/ADT/SmallVector.h"
19212795Sdim
20212795Sdimnamespace clang {
21212795Sdim
22212795Sdimclass Expr;
23212795Sdimclass IdentifierInfo;
24212795Sdimclass Sema;
25212795Sdim
26212795Sdim/// Designator - A designator in a C99 designated initializer.
27212795Sdim///
28212795Sdim/// This class is a discriminated union which holds the various
29212795Sdim/// different sorts of designators possible.  A Designation is an array of
30212795Sdim/// these.  An example of a designator are things like this:
31212795Sdim///     [8] .field [47]        // C99 designation: 3 designators
32212795Sdim///     [8 ... 47]  field:     // GNU extensions: 2 designators
33212795Sdim/// These occur in initializers, e.g.:
34212795Sdim///  int a[10] = {2, 4, [8]=9, 10};
35212795Sdim///
36212795Sdimclass Designator {
37212795Sdimpublic:
38212795Sdim  enum DesignatorKind {
39212795Sdim    FieldDesignator, ArrayDesignator, ArrayRangeDesignator
40212795Sdim  };
41212795Sdimprivate:
42212795Sdim  DesignatorKind Kind;
43212795Sdim
44212795Sdim  struct FieldDesignatorInfo {
45212795Sdim    const IdentifierInfo *II;
46212795Sdim    unsigned DotLoc;
47212795Sdim    unsigned NameLoc;
48212795Sdim  };
49212795Sdim  struct ArrayDesignatorInfo {
50212795Sdim    Expr *Index;
51212795Sdim    unsigned LBracketLoc;
52212795Sdim    mutable unsigned  RBracketLoc;
53212795Sdim  };
54212795Sdim  struct ArrayRangeDesignatorInfo {
55212795Sdim    Expr *Start, *End;
56212795Sdim    unsigned LBracketLoc, EllipsisLoc;
57212795Sdim    mutable unsigned RBracketLoc;
58212795Sdim  };
59212795Sdim
60212795Sdim  union {
61212795Sdim    FieldDesignatorInfo FieldInfo;
62212795Sdim    ArrayDesignatorInfo ArrayInfo;
63212795Sdim    ArrayRangeDesignatorInfo ArrayRangeInfo;
64212795Sdim  };
65212795Sdim
66212795Sdimpublic:
67212795Sdim
68212795Sdim  DesignatorKind getKind() const { return Kind; }
69212795Sdim  bool isFieldDesignator() const { return Kind == FieldDesignator; }
70212795Sdim  bool isArrayDesignator() const { return Kind == ArrayDesignator; }
71212795Sdim  bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
72212795Sdim
73212795Sdim  const IdentifierInfo *getField() const {
74212795Sdim    assert(isFieldDesignator() && "Invalid accessor");
75212795Sdim    return FieldInfo.II;
76212795Sdim  }
77212795Sdim
78212795Sdim  SourceLocation getDotLoc() const {
79212795Sdim    assert(isFieldDesignator() && "Invalid accessor");
80212795Sdim    return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc);
81212795Sdim  }
82212795Sdim
83212795Sdim  SourceLocation getFieldLoc() const {
84212795Sdim    assert(isFieldDesignator() && "Invalid accessor");
85212795Sdim    return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc);
86212795Sdim  }
87212795Sdim
88212795Sdim  Expr *getArrayIndex() const {
89212795Sdim    assert(isArrayDesignator() && "Invalid accessor");
90212795Sdim    return ArrayInfo.Index;
91212795Sdim  }
92212795Sdim
93212795Sdim  Expr *getArrayRangeStart() const {
94212795Sdim    assert(isArrayRangeDesignator() && "Invalid accessor");
95212795Sdim    return ArrayRangeInfo.Start;
96212795Sdim  }
97212795Sdim  Expr *getArrayRangeEnd() const {
98212795Sdim    assert(isArrayRangeDesignator() && "Invalid accessor");
99212795Sdim    return ArrayRangeInfo.End;
100212795Sdim  }
101212795Sdim
102212795Sdim  SourceLocation getLBracketLoc() const {
103212795Sdim    assert((isArrayDesignator() || isArrayRangeDesignator()) &&
104212795Sdim           "Invalid accessor");
105212795Sdim    if (isArrayDesignator())
106212795Sdim      return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc);
107212795Sdim    else
108212795Sdim      return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc);
109212795Sdim  }
110212795Sdim
111212795Sdim  SourceLocation getRBracketLoc() const {
112212795Sdim    assert((isArrayDesignator() || isArrayRangeDesignator()) &&
113212795Sdim           "Invalid accessor");
114212795Sdim    if (isArrayDesignator())
115212795Sdim      return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc);
116212795Sdim    else
117212795Sdim      return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc);
118212795Sdim  }
119212795Sdim
120212795Sdim  SourceLocation getEllipsisLoc() const {
121212795Sdim    assert(isArrayRangeDesignator() && "Invalid accessor");
122212795Sdim    return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc);
123212795Sdim  }
124212795Sdim
125212795Sdim  static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc,
126212795Sdim                             SourceLocation NameLoc) {
127212795Sdim    Designator D;
128212795Sdim    D.Kind = FieldDesignator;
129212795Sdim    D.FieldInfo.II = II;
130212795Sdim    D.FieldInfo.DotLoc = DotLoc.getRawEncoding();
131212795Sdim    D.FieldInfo.NameLoc = NameLoc.getRawEncoding();
132212795Sdim    return D;
133212795Sdim  }
134212795Sdim
135212795Sdim  static Designator getArray(Expr *Index,
136212795Sdim                             SourceLocation LBracketLoc) {
137212795Sdim    Designator D;
138212795Sdim    D.Kind = ArrayDesignator;
139212795Sdim    D.ArrayInfo.Index = Index;
140212795Sdim    D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding();
141212795Sdim    D.ArrayInfo.RBracketLoc = 0;
142212795Sdim    return D;
143212795Sdim  }
144212795Sdim
145212795Sdim  static Designator getArrayRange(Expr *Start,
146212795Sdim                                  Expr *End,
147212795Sdim                                  SourceLocation LBracketLoc,
148212795Sdim                                  SourceLocation EllipsisLoc) {
149212795Sdim    Designator D;
150212795Sdim    D.Kind = ArrayRangeDesignator;
151212795Sdim    D.ArrayRangeInfo.Start = Start;
152212795Sdim    D.ArrayRangeInfo.End = End;
153212795Sdim    D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding();
154212795Sdim    D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding();
155212795Sdim    D.ArrayRangeInfo.RBracketLoc = 0;
156212795Sdim    return D;
157212795Sdim  }
158212795Sdim
159212795Sdim  void setRBracketLoc(SourceLocation RBracketLoc) const {
160212795Sdim    assert((isArrayDesignator() || isArrayRangeDesignator()) &&
161212795Sdim           "Invalid accessor");
162212795Sdim    if (isArrayDesignator())
163212795Sdim      ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding();
164212795Sdim    else
165212795Sdim      ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
166212795Sdim  }
167212795Sdim
168212795Sdim  /// ClearExprs - Null out any expression references, which prevents
169212795Sdim  /// them from being 'delete'd later.
170212795Sdim  void ClearExprs(Sema &Actions) {}
171212795Sdim
172212795Sdim  /// FreeExprs - Release any unclaimed memory for the expressions in
173212795Sdim  /// this designator.
174212795Sdim  void FreeExprs(Sema &Actions) {}
175212795Sdim};
176212795Sdim
177212795Sdim
178212795Sdim/// Designation - Represent a full designation, which is a sequence of
179212795Sdim/// designators.  This class is mostly a helper for InitListDesignations.
180212795Sdimclass Designation {
181212795Sdim  /// Designators - The actual designators for this initializer.
182226633Sdim  SmallVector<Designator, 2> Designators;
183212795Sdim
184212795Sdimpublic:
185212795Sdim  /// AddDesignator - Add a designator to the end of this list.
186212795Sdim  void AddDesignator(Designator D) {
187212795Sdim    Designators.push_back(D);
188212795Sdim  }
189212795Sdim
190212795Sdim  bool empty() const { return Designators.empty(); }
191212795Sdim
192212795Sdim  unsigned getNumDesignators() const { return Designators.size(); }
193212795Sdim  const Designator &getDesignator(unsigned Idx) const {
194212795Sdim    assert(Idx < Designators.size());
195212795Sdim    return Designators[Idx];
196212795Sdim  }
197212795Sdim
198212795Sdim  /// ClearExprs - Null out any expression references, which prevents them from
199212795Sdim  /// being 'delete'd later.
200212795Sdim  void ClearExprs(Sema &Actions) {}
201212795Sdim
202212795Sdim  /// FreeExprs - Release any unclaimed memory for the expressions in this
203212795Sdim  /// designation.
204212795Sdim  void FreeExprs(Sema &Actions) {}
205212795Sdim};
206212795Sdim
207212795Sdim} // end namespace clang
208212795Sdim
209212795Sdim#endif
210