15#include "clang/AST/DeclCXX.h"
16#include "clang/AST/Type.h"
17#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/ScopeExit.h"
27 return Name.size() >= 2 && Name[0] ==
'_' &&
28 (isUppercase(Name[1]) || Name[1] ==
'_');
36class AggregateDesignatorNames {
38 AggregateDesignatorNames(QualType T) {
40 T =
T.getCanonicalType();
41 if (
T->isArrayType()) {
46 if (
const RecordDecl *RD =
T->getAsRecordDecl()) {
48 FieldsIt = RD->field_begin();
49 FieldsEnd = RD->field_end();
50 if (
const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(RD)) {
51 BasesIt = CRD->bases_begin();
52 BasesEnd = CRD->bases_end();
53 Valid = CRD->isAggregate();
55 OneField = Valid && BasesIt == BasesEnd && FieldsIt != FieldsEnd &&
56 std::next(FieldsIt) == FieldsEnd;
61 operator bool()
const {
return Valid; }
66 else if (BasesIt != BasesEnd)
68 else if (FieldsIt != FieldsEnd)
73 bool append(std::string &Out,
bool ForSubobject) {
76 Out.append(std::to_string(Index));
80 if (BasesIt != BasesEnd)
82 if (FieldsIt != FieldsEnd) {
83 llvm::StringRef FieldName;
84 if (
const IdentifierInfo *II = FieldsIt->getIdentifier())
85 FieldName = II->getName();
89 (FieldsIt->isAnonymousStructOrUnion() ||
96 Out.append(FieldName.begin(), FieldName.end());
106 bool IsArray =
false;
107 bool OneField =
false;
109 CXXRecordDecl::base_class_const_iterator BasesIt;
110 CXXRecordDecl::base_class_const_iterator BasesEnd;
111 RecordDecl::field_iterator FieldsIt;
112 RecordDecl::field_iterator FieldsEnd;
130void collectDesignators(
const InitListExpr *Sem,
131 llvm::DenseMap<SourceLocation, std::string> &Out,
132 const llvm::DenseSet<SourceLocation> &NestedBraces,
133 std::string &Prefix) {
134 if (!Sem || Sem->isTransparent())
136 assert(Sem->isSemanticForm());
140 AggregateDesignatorNames Fields(Sem->getType());
143 for (
const Expr *Init : Sem->inits()) {
144 auto Next = llvm::make_scope_exit([&, Size(Prefix.size())] {
150 if (!Init || llvm::isa<ImplicitValueInitExpr>(Init))
153 const auto *BraceElidedSubobject = llvm::dyn_cast<InitListExpr>(Init);
154 if (BraceElidedSubobject &&
155 NestedBraces.contains(BraceElidedSubobject->getLBraceLoc()))
156 BraceElidedSubobject =
nullptr;
158 if (!Fields.append(Prefix, BraceElidedSubobject !=
nullptr))
160 if (BraceElidedSubobject) {
166 collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix);
169 Out.try_emplace(Init->getBeginLoc(), Prefix);
175llvm::DenseMap<SourceLocation, std::string>
177 assert(Syn->isSyntacticForm());
182 llvm::DenseSet<SourceLocation> NestedBraces;
183 for (
const Expr *Init : Syn->inits())
184 if (
auto *Nested = llvm::dyn_cast<InitListExpr>(Init))
185 NestedBraces.insert(Nested->getLBraceLoc());
189 llvm::DenseMap<SourceLocation, std::string> Designators;
190 std::string EmptyPrefix;
191 collectDesignators(Syn->isSemanticForm() ? Syn : Syn->getSemanticForm(),
192 Designators, NestedBraces, EmptyPrefix);
This file provides utilities for designated initializers.
bool isReservedName(llvm::StringRef Name)
Returns true if Name is reserved, like _Foo or __Vector_base.
llvm::DenseMap< SourceLocation, std::string > getUnwrittenDesignators(const InitListExpr *Syn)