Hi revane,
useAuto used to match initialized variable declarations independently of
whether they were defined in a declaration list or as a single declaration. Now
it matches declaration statements where every variable declaration is
initialized.
http://llvm-reviews.chandlerc.com/D808
Files:
cpp11-migrate/UseAuto/UseAuto.cpp
cpp11-migrate/UseAuto/UseAutoActions.cpp
cpp11-migrate/UseAuto/UseAutoMatchers.cpp
cpp11-migrate/UseAuto/UseAutoMatchers.h
test/cpp11-migrate/UseAuto/iterator.cpp
Index: cpp11-migrate/UseAuto/UseAuto.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAuto.cpp
+++ cpp11-migrate/UseAuto/UseAuto.cpp
@@ -40,7 +40,7 @@
NewReplacer ReplaceNew(UseAutoTool.getReplacements(), AcceptedChanges,
MaxRisk);
- Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
+ Finder.addMatcher(makeDeclStatmentMatcher(), &ReplaceIterators);
Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
if (int Result = UseAutoTool.run(newFrontendActionFactory(&Finder))) {
Index: cpp11-migrate/UseAuto/UseAutoActions.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAutoActions.cpp
+++ cpp11-migrate/UseAuto/UseAutoActions.cpp
@@ -20,54 +20,60 @@
using namespace clang::tooling;
using namespace clang;
-void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
- const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(IteratorDeclId);
+void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
+ const DeclStmt *D = Result.Nodes.getNodeAs<DeclStmt>(IteratorDeclStmtId);
assert(D && "Bad Callback. No node provided");
SourceManager &SM = *Result.SourceManager;
if (!SM.isFromMainFile(D->getLocStart()))
return;
- const Expr *ExprInit = D->getInit();
+ for (clang::DeclStmt::const_decl_iterator I = D->decl_begin(),
+ E = D->decl_end(); I != E; ++I) {
+ const VarDecl *V = cast<VarDecl>(*I);
- // Skip expressions with cleanups from the initializer expression.
- if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(ExprInit))
- ExprInit = E->getSubExpr();
+ const Expr *ExprInit = V->getInit();
- const CXXConstructExpr *Construct = cast<CXXConstructExpr>(ExprInit);
+ // Skip expressions with cleanups from the initializer expression.
+ if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(ExprInit))
+ ExprInit = E->getSubExpr();
- assert(Construct->getNumArgs() == 1u &&
- "Expected constructor with single argument");
+ const CXXConstructExpr *Construct = cast<CXXConstructExpr>(ExprInit);
- // 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;
+ assert(Construct->getNumArgs() == 1u &&
+ "Expected constructor with single argument");
- 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))
+ // 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 (Result.Context->hasSameType(D->getType(), E->getType())) {
- TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
+ 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(V->getType(), E->getType()))
+ return;
+ }
+ // Get the type location using the first declartion.
+ const VarDecl *V = cast<VarDecl>(*D->decl_begin());
+ TypeLoc TL = V->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.
+ // 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;
- }
+ CharSourceRange Range(TL.getSourceRange(), true);
+ Replace.insert(tooling::Replacement(SM, Range, "auto"));
+ ++AcceptedChanges;
}
void NewReplacer::run(const MatchFinder::MatchResult &Result) {
@@ -77,7 +83,7 @@
SourceManager &SM = *Result.SourceManager;
if (!SM.isFromMainFile(D->getLocStart()))
return;
-
+
const CXXNewExpr *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>(NewExprId);
assert(NewExpr && "Bad Callback. No CXXNewExpr bound");
Index: cpp11-migrate/UseAuto/UseAutoMatchers.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAutoMatchers.cpp
+++ cpp11-migrate/UseAuto/UseAutoMatchers.cpp
@@ -18,7 +18,7 @@
using namespace clang::ast_matchers;
using namespace clang;
-const char *IteratorDeclId = "iterator_decl";
+const char *IteratorDeclStmtId = "iterator_decl";
const char *DeclWithNewId = "decl_new";
const char *NewExprId = "new_expr";
@@ -157,6 +157,7 @@
return false;
}
+
} // namespace ast_matchers
} // namespace clang
@@ -232,22 +233,34 @@
}
} // namespace
-DeclarationMatcher makeIteratorDeclMatcher() {
- return varDecl(allOf(
- hasWrittenNonListInitializer(),
- unless(hasType(autoType())),
- hasType(
- isSugarFor(
- anyOf(
- typedefIterator(),
- nestedIterator(),
- iteratorFromUsingDeclaration()
- )
- )
- )
- )).bind(IteratorDeclId);
+StatementMatcher makeDeclStatmentMatcher() {
+ return declStmt(
+ has(varDecl()),
+ unless(
+ has(
+ varDecl(
+ anyOf(
+ unless(hasWrittenNonListInitializer()),
+ hasType(autoType()),
+ unless(
+ hasType(
+ isSugarFor(
+ anyOf(
+ typedefIterator(),
+ nestedIterator(),
+ iteratorFromUsingDeclaration()
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ ).bind(IteratorDeclStmtId);
}
+
DeclarationMatcher makeDeclWithNewMatcher() {
return varDecl(
hasInitializer(
Index: cpp11-migrate/UseAuto/UseAutoMatchers.h
===================================================================
--- cpp11-migrate/UseAuto/UseAutoMatchers.h
+++ cpp11-migrate/UseAuto/UseAutoMatchers.h
@@ -17,14 +17,14 @@
#include "clang/ASTMatchers/ASTMatchers.h"
-extern const char *IteratorDeclId;
+extern const char *IteratorDeclStmtId;
extern const char *DeclWithNewId;
extern const char *NewExprId;
-/// \brief Create a matcher that matches variable declarations where the type
-/// is an iterator for an std container and has an explicit initializer of the
-/// same type.
-clang::ast_matchers::DeclarationMatcher makeIteratorDeclMatcher();
+/// \brief Create a matcher that matches declaration staments that have
+/// variable declarations where the type is an iterator for an std container
+/// and has an explicit initializer of the same type.
+clang::ast_matchers::StatementMatcher makeDeclStatmentMatcher();
/// \brief Create a matcher that matches variable declarations that are
/// initialized by a C++ new expression.
Index: test/cpp11-migrate/UseAuto/iterator.cpp
===================================================================
--- test/cpp11-migrate/UseAuto/iterator.cpp
+++ test/cpp11-migrate/UseAuto/iterator.cpp
@@ -156,5 +156,10 @@
// CHECK: auto I = MapFind.find("foo");
}
+ // declaration lists with non-initialized variables should not be transformed
+ {
+ std::vector<int>::iterator I = Vec.begin(), J;
+ // CHECK: std::vector<int>::iterator I = Vec.begin(), J;
+ }
return 0;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits