================
@@ -0,0 +1,213 @@
+//===-- tools/extra/clang-reorder-fields/utils/Designator.cpp ---*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the definition of the DesignatorIter and Designators
+/// utility classes.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Designator.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+namespace reorder_fields {
+
+DesignatorIter &DesignatorIter::operator++() {
+  assert(!isFinished() && "Iterator is already finished");
+  switch (Tag) {
+  case STRUCT:
+    if (StructIt.Record->isUnion()) {
+      // Union always finishes on first increment.
+      StructIt.Field = StructIt.Record->field_end();
+      Type = QualType();
+      break;
+    }
+    ++StructIt.Field;
+    if (StructIt.Field != StructIt.Record->field_end()) {
+      Type = StructIt.Field->getType();
+    } else {
+      Type = QualType();
+    }
+    break;
+  case ARRAY:
+    ++ArrayIt.Index;
+    break;
+  case ARRAY_RANGE:
+    ArrayIt.Index = ArrayRangeIt.End + 1;
+    ArrayIt.Size = ArrayRangeIt.Size;
+    Tag = ARRAY;
+    break;
+  }
+  return *this;
+}
+
+bool DesignatorIter::isFinished() {
+  switch (Tag) {
+  case STRUCT:
+    return StructIt.Field == StructIt.Record->field_end();
+  case ARRAY:
+    return ArrayIt.Index == ArrayIt.Size;
+  case ARRAY_RANGE:
+    return ArrayRangeIt.End == ArrayRangeIt.Size;
+  }
+  return false;
+}
+
+Designators::Designators(const Expr *Init, const InitListExpr *ILE,
+                         const ASTContext *Context)
+    : ILE(ILE), Context(Context) {
+  if (ILE->getType()->isArrayType()) {
+    const ConstantArrayType *CAT =
+        Context->getAsConstantArrayType(ILE->getType());
+    // Only constant size arrays are supported.
+    if (!CAT) {
+      DesignatorList.clear();
+      return;
+    }
+    DesignatorList.push_back(
+        {CAT->getElementType(), 0, CAT->getSize().getZExtValue()});
+  } else {
+    const RecordDecl *DesignatorRD = ILE->getType()->getAsRecordDecl();
+    DesignatorList.push_back({DesignatorRD->field_begin()->getType(),
+                              DesignatorRD->field_begin(), DesignatorRD});
+  }
+
+  // If the designator list is empty at this point, then there must be excess
+  // elements in the initializer list. They are not currently supported.
+  if (DesignatorList.empty())
+    return;
+
+  if (!enterImplicitInitLists(Init))
+    DesignatorList.clear();
+}
+
+Designators::Designators(const DesignatedInitExpr *DIE, const InitListExpr 
*ILE,
+                         const ASTContext *Context)
+    : ILE(ILE), Context(Context) {
+  for (const auto &D : DIE->designators()) {
+    if (D.isFieldDesignator()) {
+      RecordDecl *DesignatorRecord = D.getFieldDecl()->getParent();
+      for (auto FieldIt = DesignatorRecord->field_begin();
+           FieldIt != DesignatorRecord->field_end(); ++FieldIt) {
+        if (*FieldIt == D.getFieldDecl()) {
+          DesignatorList.push_back(
+              {FieldIt->getType(), FieldIt, DesignatorRecord});
+          break;
+        }
+      }
+    } else {
+      const QualType CurrentType = DesignatorList.empty()
+                                       ? ILE->getType()
+                                       : DesignatorList.back().getType();
+      const ConstantArrayType *CAT =
+          Context->getAsConstantArrayType(CurrentType);
+      if (!CAT) {
+        // Non-constant-sized arrays are not supported.
+        DesignatorList.clear();
+        return;
+      }
+      if (D.isArrayDesignator()) {
+        DesignatorList.push_back({CAT->getElementType(),
+                                  DIE->getArrayIndex(D)
+                                      ->EvaluateKnownConstInt(*Context)
+                                      .getZExtValue(),
+                                  CAT->getSize().getZExtValue()});
+      } else if (D.isArrayRangeDesignator()) {
+        DesignatorList.push_back({CAT->getElementType(),
+                                  DIE->getArrayRangeStart(D)
+                                      ->EvaluateKnownConstInt(*Context)
+                                      .getZExtValue(),
+                                  DIE->getArrayRangeEnd(D)
+                                      ->EvaluateKnownConstInt(*Context)
+                                      .getZExtValue(),
+                                  CAT->getSize().getZExtValue()});
+      } else {
+        llvm_unreachable("Unexpected designator kind");
+      }
+    }
+  }
+}
+
+bool Designators::advanceToNextField(const Expr *Init) {
+  // Remove all designators that refer to the last field of a struct or final
+  // element of the array.
+  while (!DesignatorList.empty()) {
+    auto &CurrentDesignator = DesignatorList.back();
+    ++CurrentDesignator;
+    if (CurrentDesignator.isFinished()) {
+      DesignatorList.pop_back();
+      continue;
+    }
+    break;
+  }
+
+  // If the designator list is empty at this point, then there must be excess
+  // elements in the initializer list. They are not currently supported.
+  if (DesignatorList.empty())
+    return false;
+
+  return enterImplicitInitLists(Init);
+}
+
+bool Designators::enterImplicitInitLists(const Expr *Init) {
+  // Check for missing braces by comparing the type of the last designator and
+  // type of Init.
+  while (true) {
+    const QualType T = DesignatorList.back().getType();
+    // If the types match, there are no missing braces.
+    if (Init->getType() == T)
+      break;
+
+    // If the current type is a struct, then get its first field.
+    if (T->isRecordType()) {
+      DesignatorList.push_back({T->getAsRecordDecl()->field_begin()->getType(),
+                                T->getAsRecordDecl()->field_begin(),
+                                T->getAsRecordDecl()});
+      continue;
+    }
+    // If the current type is an array, then get its first element.
+    if (T->isArrayType()) {
+      DesignatorList.push_back(
+          {Context->getAsArrayType(T)->getElementType(), 0,
+           Context->getAsConstantArrayType(T)->getSize().getZExtValue()});
+      continue;
+    }
+
+    // The initializer doesn't match the expected type. The initializer list is
+    // invalid.
+    return false;
+  }
+
+  return true;
+}
+
+std::string Designators::toString() const {
+  if (DesignatorList.empty())
+    return "";
+  std::string Designator = "";
+  for (auto &I : DesignatorList) {
+    switch (I.getTag()) {
+    case DesignatorIter::STRUCT:
+      Designator += "." + I.getStructIter()->getName().str();
----------------
alexander-shaposhnikov wrote:

https://llvm.org/doxygen/classllvm_1_1Twine.html

https://github.com/llvm/llvm-project/pull/142150
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to