165 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the declarations of the Designator and Designators11/// utility classes.12///13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_UTILS_DESIGNATOR_H16#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_UTILS_DESIGNATOR_H17 18#include "clang/AST/Decl.h"19#include "clang/AST/Expr.h"20#include "clang/AST/Type.h"21 22namespace clang {23namespace reorder_fields {24 25/// Represents a part of a designation in a C99/C++20 designated initializer. It26/// is a tagged union of different kinds of designators: struct, array and array27/// range. Holds enough information to be able to advance to the next field and28/// to know when all fields have been iterated through.29class Designator {30public: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 85private: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 field93 /// 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.120class Designators {121public:122 /// Initialize to the first member of the struct/array. Enters implicit123 /// 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 the135 /// type of next initializer doesn't match the expected type then there are136 /// 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 will140 /// 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 152private:153 /// Enters any implicit initializer lists until a type that matches the given154 /// expression is found.155 bool enterImplicitInitLists(const Expr *Init);156 157 const ASTContext *Context;158 SmallVector<Designator, 1> DesignatorList;159};160 161} // namespace reorder_fields162} // namespace clang163 164#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REORDER_FIELDS_UTILS_DESIGNATOR_H165