Skip to content

Commit 3c07db5

Browse files
committed
[Clang] Refactor "Designators" into a unified implementation [NFC]
The interfaces for designators (i.e. C99 designated initializers) was done in two slightly different ways. This was rather wasteful as the differences could be combined into one. Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D140584
1 parent 9fdff54 commit 3c07db5

File tree

19 files changed

+410
-484
lines changed

19 files changed

+410
-484
lines changed

clang-tools-extra/clangd/FindTarget.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,7 @@ struct TargetFinder {
285285
Outer.add(CCE->getConstructor(), Flags);
286286
}
287287
void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) {
288-
for (const DesignatedInitExpr::Designator &D :
289-
llvm::reverse(DIE->designators()))
288+
for (const Designator &D : llvm::reverse(DIE->designators()))
290289
if (D.isFieldDesignator()) {
291290
Outer.add(D.getField(), Flags);
292291
// We don't know which designator was intended, we assume the outer.
@@ -801,7 +800,7 @@ llvm::SmallVector<ReferenceLoc> refInStmt(const Stmt *S,
801800
}
802801

803802
void VisitDesignatedInitExpr(const DesignatedInitExpr *DIE) {
804-
for (const DesignatedInitExpr::Designator &D : DIE->designators()) {
803+
for (const Designator &D : DIE->designators()) {
805804
if (!D.isFieldDesignator())
806805
continue;
807806

clang/include/clang/AST/Designator.h

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
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 (i.e. C99
10+
// designated initializers) during parsing and sema.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_AST_DESIGNATOR_H
15+
#define LLVM_CLANG_AST_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 FieldDecl;
24+
class IdentifierInfo;
25+
class Sema;
26+
27+
/// Designator - A designator in a C99 designated initializer.
28+
///
29+
/// This class is a discriminated union which holds the various
30+
/// different sorts of designators possible. A Designation is an array of
31+
/// these. An example of a designator are things like this:
32+
///
33+
/// [8] .field [47] // C99 designation: 3 designators
34+
/// [8 ... 47] field: // GNU extensions: 2 designators
35+
///
36+
/// These occur in initializers, e.g.:
37+
///
38+
/// int a[10] = {2, 4, [8]=9, 10};
39+
///
40+
class Designator {
41+
enum DesignatorKind {
42+
FieldDesignator,
43+
ArrayDesignatorExpr,
44+
ArrayDesignatorInt,
45+
ArrayRangeDesignatorExpr,
46+
ArrayRangeDesignatorInt,
47+
};
48+
49+
DesignatorKind Kind;
50+
51+
/// A field designator, e.g., ".x = 42".
52+
class FieldDesignatorInfo {
53+
/// Refers to the field that is being initialized. The low bit of this
54+
/// field determines whether this is actually a pointer to an
55+
/// IdentifierInfo (if 1) or a FieldDecl (if 0). When initially
56+
/// constructed, a field designator will store an IdentifierInfo*. After
57+
/// semantic analysis has resolved that name, the field designator will
58+
/// instead store a FieldDecl*.
59+
uintptr_t NameOrField;
60+
61+
public:
62+
/// The location of the '.' in the designated initializer.
63+
SourceLocation DotLoc;
64+
65+
/// The location of the field name in the designated initializer.
66+
SourceLocation NameLoc;
67+
68+
FieldDesignatorInfo(const IdentifierInfo *II, SourceLocation DotLoc,
69+
SourceLocation NameLoc)
70+
: NameOrField(reinterpret_cast<uintptr_t>(II) | 0x01), DotLoc(DotLoc),
71+
NameLoc(NameLoc) {}
72+
73+
FieldDecl *getFieldDecl() const {
74+
if (NameOrField & 0x01)
75+
return nullptr;
76+
return reinterpret_cast<FieldDecl *>(NameOrField);
77+
}
78+
const IdentifierInfo *getIdentifierInfo() const {
79+
if (NameOrField & 0x01)
80+
return reinterpret_cast<const IdentifierInfo *>(NameOrField & ~0x1);
81+
return nullptr;
82+
}
83+
84+
void set(FieldDecl *FD) { NameOrField = reinterpret_cast<uintptr_t>(FD); }
85+
};
86+
87+
/// An array designator, e.g., "[42] = 0" and "[42 ... 50] = 1".
88+
template <typename Ty> struct ArrayDesignatorInfo {
89+
/// Location of the first and last index expression within the designated
90+
/// initializer expression's list of subexpressions.
91+
Ty Start;
92+
Ty End;
93+
94+
/// The location of the '[' starting the array designator.
95+
SourceLocation LBracketLoc;
96+
97+
/// The location of the ellipsis separating the start and end indices.
98+
/// Only valid for GNU array-range designators.
99+
SourceLocation EllipsisLoc;
100+
101+
/// The location of the ']' terminating the array designator.
102+
SourceLocation RBracketLoc;
103+
104+
ArrayDesignatorInfo(Ty Start, Ty End, SourceLocation LBracketLoc,
105+
SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
106+
: Start(Start), End(End), LBracketLoc(LBracketLoc),
107+
EllipsisLoc(EllipsisLoc), RBracketLoc(RBracketLoc) {}
108+
109+
Ty getStart() const { return Start; }
110+
Ty getEnd() const { return End; }
111+
};
112+
113+
union {
114+
FieldDesignatorInfo FieldInfo;
115+
ArrayDesignatorInfo<Expr *> ArrayInfoExpr;
116+
ArrayDesignatorInfo<unsigned> ArrayInfoInt;
117+
};
118+
119+
Designator(DesignatorKind Kind) : Kind(Kind) {}
120+
121+
public:
122+
Designator() {}
123+
124+
bool isFieldDesignator() const { return Kind == FieldDesignator; }
125+
bool isArrayDesignator() const {
126+
return Kind == ArrayDesignatorExpr || Kind == ArrayDesignatorInt;
127+
}
128+
bool isArrayRangeDesignator() const {
129+
return Kind == ArrayRangeDesignatorExpr || Kind == ArrayRangeDesignatorInt;
130+
}
131+
132+
/// FieldDesignatorInfo:
133+
static Designator CreateFieldDesignator(const IdentifierInfo *FieldName,
134+
SourceLocation DotLoc,
135+
SourceLocation NameLoc) {
136+
Designator D(FieldDesignator);
137+
new (&D.FieldInfo) FieldDesignatorInfo(FieldName, DotLoc, NameLoc);
138+
return D;
139+
}
140+
141+
const IdentifierInfo *getFieldName() const;
142+
143+
FieldDecl *getField() const {
144+
assert(isFieldDesignator() && "Invalid accessor");
145+
return FieldInfo.getFieldDecl();
146+
}
147+
148+
void setField(FieldDecl *FD) {
149+
assert(isFieldDesignator() && "Invalid accessor");
150+
FieldInfo.set(FD);
151+
}
152+
153+
SourceLocation getDotLoc() const {
154+
assert(isFieldDesignator() && "Invalid accessor");
155+
return FieldInfo.DotLoc;
156+
}
157+
158+
SourceLocation getFieldLoc() const {
159+
assert(isFieldDesignator() && "Invalid accessor");
160+
return FieldInfo.NameLoc;
161+
}
162+
163+
/// ArrayDesignatorInfo:
164+
static Designator
165+
CreateArrayDesignator(Expr *Start, SourceLocation LBracketLoc,
166+
SourceLocation RBracketLoc = SourceLocation()) {
167+
Designator D(ArrayDesignatorExpr);
168+
new (&D.ArrayInfoExpr) ArrayDesignatorInfo<Expr *>(
169+
Start, nullptr, LBracketLoc, SourceLocation(), RBracketLoc);
170+
return D;
171+
}
172+
static Designator
173+
CreateArrayDesignator(unsigned Start, SourceLocation LBracketLoc,
174+
SourceLocation RBracketLoc = SourceLocation()) {
175+
Designator D(ArrayDesignatorInt);
176+
new (&D.ArrayInfoInt) ArrayDesignatorInfo<unsigned>(
177+
Start, 0, LBracketLoc, SourceLocation(), RBracketLoc);
178+
return D;
179+
}
180+
181+
template <typename Ty = Expr *> Ty getArrayIndex() const {
182+
assert(isArrayDesignator() && "Invalid accessor");
183+
return ArrayInfoExpr.getStart();
184+
}
185+
186+
/// ArrayRangeDesignatorInfo:
187+
static Designator
188+
CreateArrayRangeDesignator(Expr *Start, Expr *End, SourceLocation LBracketLoc,
189+
SourceLocation EllipsisLoc,
190+
SourceLocation RBracketLoc = SourceLocation()) {
191+
Designator D(ArrayRangeDesignatorExpr);
192+
new (&D.ArrayInfoExpr) ArrayDesignatorInfo<Expr *>(
193+
Start, End, LBracketLoc, EllipsisLoc, RBracketLoc);
194+
return D;
195+
}
196+
static Designator
197+
CreateArrayRangeDesignator(unsigned Index, SourceLocation LBracketLoc,
198+
SourceLocation EllipsisLoc,
199+
SourceLocation RBracketLoc = SourceLocation()) {
200+
Designator D(ArrayRangeDesignatorInt);
201+
new (&D.ArrayInfoInt) ArrayDesignatorInfo<unsigned>(
202+
Index, 0, LBracketLoc, EllipsisLoc, RBracketLoc);
203+
return D;
204+
}
205+
206+
Expr *getArrayRangeStart() const {
207+
assert(isArrayRangeDesignator() && "Invalid accessor");
208+
return ArrayInfoExpr.getStart();
209+
}
210+
211+
Expr *getArrayRangeEnd() const {
212+
assert(isArrayRangeDesignator() && "Invalid accessor");
213+
return ArrayInfoExpr.getEnd();
214+
}
215+
216+
SourceLocation getLBracketLoc() const {
217+
switch (Kind) {
218+
default:
219+
break;
220+
case ArrayDesignatorExpr:
221+
case ArrayRangeDesignatorExpr:
222+
return ArrayInfoExpr.LBracketLoc;
223+
case ArrayDesignatorInt:
224+
case ArrayRangeDesignatorInt:
225+
return ArrayInfoInt.LBracketLoc;
226+
}
227+
228+
assert(false && "Invalid accessor");
229+
return SourceLocation();
230+
}
231+
232+
SourceLocation getEllipsisLoc() const {
233+
switch (Kind) {
234+
default:
235+
break;
236+
case ArrayRangeDesignatorExpr:
237+
return ArrayInfoExpr.EllipsisLoc;
238+
case ArrayRangeDesignatorInt:
239+
return ArrayInfoInt.EllipsisLoc;
240+
}
241+
242+
assert(false && "Invalid accessor");
243+
return SourceLocation();
244+
}
245+
246+
SourceLocation getRBracketLoc() const {
247+
switch (Kind) {
248+
default:
249+
break;
250+
case ArrayDesignatorExpr:
251+
case ArrayRangeDesignatorExpr:
252+
return ArrayInfoExpr.RBracketLoc;
253+
case ArrayDesignatorInt:
254+
case ArrayRangeDesignatorInt:
255+
return ArrayInfoInt.RBracketLoc;
256+
}
257+
258+
assert(false && "Invalid accessor");
259+
return SourceLocation();
260+
}
261+
262+
void setRBracketLoc(SourceLocation RBracketLoc) {
263+
switch (Kind) {
264+
default:
265+
assert(false && "Invalid accessor");
266+
break;
267+
case ArrayDesignatorExpr:
268+
case ArrayRangeDesignatorExpr:
269+
ArrayInfoExpr.RBracketLoc = RBracketLoc;
270+
break;
271+
case ArrayDesignatorInt:
272+
case ArrayRangeDesignatorInt:
273+
ArrayInfoInt.RBracketLoc = RBracketLoc;
274+
break;
275+
}
276+
}
277+
278+
unsigned getFirstExprIndex() const {
279+
if (Kind == ArrayDesignatorInt || Kind == ArrayRangeDesignatorInt)
280+
return ArrayInfoInt.getStart();
281+
282+
assert(false && "Invalid accessor");
283+
return 0;
284+
}
285+
286+
/// Source location accessors.
287+
SourceLocation getBeginLoc() const LLVM_READONLY {
288+
if (isFieldDesignator())
289+
return getDotLoc().isInvalid() ? getFieldLoc() : getDotLoc();
290+
return getLBracketLoc();
291+
}
292+
SourceLocation getEndLoc() const LLVM_READONLY {
293+
return isFieldDesignator() ? getFieldLoc() : getRBracketLoc();
294+
}
295+
SourceRange getSourceRange() const LLVM_READONLY {
296+
return SourceRange(getBeginLoc(), getEndLoc());
297+
}
298+
};
299+
300+
/// Designation - Represent a full designation, which is a sequence of
301+
/// designators. This class is mostly a helper for InitListDesignations.
302+
class Designation {
303+
/// Designators - The actual designators for this initializer.
304+
SmallVector<Designator, 2> Designators;
305+
306+
public:
307+
/// AddDesignator - Add a designator to the end of this list.
308+
void AddDesignator(Designator D) { Designators.push_back(D); }
309+
310+
bool empty() const { return Designators.empty(); }
311+
312+
unsigned getNumDesignators() const { return Designators.size(); }
313+
314+
const Designator &getDesignator(unsigned Idx) const {
315+
assert(Idx < getNumDesignators());
316+
return Designators[Idx];
317+
}
318+
Designator &getDesignator(unsigned Idx) {
319+
assert(Idx < getNumDesignators());
320+
return Designators[Idx];
321+
}
322+
};
323+
324+
} // end namespace clang
325+
326+
#endif

0 commit comments

Comments
 (0)