[clang-tools-extra] r190212 - clang-modernize: Fix bugs in Pass-By-Value transform
Guillaume Papin
guillaume.papin at epitech.eu
Fri Sep 6 15:28:53 PDT 2013
Author: papin_g
Date: Fri Sep 6 17:28:53 2013
New Revision: 190212
URL: http://llvm.org/viewvc/llvm-project?rev=190212&view=rev
Log:
clang-modernize: Fix bugs in Pass-By-Value transform
- Limit the transform to const-ref and non-const value parameters only.
- Do not generate a replacement when the type is already a value.
See CM-139 for the bugs corresponding to this issue.
Modified:
clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueActions.cpp
clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueMatchers.cpp
clang-tools-extra/trunk/test/clang-modernize/PassByValue/basic.cpp
Modified: clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueActions.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueActions.cpp?rev=190212&r1=190211&r2=190212&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueActions.cpp (original)
+++ clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueActions.cpp Fri Sep 6 17:28:53 2013
@@ -113,16 +113,20 @@ void ConstructorParamReplacer::run(const
collectParamDecls(Ctor, ParamDecl, AllParamDecls);
// Generate all replacements for the params.
- llvm::SmallVector<Replacement, 2> ParamReplaces(AllParamDecls.size());
+ llvm::SmallVector<Replacement, 2> ParamReplaces;
for (unsigned I = 0, E = AllParamDecls.size(); I != E; ++I) {
TypeLoc ParamTL = AllParamDecls[I]->getTypeSourceInfo()->getTypeLoc();
+ ReferenceTypeLoc RefTL = ParamTL.getAs<ReferenceTypeLoc>();
SourceRange Range(AllParamDecls[I]->getLocStart(), ParamTL.getLocEnd());
CharSourceRange CharRange = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(Range), SM, LangOptions());
- TypeLoc ValueTypeLoc = ParamTL;
+
+ // do not generate a replacement when the parameter is already a value
+ if (RefTL.isNull())
+ continue;
+
// transform non-value parameters (e.g: const-ref) to values
- if (!ParamTL.getNextTypeLoc().isNull())
- ValueTypeLoc = ParamTL.getNextTypeLoc();
+ TypeLoc ValueTypeLoc = RefTL.getPointeeLoc();
llvm::SmallString<32> ValueStr = Lexer::getSourceText(
CharSourceRange::getTokenRange(ValueTypeLoc.getSourceRange()), SM,
LangOptions());
@@ -136,7 +140,7 @@ void ConstructorParamReplacer::run(const
// 'const Foo ¶m' -> 'Foo param'
// ~~~~~~~~~~~ ~~~^
ValueStr += ' ';
- ParamReplaces[I] = Replacement(SM, CharRange, ValueStr);
+ ParamReplaces.push_back(Replacement(SM, CharRange, ValueStr));
}
// Reject the changes if the the risk level is not acceptable.
Modified: clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueMatchers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueMatchers.cpp?rev=190212&r1=190211&r2=190212&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueMatchers.cpp (original)
+++ clang-tools-extra/trunk/clang-modernize/PassByValue/PassByValueMatchers.cpp Fri Sep 6 17:28:53 2013
@@ -63,6 +63,14 @@ AST_MATCHER(CXXConstructorDecl, isNonDel
using namespace clang;
using namespace clang::ast_matchers;
+static TypeMatcher constRefType() {
+ return lValueReferenceType(pointee(isConstQualified()));
+}
+
+static TypeMatcher nonConstValueType() {
+ return qualType(unless(anyOf(referenceType(), isConstQualified())));
+}
+
DeclarationMatcher makePassByValueCtorParamMatcher() {
return constructorDecl(
forEachConstructorInitializer(ctorInitializer(
@@ -71,7 +79,13 @@ DeclarationMatcher makePassByValueCtorPa
// is generated instead of a CXXConstructExpr, filtering out templates
// automatically for us.
withInitializer(constructExpr(
- has(declRefExpr(to(parmVarDecl().bind(PassByValueParamId)))),
+ has(declRefExpr(to(
+ parmVarDecl(hasType(qualType(
+ // match only const-ref or a non-const value
+ // parameters, rvalues and const-values
+ // shouldn't be modified.
+ anyOf(constRefType(), nonConstValueType()))))
+ .bind(PassByValueParamId)))),
hasDeclaration(constructorDecl(
isNonDeletedCopyConstructor(),
hasDeclContext(recordDecl(isMoveConstructible())))))))
Modified: clang-tools-extra/trunk/test/clang-modernize/PassByValue/basic.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-modernize/PassByValue/basic.cpp?rev=190212&r1=190211&r2=190212&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-modernize/PassByValue/basic.cpp (original)
+++ clang-tools-extra/trunk/test/clang-modernize/PassByValue/basic.cpp Fri Sep 6 17:28:53 2013
@@ -150,7 +150,7 @@ struct O {
// Test with a const-value parameter
struct P {
P(const Movable M) : M(M) {}
- // CHECK: P(Movable M) : M(std::move(M)) {}
+ // CHECK: P(const Movable M) : M(M) {}
Movable M;
};
@@ -166,3 +166,20 @@ struct Q {
Movable C;
double D;
};
+
+// Test that value-parameters with a nested name specifier are left as-is
+namespace ns_R {
+typedef ::Movable RMovable;
+}
+struct R {
+ R(ns_R::RMovable M) : M(M) {}
+ // CHECK: R(ns_R::RMovable M) : M(std::move(M)) {}
+ ns_R::RMovable M;
+};
+
+// Test with rvalue parameter
+struct S {
+ S(Movable &&M) : M(M) {}
+ // CHECK: S(Movable &&M) : M(M) {}
+ Movable M;
+};
More information about the cfe-commits
mailing list