mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 00:20:25 +08:00
[clang-tools-extra] Add support for plain C structs in clang-reorder-fields
This diff updates the tool clang-reorder-fields to enable reordering of fields of plain C structs. Test plan: make check-all Differential revision: https://reviews.llvm.org/D35329 llvm-svn: 308678
This commit is contained in:
@@ -32,10 +32,10 @@ using namespace clang::ast_matchers;
|
||||
/// \brief Finds the definition of a record by name.
|
||||
///
|
||||
/// \returns nullptr if the name is ambiguous or not found.
|
||||
static const CXXRecordDecl *findDefinition(StringRef RecordName,
|
||||
ASTContext &Context) {
|
||||
static const RecordDecl *findDefinition(StringRef RecordName,
|
||||
ASTContext &Context) {
|
||||
auto Results = match(
|
||||
recordDecl(hasName(RecordName), isDefinition()).bind("cxxRecordDecl"),
|
||||
recordDecl(hasName(RecordName), isDefinition()).bind("recordDecl"),
|
||||
Context);
|
||||
if (Results.empty()) {
|
||||
llvm::errs() << "Definition of " << RecordName << " not found\n";
|
||||
@@ -46,14 +46,14 @@ static const CXXRecordDecl *findDefinition(StringRef RecordName,
|
||||
<< " is ambiguous, several definitions found\n";
|
||||
return nullptr;
|
||||
}
|
||||
return selectFirst<CXXRecordDecl>("cxxRecordDecl", Results);
|
||||
return selectFirst<RecordDecl>("recordDecl", Results);
|
||||
}
|
||||
|
||||
/// \brief Calculates the new order of fields.
|
||||
///
|
||||
/// \returns empty vector if the list of fields doesn't match the definition.
|
||||
static SmallVector<unsigned, 4>
|
||||
getNewFieldsOrder(const CXXRecordDecl *Definition,
|
||||
getNewFieldsOrder(const RecordDecl *Definition,
|
||||
ArrayRef<std::string> DesiredFieldsOrder) {
|
||||
assert(Definition && "Definition is null");
|
||||
|
||||
@@ -97,7 +97,7 @@ addReplacement(SourceRange Old, SourceRange New, const ASTContext &Context,
|
||||
/// different accesses (public/protected/private) is not supported.
|
||||
/// \returns true on success.
|
||||
static bool reorderFieldsInDefinition(
|
||||
const CXXRecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
|
||||
const RecordDecl *Definition, ArrayRef<unsigned> NewFieldsOrder,
|
||||
const ASTContext &Context,
|
||||
std::map<std::string, tooling::Replacements> &Replacements) {
|
||||
assert(Definition && "Definition is null");
|
||||
@@ -223,7 +223,7 @@ public:
|
||||
ReorderingConsumer &operator=(const ReorderingConsumer &) = delete;
|
||||
|
||||
void HandleTranslationUnit(ASTContext &Context) override {
|
||||
const CXXRecordDecl *RD = findDefinition(RecordName, Context);
|
||||
const RecordDecl *RD = findDefinition(RecordName, Context);
|
||||
if (!RD)
|
||||
return;
|
||||
SmallVector<unsigned, 4> NewFieldsOrder =
|
||||
@@ -232,16 +232,21 @@ public:
|
||||
return;
|
||||
if (!reorderFieldsInDefinition(RD, NewFieldsOrder, Context, Replacements))
|
||||
return;
|
||||
for (const auto *C : RD->ctors())
|
||||
if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
|
||||
reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
|
||||
NewFieldsOrder, Context, Replacements);
|
||||
|
||||
// We only need to reorder init list expressions for aggregate types.
|
||||
// CXXRD will be nullptr if C code (not C++) is being processed.
|
||||
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
|
||||
if (CXXRD)
|
||||
for (const auto *C : CXXRD->ctors())
|
||||
if (const auto *D = dyn_cast<CXXConstructorDecl>(C->getDefinition()))
|
||||
reorderFieldsInConstructor(cast<const CXXConstructorDecl>(D),
|
||||
NewFieldsOrder, Context, Replacements);
|
||||
|
||||
// We only need to reorder init list expressions for
|
||||
// plain C structs or C++ aggregate types.
|
||||
// For other types the order of constructor parameters is used,
|
||||
// which we don't change at the moment.
|
||||
// Now (v0) partial initialization is not supported.
|
||||
if (RD->isAggregate())
|
||||
if (!CXXRD || CXXRD->isAggregate())
|
||||
for (auto Result :
|
||||
match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"),
|
||||
Context))
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// RUN: clang-reorder-fields -record-name Foo -fields-order z,w,y,x %s -- | FileCheck %s
|
||||
|
||||
struct Foo {
|
||||
const int* x; // CHECK: {{^ double z;}}
|
||||
int y; // CHECK-NEXT: {{^ int w;}}
|
||||
double z; // CHECK-NEXT: {{^ int y;}}
|
||||
int w; // CHECK-NEXT: {{^ const int\* x}}
|
||||
};
|
||||
|
||||
int main() {
|
||||
const int x = 13;
|
||||
struct Foo foo = { &x, 0, 1.29, 17 }; // CHECK: {{^ struct Foo foo = { 1.29, 17, 0, &x };}}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user