CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
220 lines
6.9 KiB
C++
220 lines
6.9 KiB
C++
//===-- 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 Designator and Designators utility
|
|
/// classes.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Designator.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/Expr.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace clang {
|
|
namespace reorder_fields {
|
|
|
|
void Designator::advanceToNextField() {
|
|
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;
|
|
}
|
|
}
|
|
|
|
bool Designator::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)
|
|
: 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)
|
|
: 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.advanceToNextField();
|
|
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;
|
|
|
|
if (!enterImplicitInitLists(Init)) {
|
|
DesignatorList.clear();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
llvm::raw_string_ostream OS(Designator);
|
|
for (auto &I : DesignatorList) {
|
|
switch (I.getTag()) {
|
|
case Designator::STRUCT:
|
|
OS << '.' << I.getStructIter()->getName();
|
|
break;
|
|
case Designator::ARRAY:
|
|
OS << '[' << I.getArrayIndex() << ']';
|
|
break;
|
|
case Designator::ARRAY_RANGE:
|
|
OS << '[' << I.getArrayRangeStart() << "..." << I.getArrayRangeEnd()
|
|
<< ']';
|
|
}
|
|
}
|
|
OS << " = ";
|
|
return Designator;
|
|
}
|
|
|
|
} // namespace reorder_fields
|
|
} // namespace clang
|