Files
clang-p2996/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp
Edwin Vane 266b625ca9 Introducing Use-Auto transform for cpp11-migrate
The new Use-Auto transform replaces the type specifier for variable
declarations with the special C++11 'auto' type specifier. For now, the
replacement is done only for variables that are iterators of any of the
std containers and only if the type used is one of those explicitly
allowed by the standard (i.e. not an implementation-specific type).

Reviewers: gribozavr, silvas, klimek
llvm-svn: 176266
2013-02-28 16:29:24 +00:00

64 lines
2.4 KiB
C++

//===-- UseAuto/UseAutoActions.cpp - Matcher callback impl ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file contains the implementation of the UseAutoFixer class.
///
//===----------------------------------------------------------------------===//
#include "UseAutoActions.h"
#include "UseAutoMatchers.h"
#include "clang/AST/ASTContext.h"
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace clang;
void UseAutoFixer::run(const MatchFinder::MatchResult &Result) {
const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(DeclNodeId);
assert(D && "Bad Callback. No node provided");
SourceManager &SM = *Result.SourceManager;
if (!SM.isFromMainFile(D->getLocStart()))
return;
const CXXConstructExpr *Construct = cast<CXXConstructExpr>(D->getInit());
assert(Construct->getNumArgs() == 1u &&
"Expected constructor with single argument");
// Drill down to the as-written initializer.
const Expr *E = Construct->arg_begin()->IgnoreParenImpCasts();
if (E != E->IgnoreConversionOperator())
// We hit a conversion operator. Early-out now as they imply an implicit
// conversion from a different type. Could also mean an explicit conversion
// from the same type but that's pretty rare.
return;
if (const CXXConstructExpr *NestedConstruct = dyn_cast<CXXConstructExpr>(E))
// If we ran into an implicit conversion constructor, can't convert.
//
// FIXME: The following only checks if the constructor can be used
// implicitly, not if it actually was. Cases where the converting constructor
// was used explicitly won't get converted.
if (NestedConstruct->getConstructor()->isConvertingConstructor(false))
return;
if (Result.Context->hasSameType(D->getType(), E->getType())) {
TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
// WARNING: TypeLoc::getSourceRange() will include the identifier for things
// like function pointers. Not a concern since this action only works with
// iterators but something to keep in mind in the future.
CharSourceRange Range(TL.getSourceRange(), true);
Replace.insert(tooling::Replacement(SM, Range, "auto"));
++AcceptedChanges;
}
}