Status of the C++11 Migrator

Monday, April 15, 2013

Status of the C++11 Migrator

Since the design document for cpp11-migrate, the C++11 migrator tool, was first proposed in early December 2012 development has been making steady progress. In this article I’ll talk about what’s been implemented in cpp11-migrate so far, what’s coming up, and how you can get involved.

The purpose of the C++11 Migrator is to do source-to-source translation to migrate existing C++ code to use C++11 features to enhance maintainability, readability, runtime performance, and compile-time performance. Development is still early and transforms fall mostly into the first two categories. The migrator is based on Clang’s LibTooling and the AST Matching library.

Most of the development so far has been carried out by a small core group at Intel. Our focus so far has been to set up project infrastructure and testing, implement a few basic transforms, and make sure those transforms work well. Our aim is to make this tool useful to the community so we’re always listening for transform ideas and feedback.

How to Get cpp11-migrate

cpp11-migrate is located in the Extra Clang Tools repository. To build cpp11-migrate, you will need the LLVM and Clang sources as well. Follow the directions in Clang’s Getting Started instructionscpp11-migrate.check-clang-tools

The Transforms So Far

The C++11 Migrator currently supports four features of C++11:

  • Range-based for loops
  • The nullptr literal for null pointers
  • The auto type specifier
  • override virtual specifier

The range-based for-loop transform once existed as a stand-alone tool called contributed by Sam Panzer. When development on more transforms started, the idea became to pull all transforms under the jurisdiction of a single tool and was born. The range-based for-loop transform replaces for-loops used in one of the following three common situations:

The range-based for-loop transform once existed as a stand-alone tool called contributed by Sam Panzer. When development on more transforms started, the idea became to pull all transforms under the jurisdiction of a single tool and was born. The range-based for-loop transform replaces for-loops used in one of the following three common situations:

  1. Loops over containers using iterators

  2. std::vector<int> myVec;
    for (std::vector<int>::iterator I = myVec.begin(),
                                    E = myVec.end();
         I != E; ++I)
      llvm::outs() << *I;
    
  3. std::vector<int> myVec;
    for (auto & elem : myVec)
      llvm::outs() << elem;
    
  4. Loops over statically allocated arrays

  5. int arr[] = {1,2,3,4,5};
    for (int i = 0; i < 5; ++i)
      llvm::outs() << arr[i];
    
  6. int arr[] = {1,2,3,4,5};
    for (auto & elem : arr)
      llvm::outs() << elem;
    
  7. Loops over array-like containers using operator[] or at().

  8. std::vector<int> myVec;
    for (int i = 0; i < myVec.size(); ++i)
      llvm::outs() << v[i];
    
  9. std::vector<int> myVec;
    for (auto & elem : myVec)
      llvm::outs() << elem;
    

The nullptr transform uses the new literal where pointers are being initialized with or assigned a null value. In cases where an explicit cast is used, the explicit cast is left behind to avoid introducing ambiguities into the code.

void foo(int *arg);
void foo(float *arg);

int *IntPtr = 0;
float *FloatPtr = NULL;
foo(static_cast<int*>(0));

void foo(int *arg);
void foo(float *arg);

int *IntPtr = nullptr;
float *FloatPtr = nullptr;
foo(static_cast<int*>(nullptr));

The auto type specifier transform replaces the type specifier for variable declarations with the new keyword. In general, such a replacement can be done whenever the type of the variable declaration matches the type of its initializer. However, the transform targets only a few specific useful situations with readability and maintainability in mind:

  1. When the variable is an iterator for an STL container.

  2. std::vector<std::pair<int, std::string> >::iterator NameAgeI = People.begin();
    for (std::vector<MyType>::iterator I = Container.begin(),
                                       E = Container.end;
         I != E; ++I) {
      // ...
    }
    
  3. auto NameAgeI = People.begin();
    for (auto I = Container.begin(),
                                      E = Container.end;
         I != E; ++I) {
      // ...
    }
    
  4. When the initializer is an allocation using the new operator.

  5. MyType *VarPtr = new MyType();
    MyType * const VarCPtr = new MyType();
    
  6. auto VarPtr = new MyType();
    auto const VarCPtr = new MyType();
    

Support for a third situation is in development: creating objects with factory functions.

MyType *FooPtr = makeObject<MyType>(/*...*/);
MyType *BarPtr = MyType::create(/*...*/);

auto FooPtr = makeObject<MyType>(/*...*/);
auto BarPtr = MyType::create(/*...*/);

In each situation, the deduced type for the declared variable should be obvious to the reader. Iterators for standard containers are created by functions with specific names and are used in specific situations. For factory functions and operator newthe type is spelled out in the initializer so repeating it in the variable declaration is not necessary.

The override virtual specifier transform, contributed by Philip Dunstan, is the migrator’s fourth transform and the first to be contributed from outside the core group at Intel. This transform detects virtual member functions in derived classes that override member functions from parent classes and adds the override virtual specifier to the function.

class Parent {
public:
  virtual int getNumChildren();
};

class Child {
public:
  virtual int getNumChildren();
};

class Parent {
public:
  virtual int getNumChildren();
};

class Child {
public:
  virtual int getNumChildren() override;
};

More details on these transforms, what they can and can’t do, how to adjust their behaviour, and known limitations can be found in the .

Testing on Real Projects

What better way to test the C++11 Migrator than to run it on entire real projects? We’ve set up a continuous integration server to build and run cpp11-migrate on two projects so far and have plans for at least three more. For each project, the goal is to build the transformed code and run that project’s test suite to ensure semantics haven’t changed.

Implemented:

  1. LLVM 3.1
  2. ITK 4.3.1

Planned:

  1. LLDB
  2. OpenCV
  3. Poco

Running the migrator on real code has been enormously helpful for finding bugs. Real code from varying projects often reveals code expressions not accounted for in the development and unit testing of the transforms. Every time a bug found from transforming these projects gets fixed, new test cases are added to the regression test suite and the migrator becomes more robust.

Future Work

Fixing bugs found by migrating real code is of high priority right now since we want a good user experience for as many people as we can as soon as possible. Adding more transforms is another priority and those transforms with the most interest from the community will come first. Currently at the top of the list are:

  1. Use the standard library instead of TR1
  2. Replace use of the deprecated auto_ptr class.

In addition to fixing bugs and adding transforms, there are also more general improvements to consider. One such improvement we’re making progress on is to remove the restriction that only source files are transformed and not any of the headers they include. The restriction has been in place until now because the migrator needs to know which headers are safe to transform. System headers and third-party library headers clearly shouldn’t be touched.

Get Involved!

If you want to get involved, the first thing you can do is try out cpp11-migrate on your code. Bugs can be logged with LLVM’s bug tracker under the product clang-tools-extra. Send an email to the Clang Developer’s Mailing List if you need help or would like to get more involved. We look forward to hearing from you!

Posted by Edwin Vane at 5:53 AM

Labels: C++, Clang

Location: Waterloo, ON, Canada

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Microsoft Printer Migrator 是一个由微软开发的打印机迁移工具。它的主要功能是帮助用户在不同的计算机之间快速、简便地迁移打印机设置和驱动程序。 使用 Microsoft Printer Migrator,用户可以轻松地将一个打印机的设置从一台计算机复制到另一台计算机。这对于组织中需要频繁更换计算机的人员来说非常有用,他们不必花费很长时间手动重新配置每个新计算机的打印机设置。 此外,Microsoft Printer Migrator 还可以方便地迁移打印机驱动程序。打印机驱动程序是连接计算机和打印机之间的桥梁,其性能和兼容性直接影响打印任务的质量。使用该迁移工具,用户可以轻松地将一个打印机的驱动程序复制到另一台计算机,保证了打印机在不同计算机上的良好运行。 此外,该工具还支持在不同操作系统间进行打印机设置的迁移,例如在 Windows 7 和 Windows 10 之间。这对于那些需要升级操作系统或更换计算机的用户来说非常方便,他们可以轻松地将打印机设置从旧的操作系统迁移到新的操作系统,而不必重新配置打印机。 总之,Microsoft Printer Migrator 是一个功能丰富、易于使用的工具,可以帮助用户在不同的计算机之间迁移打印机设置和驱动程序。它极大地简化了打印机迁移的流程,节省了用户的时间和精力。 ### 回答2: Microsoft打印机迁移工具是一种由Microsoft开发的软件工具,用于帮助用户在不同的计算机系统或打印机之间迁移打印机设置和配置。 该工具的使用非常简便,用户只需按照指引一步步操作即可完成打印机的迁移。首先,用户需要选择要迁移的打印机,可以是连接在当前计算机上的本地打印机,也可以是网络中的共享打印机。接下来,用户需要选择目标计算机或目标打印机,即将打印机迁移至哪个计算机或打印机上。在迁移过程中,用户还可以选择是否包含与打印机相关的驱动程序和端口设置。 通过使用Microsoft打印机迁移工具,用户可以方便地将打印机设置从一台计算机迁移到另一台计算机上,无论是在局域网内还是在不同的网络环境下。这对于在更换计算机或迁移打印机到新的地点时,能够减少重复配置的工作量,提高工作效率,降低用户迁移过程中遇到的问题的可能性。 总之,Microsoft打印机迁移工具是一款实用的软件工具,可以帮助用户在不同的计算机系统或打印机之间快速迁移打印机设置和配置,从而提高用户的工作效率。 ### 回答3: Microsoft Printer Migrator(微软打印机迁移工具)是一种被微软公司开发的软件工具,用于帮助用户在不同的计算机系统之间迁移打印机设置和驱动程序。 在现代的办公环境中,打印机是至关重要的设备,每个用户都有可能需要连接不同的打印机来满足其工作需求。然而,当我们更换计算机或迁移到新的操作系统时,重新设置和安装打印机驱动程序可能会变得十分繁琐和耗时。为此,Microsoft Printer Migrator应运而生,以简化和加速这一过程。 使用Microsoft Printer Migrator,用户可以轻松地将他们在一个计算机上设置和配置好的打印机移植到另一个计算机上。该工具允许用户备份打印机设置和相关的驱动程序,并将其导出到一个文件,然后,用户可以将该文件导入到目标计算机上,以恢复原有的打印机设置。 此外,Microsoft Printer Migrator还支持批量迁移打印机设置。用户可以一次选择多个打印机进行备份和导出,并在目标计算机上一次性导入这些设置,从而大大提高了迁移效率。 总而言之,Microsoft Printer Migrator是一款方便实用的打印机迁移工具,可以帮助用户简化打印机设置和驱动程序的迁移过程,节省时间和精力。无论是在个人使用还是企业级迁移中,都可以利用这个工具来快速迁移打印机设置,提高工作效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值