diff options
Diffstat (limited to 'clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp')
-rw-r--r-- | clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp new file mode 100644 index 00000000000..ceb22390a1f --- /dev/null +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp @@ -0,0 +1,63 @@ +//===-- 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; + } +} |