brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · d36a080 Raw
220 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the definition of the Designator and Designators utility11/// 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 20namespace clang {21namespace reorder_fields {22 23void 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 51bool 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 63Designators::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 excess83  // 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 91Designators::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 138bool Designators::advanceToNextField(const Expr *Init) {139  // Remove all designators that refer to the last field of a struct or final140  // 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 excess152  // 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 164bool Designators::enterImplicitInitLists(const Expr *Init) {165  // Check for missing braces by comparing the type of the last designator and166  // 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 is189    // invalid.190    return false;191  }192 193  return true;194}195 196std::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_fields219} // namespace clang220