diff options
author | Alexander Kornienko <alexfh@google.com> | 2016-06-03 21:22:58 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2016-06-03 21:22:58 +0000 |
commit | c0308c451bc1f2b19ea4c60b3606edf6e1651731 (patch) | |
tree | e8dc44a114298d15f1e4a5a26638b2f88403e76e /clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp | |
parent | 94edaaaefba9727db12206de96c9046fe1629646 (diff) | |
download | bcm5719-llvm-c0308c451bc1f2b19ea4c60b3606edf6e1651731.tar.gz bcm5719-llvm-c0308c451bc1f2b19ea4c60b3606edf6e1651731.zip |
[clang-tidy] modernize-use-auto: don't remove stars by default
Summary:
By default, modernize-use-auto check will retain stars when replacing an explicit type with `auto`: `MyType *t = new MyType;` will be changed to `auto *t = new MyType;`, thus resulting in more consistency with the recommendations to use `auto *` for iterating over pointers in range-based for loops: http://llvm.org/docs/CodingStandards.html#beware-unnecessary-copies-with-auto
The new `RemoveStars` option allows to revert to the old behavior: with the new option turned on the check will change `MyType *t = new MyType;` to `auto t = new MyType;`.
Reviewers: aaron.ballman, sbenza
Subscribers: Eugene.Zelenko, cfe-commits
Differential Revision: http://reviews.llvm.org/D20917
llvm-svn: 271739
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp')
-rw-r--r-- | clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp index 415ecdd83ad..1f1c140f027 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -243,6 +243,14 @@ StatementMatcher makeDeclWithNewMatcher() { } // namespace +UseAutoCheck::UseAutoCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + RemoveStars(Options.get("RemoveStars", 0)) {} + +void UseAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "RemoveStars", RemoveStars ? 1 : 0); +} + void UseAutoCheck::registerMatchers(MatchFinder *Finder) { // Only register the matchers for C++; the functionality currently does not // provide any benefit to other languages, despite being benign. @@ -311,7 +319,7 @@ void UseAutoCheck::replaceNew(const DeclStmt *D, ASTContext *Context) { const QualType FirstDeclType = FirstDecl->getType().getCanonicalType(); - std::vector<SourceLocation> StarLocations; + std::vector<FixItHint> StarRemovals; for (const auto *Dec : D->decls()) { const auto *V = cast<VarDecl>(Dec); // Ensure that every DeclStmt child is a VarDecl. @@ -327,19 +335,23 @@ void UseAutoCheck::replaceNew(const DeclStmt *D, ASTContext *Context) { if (!Context->hasSameUnqualifiedType(V->getType(), NewExpr->getType())) return; - // Remove explicitly written '*' from declarations where there's more than - // one declaration in the declaration list. - if (Dec == *D->decl_begin()) - continue; - - // All subsequent declarations should match the same non-decorated type. + // All subsequent variables in this declaration should have the same + // canonical type. For example, we don't want to use `auto` in + // `T *p = new T, **pp = new T*;`. if (FirstDeclType != V->getType().getCanonicalType()) return; - auto Q = V->getTypeSourceInfo()->getTypeLoc().getAs<PointerTypeLoc>(); - while (!Q.isNull()) { - StarLocations.push_back(Q.getStarLoc()); - Q = Q.getNextTypeLoc().getAs<PointerTypeLoc>(); + if (RemoveStars) { + // Remove explicitly written '*' from declarations where there's more than + // one declaration in the declaration list. + if (Dec == *D->decl_begin()) + continue; + + auto Q = V->getTypeSourceInfo()->getTypeLoc().getAs<PointerTypeLoc>(); + while (!Q.isNull()) { + StarRemovals.push_back(FixItHint::CreateRemoval(Q.getStarLoc())); + Q = Q.getNextTypeLoc().getAs<PointerTypeLoc>(); + } } } @@ -347,19 +359,20 @@ void UseAutoCheck::replaceNew(const DeclStmt *D, ASTContext *Context) { // is the same as the initializer, just more CV-qualified. However, TypeLoc // information is not reliable where CV qualifiers are concerned so we can't // do anything about this case for now. - SourceRange Range( - FirstDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange()); + TypeLoc Loc = FirstDecl->getTypeSourceInfo()->getTypeLoc(); + if (!RemoveStars) { + while (Loc.getTypeLocClass() == TypeLoc::Pointer || + Loc.getTypeLocClass() == TypeLoc::Qualified) + Loc = Loc.getNextTypeLoc(); + } + SourceRange Range(Loc.getSourceRange()); auto Diag = diag(Range.getBegin(), "use auto when initializing with new" " to avoid duplicating the type name"); // Space after 'auto' to handle cases where the '*' in the pointer type is // next to the identifier. This avoids changing 'int *p' into 'autop'. - Diag << FixItHint::CreateReplacement(Range, "auto "); - - // Remove '*' from declarations using the saved star locations. - for (const auto &Loc : StarLocations) { - Diag << FixItHint::CreateReplacement(Loc, ""); - } + Diag << FixItHint::CreateReplacement(Range, RemoveStars ? "auto " : "auto") + << StarRemovals; } void UseAutoCheck::check(const MatchFinder::MatchResult &Result) { |