Skip to content

Commit 17fe80c

Browse files
committed
Merge remote-tracking branch 'origin/main' into vplan-simplify-branch-on-const-entry
2 parents 1e16872 + a53a5ed commit 17fe80c

File tree

103 files changed

+15601
-3151
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+15601
-3151
lines changed

clang-tools-extra/clang-reorder-fields/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
44
)
55

66
add_clang_library(clangReorderFields STATIC
7+
Designator.cpp
78
ReorderFieldsAction.cpp
89

910
DEPENDS
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
//===-- tools/extra/clang-reorder-fields/utils/Designator.cpp ---*- 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+
/// \file
10+
/// This file contains the definition of the Designator and Designators utility
11+
/// classes.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "Designator.h"
16+
#include "clang/AST/ASTContext.h"
17+
#include "clang/AST/Expr.h"
18+
#include "llvm/Support/raw_ostream.h"
19+
20+
namespace clang {
21+
namespace reorder_fields {
22+
23+
void Designator::advanceToNextField() {
24+
assert(!isFinished() && "Iterator is already finished");
25+
switch (Tag) {
26+
case STRUCT:
27+
if (StructIt.Record->isUnion()) {
28+
// Union always finishes on first increment.
29+
StructIt.Field = StructIt.Record->field_end();
30+
Type = QualType();
31+
break;
32+
}
33+
++StructIt.Field;
34+
if (StructIt.Field != StructIt.Record->field_end()) {
35+
Type = StructIt.Field->getType();
36+
} else {
37+
Type = QualType();
38+
}
39+
break;
40+
case ARRAY:
41+
++ArrayIt.Index;
42+
break;
43+
case ARRAY_RANGE:
44+
ArrayIt.Index = ArrayRangeIt.End + 1;
45+
ArrayIt.Size = ArrayRangeIt.Size;
46+
Tag = ARRAY;
47+
break;
48+
}
49+
}
50+
51+
bool Designator::isFinished() {
52+
switch (Tag) {
53+
case STRUCT:
54+
return StructIt.Field == StructIt.Record->field_end();
55+
case ARRAY:
56+
return ArrayIt.Index == ArrayIt.Size;
57+
case ARRAY_RANGE:
58+
return ArrayRangeIt.End == ArrayRangeIt.Size;
59+
}
60+
return false;
61+
}
62+
63+
Designators::Designators(const Expr *Init, const InitListExpr *ILE,
64+
const ASTContext *Context)
65+
: Context(Context) {
66+
if (ILE->getType()->isArrayType()) {
67+
const ConstantArrayType *CAT =
68+
Context->getAsConstantArrayType(ILE->getType());
69+
// Only constant size arrays are supported.
70+
if (!CAT) {
71+
DesignatorList.clear();
72+
return;
73+
}
74+
DesignatorList.push_back(
75+
{CAT->getElementType(), 0, CAT->getSize().getZExtValue()});
76+
} else {
77+
const RecordDecl *DesignatorRD = ILE->getType()->getAsRecordDecl();
78+
DesignatorList.push_back({DesignatorRD->field_begin()->getType(),
79+
DesignatorRD->field_begin(), DesignatorRD});
80+
}
81+
82+
// If the designator list is empty at this point, then there must be excess
83+
// elements in the initializer list. They are not currently supported.
84+
if (DesignatorList.empty())
85+
return;
86+
87+
if (!enterImplicitInitLists(Init))
88+
DesignatorList.clear();
89+
}
90+
91+
Designators::Designators(const DesignatedInitExpr *DIE, const InitListExpr *ILE,
92+
const ASTContext *Context)
93+
: Context(Context) {
94+
for (const auto &D : DIE->designators()) {
95+
if (D.isFieldDesignator()) {
96+
RecordDecl *DesignatorRecord = D.getFieldDecl()->getParent();
97+
for (auto FieldIt = DesignatorRecord->field_begin();
98+
FieldIt != DesignatorRecord->field_end(); ++FieldIt) {
99+
if (*FieldIt == D.getFieldDecl()) {
100+
DesignatorList.push_back(
101+
{FieldIt->getType(), FieldIt, DesignatorRecord});
102+
break;
103+
}
104+
}
105+
} else {
106+
const QualType CurrentType = DesignatorList.empty()
107+
? ILE->getType()
108+
: DesignatorList.back().getType();
109+
const ConstantArrayType *CAT =
110+
Context->getAsConstantArrayType(CurrentType);
111+
if (!CAT) {
112+
// Non-constant-sized arrays are not supported.
113+
DesignatorList.clear();
114+
return;
115+
}
116+
if (D.isArrayDesignator()) {
117+
DesignatorList.push_back({CAT->getElementType(),
118+
DIE->getArrayIndex(D)
119+
->EvaluateKnownConstInt(*Context)
120+
.getZExtValue(),
121+
CAT->getSize().getZExtValue()});
122+
} else if (D.isArrayRangeDesignator()) {
123+
DesignatorList.push_back({CAT->getElementType(),
124+
DIE->getArrayRangeStart(D)
125+
->EvaluateKnownConstInt(*Context)
126+
.getZExtValue(),
127+
DIE->getArrayRangeEnd(D)
128+
->EvaluateKnownConstInt(*Context)
129+
.getZExtValue(),
130+
CAT->getSize().getZExtValue()});
131+
} else {
132+
llvm_unreachable("Unexpected designator kind");
133+
}
134+
}
135+
}
136+
}
137+
138+
bool Designators::advanceToNextField(const Expr *Init) {
139+
// Remove all designators that refer to the last field of a struct or final
140+
// element of the array.
141+
while (!DesignatorList.empty()) {
142+
auto &CurrentDesignator = DesignatorList.back();
143+
CurrentDesignator.advanceToNextField();
144+
if (CurrentDesignator.isFinished()) {
145+
DesignatorList.pop_back();
146+
continue;
147+
}
148+
break;
149+
}
150+
151+
// If the designator list is empty at this point, then there must be excess
152+
// elements in the initializer list. They are not currently supported.
153+
if (DesignatorList.empty())
154+
return false;
155+
156+
if (!enterImplicitInitLists(Init)) {
157+
DesignatorList.clear();
158+
return false;
159+
}
160+
161+
return true;
162+
}
163+
164+
bool Designators::enterImplicitInitLists(const Expr *Init) {
165+
// Check for missing braces by comparing the type of the last designator and
166+
// type of Init.
167+
while (true) {
168+
const QualType T = DesignatorList.back().getType();
169+
// If the types match, there are no missing braces.
170+
if (Init->getType() == T)
171+
break;
172+
173+
// If the current type is a struct, then get its first field.
174+
if (T->isRecordType()) {
175+
DesignatorList.push_back({T->getAsRecordDecl()->field_begin()->getType(),
176+
T->getAsRecordDecl()->field_begin(),
177+
T->getAsRecordDecl()});
178+
continue;
179+
}
180+
// If the current type is an array, then get its first element.
181+
if (T->isArrayType()) {
182+
DesignatorList.push_back(
183+
{Context->getAsArrayType(T)->getElementType(), 0,
184+
Context->getAsConstantArrayType(T)->getSize().getZExtValue()});
185+
continue;
186+
}
187+
188+
// The initializer doesn't match the expected type. The initializer list is
189+
// invalid.
190+
return false;
191+
}
192+
193+
return true;
194+
}
195+
196+
std::string Designators::toString() const {
197+
if (DesignatorList.empty())
198+
return "";
199+
std::string Designator;
200+
llvm::raw_string_ostream OS(Designator);
201+
for (auto &I : DesignatorList) {
202+
switch (I.getTag()) {
203+
case Designator::STRUCT:
204+
OS << '.' << I.getStructIter()->getName();
205+
break;
206+
case Designator::ARRAY:
207+
OS << '[' << I.getArrayIndex() << ']';
208+
break;
209+
case Designator::ARRAY_RANGE:
210+
OS << '[' << I.getArrayRangeStart() << "..." << I.getArrayRangeEnd()
211+
<< ']';
212+
}
213+
}
214+
OS << " = ";
215+
return Designator;
216+
}
217+
218+
} // namespace reorder_fields
219+
} // namespace clang
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
//===-- tools/extra/clang-reorder-fields/utils/Designator.h -----*- 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+
/// \file
10+
/// This file contains the declarations of the Designator and Designators
11+
/// utility classes.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_UTILS_DESIGNATOR_H
16+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_UTILS_DESIGNATOR_H
17+
18+
#include "clang/AST/Decl.h"
19+
#include "clang/AST/Expr.h"
20+
#include "clang/AST/Type.h"
21+
22+
namespace clang {
23+
namespace reorder_fields {
24+
25+
/// Represents a part of a designation in a C99/C++20 designated initializer. It
26+
/// is a tagged union of different kinds of designators: struct, array and array
27+
/// range. Holds enough information to be able to advance to the next field and
28+
/// to know when all fields have been iterated through.
29+
class Designator {
30+
public:
31+
enum Kind { STRUCT, ARRAY, ARRAY_RANGE };
32+
33+
Designator(const QualType Type, RecordDecl::field_iterator Field,
34+
const RecordDecl *RD)
35+
: Tag(STRUCT), Type(Type), StructIt({Field, RD}) {}
36+
37+
Designator(const QualType Type, uint64_t Idx, uint64_t Size)
38+
: Tag(ARRAY), Type(Type), ArrayIt({Idx, Size}) {}
39+
40+
Designator(const QualType Type, uint64_t Start, uint64_t End, uint64_t Size)
41+
: Tag(ARRAY_RANGE), Type(Type), ArrayRangeIt({Start, End, Size}) {}
42+
43+
/// Moves the iterator to the next element.
44+
void advanceToNextField();
45+
46+
/// Checks if the iterator has iterated through all elements.
47+
bool isFinished();
48+
49+
Kind getTag() const { return Tag; }
50+
QualType getType() const { return Type; }
51+
52+
const RecordDecl::field_iterator getStructIter() const {
53+
assert(Tag == STRUCT && "Must be a field designator");
54+
return StructIt.Field;
55+
}
56+
57+
const RecordDecl *getStructDecl() const {
58+
assert(Tag == STRUCT && "Must be a field designator");
59+
return StructIt.Record;
60+
}
61+
62+
uint64_t getArrayIndex() const {
63+
assert(Tag == ARRAY && "Must be an array designator");
64+
return ArrayIt.Index;
65+
}
66+
67+
uint64_t getArrayRangeStart() const {
68+
assert(Tag == ARRAY_RANGE && "Must be an array range designator");
69+
return ArrayRangeIt.Start;
70+
}
71+
72+
uint64_t getArrayRangeEnd() const {
73+
assert(Tag == ARRAY_RANGE && "Must be an array range designator");
74+
return ArrayRangeIt.End;
75+
}
76+
77+
uint64_t getArraySize() const {
78+
assert((Tag == ARRAY || Tag == ARRAY_RANGE) &&
79+
"Must be an array or range designator");
80+
if (Tag == ARRAY)
81+
return ArrayIt.Size;
82+
return ArrayRangeIt.Size;
83+
}
84+
85+
private:
86+
/// Type of the designator.
87+
Kind Tag;
88+
89+
/// Type of the designated entry. For arrays this is the type of the element.
90+
QualType Type;
91+
92+
/// Field designator has the iterator to the field and the record the field
93+
/// is declared in.
94+
struct StructIter {
95+
RecordDecl::field_iterator Field;
96+
const RecordDecl *Record;
97+
};
98+
99+
/// Array designator has an index and size of the array.
100+
struct ArrayIter {
101+
uint64_t Index;
102+
uint64_t Size;
103+
};
104+
105+
/// Array range designator has a start and end index and size of the array.
106+
struct ArrayRangeIter {
107+
uint64_t Start;
108+
uint64_t End;
109+
uint64_t Size;
110+
};
111+
112+
union {
113+
StructIter StructIt;
114+
ArrayIter ArrayIt;
115+
ArrayRangeIter ArrayRangeIt;
116+
};
117+
};
118+
119+
/// List of designators.
120+
class Designators {
121+
public:
122+
/// Initialize to the first member of the struct/array. Enters implicit
123+
/// initializer lists until a type that matches Init is found.
124+
Designators(const Expr *Init, const InitListExpr *ILE,
125+
const ASTContext *Context);
126+
127+
/// Initialize to the designators of the given expression.
128+
Designators(const DesignatedInitExpr *DIE, const InitListExpr *ILE,
129+
const ASTContext *Context);
130+
131+
/// Return whether this designator list is valid.
132+
bool isValid() const { return !DesignatorList.empty(); }
133+
134+
/// Moves the designators to the next initializer in the struct/array. If the
135+
/// type of next initializer doesn't match the expected type then there are
136+
/// omitted braces and we add new designators to reflect that.
137+
bool advanceToNextField(const Expr *Init);
138+
139+
/// Gets a string representation from a list of designators. This string will
140+
/// be inserted before an initializer expression to make it designated.
141+
std::string toString() const;
142+
143+
size_t size() const { return DesignatorList.size(); }
144+
145+
SmallVector<Designator>::const_iterator begin() const {
146+
return DesignatorList.begin();
147+
}
148+
SmallVector<Designator>::const_iterator end() const {
149+
return DesignatorList.end();
150+
}
151+
152+
private:
153+
/// Enters any implicit initializer lists until a type that matches the given
154+
/// expression is found.
155+
bool enterImplicitInitLists(const Expr *Init);
156+
157+
const ASTContext *Context;
158+
SmallVector<Designator, 1> DesignatorList;
159+
};
160+
161+
} // namespace reorder_fields
162+
} // namespace clang
163+
164+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_UTILS_DESIGNATOR_H

0 commit comments

Comments
 (0)