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
64 lines
2.4 KiB
C++
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;
|
|
}
|
|
}
|