[clang-tools-extra] [clang-tidy] performance-unnecessary-copy-init: Add a hook... (PR #73921)

2023-12-05 Thread Felix Berger via cfe-commits

https://github.com/fberger approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/73921
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] performance-unnecessary-copy-init: Add a hook... (PR #73921)

2023-12-05 Thread Felix Berger via cfe-commits


@@ -290,69 +296,72 @@ void UnnecessaryCopyInitialization::check(
   // instantiations where the types differ and rely on implicit conversion 
would
   // no longer compile if we switched to a reference.
   if (differentReplacedTemplateParams(
-  NewVar->getType(), constructorArgumentType(OldVar, Result.Nodes),
+  Context.Var.getType(), constructorArgumentType(OldVar, Result.Nodes),
   *Result.Context))
 return;
 
   if (OldVar == nullptr) {
-handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg,
-   *Result.Context);
+// `auto NewVar = functionCall();`
+handleCopyFromMethodReturn(Context, ObjectArg);
   } else {
-handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
-   *Result.Context);
+// `auto NewVar = OldVar;`
+handleCopyFromLocalVar(Context, *OldVar);
   }
 }
 
-void UnnecessaryCopyInitialization::makeDiagnostic(
-DiagnosticBuilder Diagnostic, const VarDecl &Var, const Stmt &BlockStmt,
-const DeclStmt &Stmt, ASTContext &Context, bool IssueFix) {
-  const bool IsVarUnused = isVariableUnused(Var, BlockStmt, Context);
-  Diagnostic << &Var << IsVarUnused;
-  if (!IssueFix)
-return;
-  if (IsVarUnused)
-recordRemoval(Stmt, Context, Diagnostic);
-  else
-recordFixes(Var, Context, Diagnostic);
-}
-
 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
-const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
-bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) {
-  bool IsConstQualified = Var.getType().isConstQualified();
-  if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context))
+const CheckContext &Ctx, const VarDecl *ObjectArg) {
+  bool IsConstQualified = Ctx.Var.getType().isConstQualified();
+  if (!IsConstQualified && !Ctx.IsVarOnlyUsedAsConst)
 return;
   if (ObjectArg != nullptr &&
-  !isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context,
+  !isInitializingVariableImmutable(*ObjectArg, Ctx.BlockStmt, Ctx.ASTCtx,
ExcludedContainerTypes))
 return;
-
-  auto Diagnostic =
-  diag(Var.getLocation(),
-   "the %select{|const qualified }0variable %1 is copy-constructed "
-   "from a const reference%select{"
-   "%select{ but is only used as const reference|}0"
-   "| but is never used}2; consider "
-   "%select{making it a const reference|removing the statement}2")
-  << IsConstQualified;
-  makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
- IssueFix);
+  diagnoseCopyFromMethodReturn(Ctx, ObjectArg);
 }
 
 void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
-const VarDecl &Var, const VarDecl &OldVar, const Stmt &BlockStmt,
-const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) {
-  if (!isOnlyUsedAsConst(Var, BlockStmt, Context) ||
-  !isInitializingVariableImmutable(OldVar, BlockStmt, Context,
+const CheckContext &Ctx, const VarDecl &OldVar) {
+  if (!Ctx.IsVarOnlyUsedAsConst ||
+  !isInitializingVariableImmutable(OldVar, Ctx.BlockStmt, Ctx.ASTCtx,
ExcludedContainerTypes))
 return;
-  auto Diagnostic = diag(Var.getLocation(),
- "local copy %1 of the variable %0 is never modified"
- "%select{| and never used}2; consider "
- "%select{avoiding the copy|removing the statement}2")
-<< &OldVar;
-  makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
- IssueFix);
+  diagnoseCopyFromLocalVar(Ctx, OldVar);
+}
+
+void UnnecessaryCopyInitialization::diagnoseCopyFromMethodReturn(
+const CheckContext &Ctx, const VarDecl *ObjectArg) {

fberger wrote:

It doesn't look like ObjectArg is used. Can we remove it?

https://github.com/llvm/llvm-project/pull/73921
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] performance-unnecessary-copy-init: Add a hook... (PR #73921)

2023-12-05 Thread Felix Berger via cfe-commits


@@ -290,69 +296,72 @@ void UnnecessaryCopyInitialization::check(
   // instantiations where the types differ and rely on implicit conversion 
would
   // no longer compile if we switched to a reference.
   if (differentReplacedTemplateParams(
-  NewVar->getType(), constructorArgumentType(OldVar, Result.Nodes),
+  Context.Var.getType(), constructorArgumentType(OldVar, Result.Nodes),
   *Result.Context))
 return;
 
   if (OldVar == nullptr) {
-handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg,
-   *Result.Context);
+// `auto NewVar = functionCall();`
+handleCopyFromMethodReturn(Context, ObjectArg);
   } else {
-handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
-   *Result.Context);
+// `auto NewVar = OldVar;`
+handleCopyFromLocalVar(Context, *OldVar);
   }
 }
 
-void UnnecessaryCopyInitialization::makeDiagnostic(
-DiagnosticBuilder Diagnostic, const VarDecl &Var, const Stmt &BlockStmt,
-const DeclStmt &Stmt, ASTContext &Context, bool IssueFix) {
-  const bool IsVarUnused = isVariableUnused(Var, BlockStmt, Context);
-  Diagnostic << &Var << IsVarUnused;
-  if (!IssueFix)
-return;
-  if (IsVarUnused)
-recordRemoval(Stmt, Context, Diagnostic);
-  else
-recordFixes(Var, Context, Diagnostic);
-}
-
 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
-const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
-bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) {
-  bool IsConstQualified = Var.getType().isConstQualified();
-  if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context))
+const CheckContext &Ctx, const VarDecl *ObjectArg) {
+  bool IsConstQualified = Ctx.Var.getType().isConstQualified();
+  if (!IsConstQualified && !Ctx.IsVarOnlyUsedAsConst)
 return;
   if (ObjectArg != nullptr &&
-  !isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context,
+  !isInitializingVariableImmutable(*ObjectArg, Ctx.BlockStmt, Ctx.ASTCtx,
ExcludedContainerTypes))
 return;
-
-  auto Diagnostic =
-  diag(Var.getLocation(),
-   "the %select{|const qualified }0variable %1 is copy-constructed "
-   "from a const reference%select{"
-   "%select{ but is only used as const reference|}0"
-   "| but is never used}2; consider "
-   "%select{making it a const reference|removing the statement}2")
-  << IsConstQualified;
-  makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
- IssueFix);
+  diagnoseCopyFromMethodReturn(Ctx, ObjectArg);
 }
 
 void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
-const VarDecl &Var, const VarDecl &OldVar, const Stmt &BlockStmt,
-const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) {
-  if (!isOnlyUsedAsConst(Var, BlockStmt, Context) ||
-  !isInitializingVariableImmutable(OldVar, BlockStmt, Context,
+const CheckContext &Ctx, const VarDecl &OldVar) {
+  if (!Ctx.IsVarOnlyUsedAsConst ||
+  !isInitializingVariableImmutable(OldVar, Ctx.BlockStmt, Ctx.ASTCtx,
ExcludedContainerTypes))
 return;
-  auto Diagnostic = diag(Var.getLocation(),
- "local copy %1 of the variable %0 is never modified"
- "%select{| and never used}2; consider "
- "%select{avoiding the copy|removing the statement}2")
-<< &OldVar;
-  makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
- IssueFix);
+  diagnoseCopyFromLocalVar(Ctx, OldVar);
+}
+
+void UnnecessaryCopyInitialization::diagnoseCopyFromMethodReturn(
+const CheckContext &Ctx, const VarDecl *ObjectArg) {

fberger wrote:

Oh, I see sub classes might need access to it. Makes sense.

https://github.com/llvm/llvm-project/pull/73921
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] performance-unnecessary-copy-init: Add a hook... (PR #73921)

2023-12-05 Thread Felix Berger via cfe-commits

https://github.com/fberger edited 
https://github.com/llvm/llvm-project/pull/73921
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-tidy] Handle C++ structured bindings in `performance-for-range-copy` (PR #77105)

2024-01-08 Thread Felix Berger via cfe-commits

https://github.com/fberger edited 
https://github.com/llvm/llvm-project/pull/77105
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [clang-tidy] Handle C++ structured bindings in `performance-for-range-copy` (PR #77105)

2024-01-08 Thread Felix Berger via cfe-commits


@@ -234,6 +239,22 @@ void positiveOnlyAccessedFieldAsConst() {
   }
 }
 
+void positiveOnlyAccessedFieldAsConstBinding() {
+  for (auto [X, Y] : View>()) {
+// CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but
+// CHECK-FIXES: for (const auto& [X, Y] : View>()) {
+use(X);
+use(Y);
+  }
+}
+
+void negativeOnlyAccessedFieldAsConstBinding() {

fberger wrote:

Same here: Can we just have "mutated" in the function name?

https://github.com/llvm/llvm-project/pull/77105
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-tidy] Handle C++ structured bindings in `performance-for-range-copy` (PR #77105)

2024-01-08 Thread Felix Berger via cfe-commits

https://github.com/fberger approved this pull request.


https://github.com/llvm/llvm-project/pull/77105
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-tidy] Handle C++ structured bindings in `performance-for-range-copy` (PR #77105)

2024-01-08 Thread Felix Berger via cfe-commits


@@ -234,6 +239,22 @@ void positiveOnlyAccessedFieldAsConst() {
   }
 }
 
+void positiveOnlyAccessedFieldAsConstBinding() {

fberger wrote:

Why `AccessedField` here, it seems to be `JustUsedAsConst` as in other test 
names?

https://github.com/llvm/llvm-project/pull/77105
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] 00edae9 - [clang-tidy] performance-unnecessary-copy-initialization: Disable check when variable and initializer have different replaced template param types.

2021-07-22 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-07-22T15:17:24-04:00
New Revision: 00edae9203c9a4f50da058d4bd25dc2e6a4930c1

URL: 
https://github.com/llvm/llvm-project/commit/00edae9203c9a4f50da058d4bd25dc2e6a4930c1
DIFF: 
https://github.com/llvm/llvm-project/commit/00edae9203c9a4f50da058d4bd25dc2e6a4930c1.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Disable check 
when variable and initializer have different replaced template param types.

This can happen when a template with two parameter types is instantiated with a
single type. The fix would only be valid for this instantiation but fail for
others that rely on an implicit type conversion.

The test cases illustrate when the check should trigger and when not.

Differential Revision: https://reviews.llvm.org/D106011

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index f6b8e44785b5f..9631e06a8f95b 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -27,6 +27,8 @@ using utils::decl_ref_expr::isOnlyUsedAsConst;
 
 static constexpr StringRef ObjectArgId = "objectArg";
 static constexpr StringRef InitFunctionCallId = "initFunctionCall";
+static constexpr StringRef MethodDeclId = "methodDecl";
+static constexpr StringRef FunctionDeclId = "functionDecl";
 static constexpr StringRef OldVarDeclId = "oldVarDecl";
 
 void recordFixes(const VarDecl &Var, ASTContext &Context,
@@ -81,7 +83,8 @@ AST_MATCHER_FUNCTION(StatementMatcher, 
isConstRefReturningMethodCall) {
   // returned either points to a global static variable or to a member of the
   // called object.
   return cxxMemberCallExpr(
-  callee(cxxMethodDecl(returns(matchers::isReferenceToConst(,
+  callee(cxxMethodDecl(returns(matchers::isReferenceToConst()))
+ .bind(MethodDeclId)),
   on(declRefExpr(to(varDecl().bind(ObjectArgId);
 }
 
@@ -89,7 +92,8 @@ AST_MATCHER_FUNCTION(StatementMatcher, 
isConstRefReturningFunctionCall) {
   // Only allow initialization of a const reference from a free function if it
   // has no arguments. Otherwise it could return an alias to one of its
   // arguments and the arguments need to be checked for const use as well.
-  return 
callExpr(callee(functionDecl(returns(matchers::isReferenceToConst(,
+  return callExpr(callee(functionDecl(returns(matchers::isReferenceToConst()))
+ .bind(FunctionDeclId)),
   argumentCountIs(0), unless(callee(cxxMethodDecl(
   .bind(InitFunctionCallId);
 }
@@ -155,6 +159,45 @@ bool isVariableUnused(const VarDecl &Var, const Stmt 
&BlockStmt,
   return allDeclRefExprs(Var, BlockStmt, Context).empty();
 }
 
+const SubstTemplateTypeParmType *getSubstitutedType(const QualType &Type,
+ASTContext &Context) {
+  auto Matches = match(
+  qualType(anyOf(substTemplateTypeParmType().bind("subst"),
+ 
hasDescendant(substTemplateTypeParmType().bind("subst",
+  Type, Context);
+  return selectFirst("subst", Matches);
+}
+
+bool 
diff erentReplacedTemplateParams(const QualType &VarType,
+ const QualType &InitializerType,
+ ASTContext &Context) {
+  if (const SubstTemplateTypeParmType *VarTmplType =
+  getSubstitutedType(VarType, Context)) {
+if (const SubstTemplateTypeParmType *InitializerTmplType =
+getSubstitutedType(InitializerType, Context)) {
+  return VarTmplType->getReplacedParameter()
+ ->desugar()
+ .getCanonicalType() !=
+ InitializerTmplType->getReplacedParameter()
+ ->desugar()
+ .getCanonicalType();
+}
+  }
+  return false;
+}
+
+QualType constructorArgumentType(const VarDecl *OldVar,
+ const BoundNodes &Nodes) {
+  if (OldVar) {
+return OldVar->getType();
+  }
+  if (const auto *FuncDecl = Nodes.getNodeAs(FunctionDeclId)) {
+return FuncDecl->getReturnType();
+  }
+  const auto *MethodDecl = Nodes.getNodeAs(MethodDeclId);
+  return MethodDecl->getReturnType();
+}
+
 } // namespace
 
 UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
@@ -222,6 +265,16 @@ void UnnecessaryCopyInitialization::check(
 if (!CtorCall->getArg(I)->isDefaultArgument())
   return;
 
+  // Don't apply the check if the variable and its initializer have 
diff erent
+  // replaced template parameter types. In this case the check trigg

[clang-tools-extra] cb4c12b - [clang-tidy] performance-unnecessary-copy-initialization: Create option to exclude container types from triggering the check.

2021-07-22 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-07-22T16:20:20-04:00
New Revision: cb4c12b6117a6f2989d5745854a94c75cb6a09ba

URL: 
https://github.com/llvm/llvm-project/commit/cb4c12b6117a6f2989d5745854a94c75cb6a09ba
DIFF: 
https://github.com/llvm/llvm-project/commit/cb4c12b6117a6f2989d5745854a94c75cb6a09ba.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Create option to 
exclude container types from triggering the check.

Add string list option of type names analagous to `AllowedTypes` which lets
users specify a list of ExcludedContainerTypes.

Types matching this list will not trigger the check when an expensive variable
is copy initialized from a const accessor method they provide, i.e.:

```
ExcludedContainerTypes = 'ExcludedType'

void foo() {
  ExcludedType Container;
  const ExpensiveToCopy NecessaryCopy = Container.get();
}
```

Even though an expensive to copy variable is copy initialized the check does not
trigger because the container type is excluded.

This is useful for container types that don't own their data, such as view types
where modification of the returned references in other places cannot be reliably
tracked, or const incorrect types.

Differential Revision: https://reviews.llvm.org/D106173

Reviewed-by: ymandel

Added: 

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-excluded-container-types.cpp

Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h

clang-tools-extra/docs/clang-tidy/checks/performance-unnecessary-copy-initialization.rst

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 9631e06a8f95b..6f9495fd1e66c 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -75,7 +75,8 @@ void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
   }
 }
 
-AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningMethodCall) {
+AST_MATCHER_FUNCTION_P(StatementMatcher, isConstRefReturningMethodCall,
+   std::vector, ExcludedContainerTypes) {
   // Match method call expressions where the `this` argument is only used as
   // const, this will be checked in `check()` part. This returned const
   // reference is highly likely to outlive the local const reference of the
@@ -85,7 +86,11 @@ AST_MATCHER_FUNCTION(StatementMatcher, 
isConstRefReturningMethodCall) {
   return cxxMemberCallExpr(
   callee(cxxMethodDecl(returns(matchers::isReferenceToConst()))
  .bind(MethodDeclId)),
-  on(declRefExpr(to(varDecl().bind(ObjectArgId);
+  on(declRefExpr(to(
+  varDecl(
+  
unless(hasType(qualType(hasCanonicalType(hasDeclaration(namedDecl(
+  matchers::matchesAnyListedName(ExcludedContainerTypes
+  .bind(ObjectArgId);
 }
 
 AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningFunctionCall) {
@@ -98,11 +103,13 @@ AST_MATCHER_FUNCTION(StatementMatcher, 
isConstRefReturningFunctionCall) {
   .bind(InitFunctionCallId);
 }
 
-AST_MATCHER_FUNCTION(StatementMatcher, initializerReturnsReferenceToConst) {
+AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst,
+   std::vector, ExcludedContainerTypes) {
   auto OldVarDeclRef =
   declRefExpr(to(varDecl(hasLocalStorage()).bind(OldVarDeclId)));
   return expr(
-  anyOf(isConstRefReturningFunctionCall(), isConstRefReturningMethodCall(),
+  anyOf(isConstRefReturningFunctionCall(),
+isConstRefReturningMethodCall(ExcludedContainerTypes),
 ignoringImpCasts(OldVarDeclRef),
 ignoringImpCasts(unaryOperator(hasOperatorName("&"),
hasUnaryOperand(OldVarDeclRef);
@@ -120,9 +127,9 @@ AST_MATCHER_FUNCTION(StatementMatcher, 
initializerReturnsReferenceToConst) {
 // the same set of criteria we apply when identifying the unnecessary copied
 // variable in this check to begin with. In this case we check whether the
 // object arg or variable that is referenced is immutable as well.
-static bool isInitializingVariableImmutable(const VarDecl &InitializingVar,
-const Stmt &BlockStmt,
-ASTContext &Context) {
+static bool isInitializingVariableImmutable(
+const VarDecl &InitializingVar, const Stmt &BlockStmt, ASTContext &Context,
+const std::vector &ExcludedContainerTypes) {
   if (!isOnlyUsedAsConst(InitializingVar, BlockStmt, Context))
 return false;
 
@@ -138,18 +145,21 @@ static bool isInitializingVariableImmutable(const VarDecl 
&I

[clang-tools-extra] [clang-tidy] `isOnlyUsedAsConst`: Handle static method calls. (PR #84005)

2024-03-06 Thread Felix Berger via cfe-commits

https://github.com/fberger approved this pull request.


https://github.com/llvm/llvm-project/pull/84005
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add support for determining constness of more expressions. (PR #82617)

2024-02-23 Thread Felix Berger via cfe-commits

https://github.com/fberger approved this pull request.


https://github.com/llvm/llvm-project/pull/82617
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] 671ad58 - [clang-tidy] performance-unnecessary-copy-initialization: Prevent false positives when dependent variable is modified.

2020-12-10 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2020-12-10T16:58:17-05:00
New Revision: 671ad580610ad91139358b7786e02ff70433a90e

URL: 
https://github.com/llvm/llvm-project/commit/671ad580610ad91139358b7786e02ff70433a90e
DIFF: 
https://github.com/llvm/llvm-project/commit/671ad580610ad91139358b7786e02ff70433a90e.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Prevent false 
positives when dependent variable is modified.

Extend the check to not only look at the variable the unnecessarily copied
variable is initialized from, but also ensure that any variable the old variable
references is not modified.

Extend DeclRefExprUtils to also count references and pointers to const assigned
from the DeclRef we check for const usages.

Reviewed-by: aaron.ballman

Differential Revision: https://reviews.llvm.org/D91893

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
clang-tools-extra/clang-tidy/utils/Matchers.h

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 24847d80657c..f6b9365435fb 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -19,6 +19,14 @@ namespace tidy {
 namespace performance {
 namespace {
 
+using namespace ::clang::ast_matchers;
+using llvm::StringRef;
+using utils::decl_ref_expr::isOnlyUsedAsConst;
+
+static constexpr StringRef ObjectArgId = "objectArg";
+static constexpr StringRef InitFunctionCallId = "initFunctionCall";
+static constexpr StringRef OldVarDeclId = "oldVarDecl";
+
 void recordFixes(const VarDecl &Var, ASTContext &Context,
  DiagnosticBuilder &Diagnostic) {
   Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context);
@@ -29,10 +37,88 @@ void recordFixes(const VarDecl &Var, ASTContext &Context,
   }
 }
 
-} // namespace
+AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningMethodCall) {
+  // Match method call expressions where the `this` argument is only used as
+  // const, this will be checked in `check()` part. This returned const
+  // reference is highly likely to outlive the local const reference of the
+  // variable being declared. The assumption is that the const reference being
+  // returned either points to a global static variable or to a member of the
+  // called object.
+  return cxxMemberCallExpr(
+  callee(cxxMethodDecl(returns(matchers::isReferenceToConst(,
+  on(declRefExpr(to(varDecl().bind(ObjectArgId);
+}
 
-using namespace ::clang::ast_matchers;
-using utils::decl_ref_expr::isOnlyUsedAsConst;
+AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningFunctionCall) {
+  // Only allow initialization of a const reference from a free function if it
+  // has no arguments. Otherwise it could return an alias to one of its
+  // arguments and the arguments need to be checked for const use as well.
+  return 
callExpr(callee(functionDecl(returns(matchers::isReferenceToConst(,
+  argumentCountIs(0), unless(callee(cxxMethodDecl(
+  .bind(InitFunctionCallId);
+}
+
+AST_MATCHER_FUNCTION(StatementMatcher, isInitializedFromReferenceToConst) {
+  auto OldVarDeclRef =
+  declRefExpr(to(varDecl(hasLocalStorage()).bind(OldVarDeclId)));
+  return declStmt(has(varDecl(hasInitializer(
+  anyOf(isConstRefReturningFunctionCall(), isConstRefReturningMethodCall(),
+ignoringImpCasts(OldVarDeclRef),
+ignoringImpCasts(unaryOperator(
+hasOperatorName("&"), hasUnaryOperand(OldVarDeclRef;
+}
+
+// This checks that the variable itself is only used as const, and also makes
+// sure that it does not reference another variable that could be modified in
+// the BlockStmt. It does this by checking the following:
+// 1. If the variable is neither a reference nor a pointer then the
+// isOnlyUsedAsConst() check is sufficient.
+// 2. If the (reference or pointer) variable is not initialized in a DeclStmt 
in
+// the BlockStmt. In this case its pointee is likely not modified (unless it
+// is passed as an alias into the method as well).
+// 3. If the reference is initialized from a reference to const. This is
+// the same set of criteria we apply when identifying the unnecessary copied
+// variable in this check to begin with. In this case we check whether the
+// object arg or variable that is referenced is immutable as well.
+static bool isInitializingVariableImmutable(const VarDecl &InitializingVar,
+const Stmt &BlockStmt,
+ASTContex

[clang-tools-extra] ace9653 - [clang-tidy] performance-unnecessary-copy-initialization: Check for const reference arguments that are replaced template parameter type.

2020-11-16 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2020-11-16T17:08:18-05:00
New Revision: ace9653c11c6308401dcda2e8b26bf97e6e66e30

URL: 
https://github.com/llvm/llvm-project/commit/ace9653c11c6308401dcda2e8b26bf97e6e66e30
DIFF: 
https://github.com/llvm/llvm-project/commit/ace9653c11c6308401dcda2e8b26bf97e6e66e30.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Check for const 
reference arguments that are replaced template parameter type.

This fixes false positive cases where a non-const reference is passed to a
std::function but interpreted as a const reference.

Fix the definition of the fake std::function added in the test to match
std::function and make the bug reproducible.

Reviewed-by: aaron.ballman

Differential Revision: https://reviews.llvm.org/D90042

Added: 


Modified: 
clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp 
b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
index c4bc1835057b..d0933f0860c8 100644
--- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
+++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
@@ -59,9 +59,13 @@ constReferenceDeclRefExprs(const VarDecl &VarDecl, const 
Stmt &Stmt,
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   auto ConstReferenceOrValue =
   qualType(anyOf(referenceType(pointee(qualType(isConstQualified(,
- unless(anyOf(referenceType(), pointerType();
+ unless(anyOf(referenceType(), pointerType(),
+  substTemplateTypeParmType();
+  auto ConstReferenceOrValueOrReplaced = qualType(anyOf(
+  ConstReferenceOrValue,
+  substTemplateTypeParmType(hasReplacementType(ConstReferenceOrValue;
   auto UsedAsConstRefOrValueArg = forEachArgumentWithParam(
-  DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValue)));
+  DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValueOrReplaced)));
   Matches = match(findAll(callExpr(UsedAsConstRefOrValueArg)), Stmt, Context);
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   Matches =

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
index 9055529c7a3f..120902d0eade 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -411,12 +411,12 @@ inline namespace __1 {
 
 template 
 class function;
-template 
-class function {
+template 
+class function {
 public:
   function();
-  function(const function &other);
-  R operator()(Args &&...args) const;
+  function(const function &Other);
+  R operator()(ArgTypes... Args) const;
 };
 
 } // namespace __1
@@ -460,3 +460,19 @@ void positiveFakeStdFunction(std::function F) {
 }
 
 } // namespace fake
+
+void positiveInvokedOnStdFunction(
+std::function Update,
+const ExpensiveToCopyType Orig) {
+  auto Copy = Orig.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'Copy' is 
copy-constructed from a const reference
+  // CHECK-FIXES: const auto& Copy = Orig.reference();
+  Update(Copy);
+}
+
+void negativeInvokedOnStdFunction(
+std::function Update,
+const ExpensiveToCopyType Orig) {
+  auto Copy = Orig.reference();
+  Update(Copy);
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] 1c1f794 - Always allow std::function to be copied.

2020-10-21 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2020-10-21T17:20:35-04:00
New Revision: 1c1f794c2b645ba33a98f0359bc9d30bbef89920

URL: 
https://github.com/llvm/llvm-project/commit/1c1f794c2b645ba33a98f0359bc9d30bbef89920
DIFF: 
https://github.com/llvm/llvm-project/commit/1c1f794c2b645ba33a98f0359bc9d30bbef89920.diff

LOG: Always allow std::function to be copied.

Since its call operator is const but can modify the state of its underlying
functor we cannot tell whether the copy is necessary or not.

This avoids false positives.

Reviewed-by: aaron.ballman, gribozavr2

Differential Revision: https://reviews.llvm.org/D89332

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 03b4450d8ca8..24847d80657c 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -63,8 +63,10 @@ void 
UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) {
declStmt(
has(varDecl(hasLocalStorage(),
hasType(qualType(
-   hasCanonicalType(
-   matchers::isExpensiveToCopy()),
+   hasCanonicalType(allOf(
+   matchers::isExpensiveToCopy(),
+   unless(hasDeclaration(namedDecl(
+   hasName("::std::function")),
unless(hasDeclaration(namedDecl(
matchers::matchesAnyListedName(
AllowedTypes)),

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
index 7a70bc18a28c..9055529c7a3f 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -405,3 +405,58 @@ void negativeInitialzedFromFreeFunctionWithNonDefaultArg() 
{
   ExpensiveToCopyType Orig;
   const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg(&Orig);
 }
+
+namespace std {
+inline namespace __1 {
+
+template 
+class function;
+template 
+class function {
+public:
+  function();
+  function(const function &other);
+  R operator()(Args &&...args) const;
+};
+
+} // namespace __1
+} // namespace std
+
+void negativeStdFunction() {
+  std::function Orig;
+  std::function Copy = Orig;
+  int i = Orig();
+}
+
+using Functor = std::function;
+
+void negativeAliasedStdFunction() {
+  Functor Orig;
+  Functor Copy = Orig;
+  int i = Orig();
+}
+
+typedef std::function TypedefFunc;
+
+void negativeTypedefedStdFunction() {
+  TypedefFunc Orig;
+  TypedefFunc Copy = Orig;
+  int i = Orig();
+}
+
+namespace fake {
+namespace std {
+template 
+struct function {
+  // Custom copy constructor makes it expensive to copy;
+  function(const function &);
+};
+} // namespace std
+
+void positiveFakeStdFunction(std::function F) {
+  auto Copy = F;
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: local copy 'Copy' of the variable 
'F' is never modified;
+  // CHECK-FIXES: const auto& Copy = F;
+}
+
+} // namespace fake



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] 5dbe3bf - [clang-tidy] performance-unnecessary-copy-initialization: Remove the complete statement when the copied variable is unused.

2021-06-09 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-06-09T15:52:48-04:00
New Revision: 5dbe3bf4b8dbb7e67d41c7c1360f15d512dd72a0

URL: 
https://github.com/llvm/llvm-project/commit/5dbe3bf4b8dbb7e67d41c7c1360f15d512dd72a0
DIFF: 
https://github.com/llvm/llvm-project/commit/5dbe3bf4b8dbb7e67d41c7c1360f15d512dd72a0.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Remove the 
complete statement when the copied variable is unused.

It is not useful to keep the statement around and can lead to compiler
warnings when -Wall (-Wunused-variable specifically) turned on.

Differential Revision: https://reviews.llvm.org/D102175

Reviewed-by: ymandel

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-allowed-types.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 0cc9a44263021..57a2310e779fb 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -7,9 +7,9 @@
 
//===--===//
 
 #include "UnnecessaryCopyInitialization.h"
-
 #include "../utils/DeclRefExprUtils.h"
 #include "../utils/FixItHintUtils.h"
+#include "../utils/LexerUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Basic/Diagnostic.h"
@@ -21,6 +21,7 @@ namespace {
 
 using namespace ::clang::ast_matchers;
 using llvm::StringRef;
+using utils::decl_ref_expr::allDeclRefExprs;
 using utils::decl_ref_expr::isOnlyUsedAsConst;
 
 static constexpr StringRef ObjectArgId = "objectArg";
@@ -37,6 +38,19 @@ void recordFixes(const VarDecl &Var, ASTContext &Context,
   }
 }
 
+void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
+   DiagnosticBuilder &Diagnostic) {
+  // Attempt to remove the whole line until the next non-comment token.
+  auto Tok = utils::lexer::findNextTokenSkippingComments(
+  Stmt.getEndLoc(), Context.getSourceManager(), Context.getLangOpts());
+  if (Tok) {
+Diagnostic << FixItHint::CreateRemoval(SourceRange(
+Stmt.getBeginLoc(), Tok->getLocation().getLocWithOffset(-1)));
+  } else {
+Diagnostic << FixItHint::CreateRemoval(Stmt.getSourceRange());
+  }
+}
+
 AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningMethodCall) {
   // Match method call expressions where the `this` argument is only used as
   // const, this will be checked in `check()` part. This returned const
@@ -118,6 +132,11 @@ static bool isInitializingVariableImmutable(const VarDecl 
&InitializingVar,
   return false;
 }
 
+bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
+  ASTContext &Context) {
+  return allDeclRefExprs(Var, BlockStmt, Context).empty();
+}
+
 } // namespace
 
 UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
@@ -169,14 +188,13 @@ void UnnecessaryCopyInitialization::check(
   const auto *ObjectArg = Result.Nodes.getNodeAs(ObjectArgId);
   const auto *BlockStmt = Result.Nodes.getNodeAs("blockStmt");
   const auto *CtorCall = Result.Nodes.getNodeAs("ctorCall");
+  const auto *Stmt = Result.Nodes.getNodeAs("declStmt");
 
   TraversalKindScope RAII(*Result.Context, TK_AsIs);
 
   // Do not propose fixes if the DeclStmt has multiple VarDecls or in macros
   // since we cannot place them correctly.
-  bool IssueFix =
-  Result.Nodes.getNodeAs("declStmt")->isSingleDecl() &&
-  !NewVar->getLocation().isMacroID();
+  bool IssueFix = Stmt->isSingleDecl() && !NewVar->getLocation().isMacroID();
 
   // A constructor that looks like T(const T& t, bool arg = false) counts as a
   // copy only when it is called with default arguments for the arguments after
@@ -186,47 +204,68 @@ void UnnecessaryCopyInitialization::check(
   return;
 
   if (OldVar == nullptr) {
-handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, ObjectArg,
+handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg,
*Result.Context);
   } else {
-handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, IssueFix,
+handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
*Result.Context);
   }
 }
 
 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
-const VarDecl &Var, const Stmt &BlockStmt, bool IssueFix,
-const VarDecl *ObjectArg, ASTContext &Context) {
+const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
+ 

[clang-tools-extra] efa4dbc - [clang-tidy] performance-unnecessary-copy-initialization: Look at the canonical type when checking for aliases.

2021-06-09 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-06-09T16:36:53-04:00
New Revision: efa4dbc32ca9b7f3319edbcc6ac502ea962c8f0a

URL: 
https://github.com/llvm/llvm-project/commit/efa4dbc32ca9b7f3319edbcc6ac502ea962c8f0a
DIFF: 
https://github.com/llvm/llvm-project/commit/efa4dbc32ca9b7f3319edbcc6ac502ea962c8f0a.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Look at the 
canonical type when checking for aliases.

This fixes a false positive case where for instance a pointer is obtained and 
declared using `auto`.

Differential Revision: https://reviews.llvm.org/D103018

Reviewed-by: ymandel

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 57a2310e779fb..27ce36e49a073 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -100,7 +100,7 @@ static bool isInitializingVariableImmutable(const VarDecl 
&InitializingVar,
   if (!isOnlyUsedAsConst(InitializingVar, BlockStmt, Context))
 return false;
 
-  QualType T = InitializingVar.getType();
+  QualType T = InitializingVar.getType().getCanonicalType();
   // The variable is a value type and we know it is only used as const. Safe
   // to reference it and avoid the copy.
   if (!isa(T))

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
index 3a4c3ec869e1c..e894f84f11d8c 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -4,6 +4,7 @@ struct ExpensiveToCopyType {
   ExpensiveToCopyType();
   virtual ~ExpensiveToCopyType();
   const ExpensiveToCopyType &reference() const;
+  const ExpensiveToCopyType *pointer() const;
   void nonConstMethod();
   bool constMethod() const;
 };
@@ -548,6 +549,25 @@ void negativeCopiedFromGetterOfReferenceToModifiedVar() {
   Orig.nonConstMethod();
 }
 
+void negativeAliasNonCanonicalPointerType() {
+  ExpensiveToCopyType Orig;
+  // The use of auto here hides that the type is a pointer type. The check 
needs
+  // to look at the canonical type to detect the aliasing through this pointer.
+  const auto Pointer = Orig.pointer();
+  const auto NecessaryCopy = Pointer->reference();
+  Orig.nonConstMethod();
+}
+
+void negativeAliasTypedefedType() {
+  typedef const ExpensiveToCopyType &ReferenceType;
+  ExpensiveToCopyType Orig;
+  // The typedef hides the fact that this is a reference type. The check needs
+  // to look at the canonical type to detect the aliasing.
+  ReferenceType Ref = Orig.reference();
+  const auto NecessaryCopy = Ref.reference();
+  Orig.nonConstMethod();
+}
+
 void positiveCopiedFromGetterOfReferenceToConstVar() {
   ExpensiveToCopyType Orig;
   const auto &Ref = Orig.reference();



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] bdd5da9 - [clang-tidy] performance-unnecessary-copy-initialization: Directly examine the initializing var's initializer.

2021-06-18 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-06-18T15:25:17-04:00
New Revision: bdd5da9dec61072f693726d9ed2a94c78e431ba2

URL: 
https://github.com/llvm/llvm-project/commit/bdd5da9dec61072f693726d9ed2a94c78e431ba2
DIFF: 
https://github.com/llvm/llvm-project/commit/bdd5da9dec61072f693726d9ed2a94c78e431ba2.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Directly examine 
the initializing var's initializer.

This fixes false positive cases where a reference is initialized outside of a
block statement and then its initializing variable is modified. Another case is
when the looped over container is modified.

Differential Revision: https://reviews.llvm.org/D103021

Reviewed-by: ymandel

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 27ce36e49a073..f75a3a901ecd5 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -12,6 +12,7 @@
 #include "../utils/LexerUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
+#include "clang/AST/Decl.h"
 #include "clang/Basic/Diagnostic.h"
 
 namespace clang {
@@ -72,14 +73,14 @@ AST_MATCHER_FUNCTION(StatementMatcher, 
isConstRefReturningFunctionCall) {
   .bind(InitFunctionCallId);
 }
 
-AST_MATCHER_FUNCTION(StatementMatcher, isInitializedFromReferenceToConst) {
+AST_MATCHER_FUNCTION(StatementMatcher, initializerReturnsReferenceToConst) {
   auto OldVarDeclRef =
   declRefExpr(to(varDecl(hasLocalStorage()).bind(OldVarDeclId)));
-  return declStmt(has(varDecl(hasInitializer(
+  return expr(
   anyOf(isConstRefReturningFunctionCall(), isConstRefReturningMethodCall(),
 ignoringImpCasts(OldVarDeclRef),
-ignoringImpCasts(unaryOperator(
-hasOperatorName("&"), hasUnaryOperand(OldVarDeclRef;
+ignoringImpCasts(unaryOperator(hasOperatorName("&"),
+   hasUnaryOperand(OldVarDeclRef);
 }
 
 // This checks that the variable itself is only used as const, and also makes
@@ -106,18 +107,14 @@ static bool isInitializingVariableImmutable(const VarDecl 
&InitializingVar,
   if (!isa(T))
 return true;
 
-  auto Matches =
-  match(findAll(declStmt(has(varDecl(equalsNode(&InitializingVar
-.bind("declStmt")),
-BlockStmt, Context);
-  // The reference or pointer is not initialized in the BlockStmt. We assume
-  // its pointee is not modified then.
-  if (Matches.empty())
+  // The reference or pointer is not declared and hence not initialized 
anywhere
+  // in the function. We assume its pointee is not modified then.
+  if (!InitializingVar.isLocalVarDecl() || !InitializingVar.hasInit()) {
 return true;
+  }
 
-  const auto *Initialization = selectFirst("declStmt", Matches);
-  Matches =
-  match(isInitializedFromReferenceToConst(), *Initialization, Context);
+  auto Matches = match(initializerReturnsReferenceToConst(),
+   *InitializingVar.getInit(), Context);
   // The reference is initialized from a free function without arguments
   // returning a const reference. This is a global immutable object.
   if (selectFirst(InitFunctionCallId, Matches) != nullptr)

diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
index 8193672218932..c11be2d8885d6 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -10,6 +10,7 @@
 #define 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_UNNECESSARY_COPY_INITIALIZATION_H
 
 #include "../ClangTidyCheck.h"
+#include "clang/AST/Decl.h"
 
 namespace clang {
 namespace tidy {

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
index e894f84f11d8c..c2b3d8f9c7395 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -1,10 +1,20 @@
 // RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
 
+template 
+struct Iterator {
+  void operator++();
+  const T &operator*() const;
+  bool operator!=(const Iterator &) const

[clang-tools-extra] 187e050 - [clang-tidy] performance-unnecessary-copy-initialization: Disable structured bindings.

2021-07-12 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-07-12T09:55:27-04:00
New Revision: 187e050b33bbee1ef210c83f5595c283ba671909

URL: 
https://github.com/llvm/llvm-project/commit/187e050b33bbee1ef210c83f5595c283ba671909
DIFF: 
https://github.com/llvm/llvm-project/commit/187e050b33bbee1ef210c83f5595c283ba671909.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Disable 
structured bindings.

Structured bindings can currently trigger the check and lead to a wrong
fix. Because the DecompositionDecl itself is not used and the check does not
iterate through its the decl's bindings to verify whether the bindings' holding
vars are used this leads to the whole statement to be deleted.

To support structured bindings properly 3 cases would need to be considered.

  1. All holding vars are not used -> The statement can be deleted.
  2. All holding vars are used as const or not used -> auto can be converted to 
const auto&.
  3. Neither case is true -> leave unchanged.

In the check we'll have to separate the logic that determines this from the code
that produces the diagnostic and fixes and first determine which of the cases
we're dealing with before creating fixes.

Since this is a bigger refactoring we'll disable structured bindings for now to
prevent incorrect fixes.

Differential Revision: https://reviews.llvm.org/D105727

Reviewed-by: ymandel

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index f75a3a901ecd5..f69a2079e4ba1 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -147,6 +147,7 @@ void 
UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) {
 return compoundStmt(
forEachDescendant(
declStmt(
+   unless(has(decompositionDecl())),
has(varDecl(hasLocalStorage(),
hasType(qualType(
hasCanonicalType(allOf(

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
index c2b3d8f9c7395..b66a88e5cf81f 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
+// RUN: %check_clang_tidy -std=c++17 %s 
performance-unnecessary-copy-initialization %t
 
 template 
 struct Iterator {
@@ -637,3 +637,18 @@ void negativeReferenceIsInitializedOutsideOfBlock() {
 }
   };
 }
+
+void negativeStructuredBinding() {
+  // Structured bindings are not yet supported but can trigger false positives
+  // since the DecompositionDecl itself is unused and the check doesn't 
traverse
+  // VarDecls of the BindingDecls.
+  struct Pair {
+ExpensiveToCopyType first;
+ExpensiveToCopyType second;
+  };
+
+  Pair P;
+  const auto [C, D] = P;
+  C.constMethod();
+  D.constMethod();
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] 0ec8120 - [clang-tidy] performance-unnecessary-copy-initialization: Do not remove comments on new lines.

2021-07-12 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-07-12T16:23:04-04:00
New Revision: 0ec812023b43992810499b04222348fdbdb41ef2

URL: 
https://github.com/llvm/llvm-project/commit/0ec812023b43992810499b04222348fdbdb41ef2
DIFF: 
https://github.com/llvm/llvm-project/commit/0ec812023b43992810499b04222348fdbdb41ef2.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Do not remove 
comments on new lines.

When deleting the copy assignment statement because copied variable is not used
only remove trailing comments on the same line.

Differential Revision: https://reviews.llvm.org/D105734

Reviewed-by: ymandel

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index f69a2079e4ba1..f6b8e44785b5f 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -39,14 +39,35 @@ void recordFixes(const VarDecl &Var, ASTContext &Context,
   }
 }
 
+llvm::Optional firstLocAfterNewLine(SourceLocation Loc,
+SourceManager &SM) {
+  bool Invalid;
+  const char *TextAfter = SM.getCharacterData(Loc, &Invalid);
+  if (Invalid) {
+return llvm::None;
+  }
+  size_t Offset = std::strcspn(TextAfter, "\n");
+  return Loc.getLocWithOffset(TextAfter[Offset] == '\0' ? Offset : Offset + 1);
+}
+
 void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
-  // Attempt to remove the whole line until the next non-comment token.
-  auto Tok = utils::lexer::findNextTokenSkippingComments(
-  Stmt.getEndLoc(), Context.getSourceManager(), Context.getLangOpts());
-  if (Tok) {
-Diagnostic << FixItHint::CreateRemoval(SourceRange(
-Stmt.getBeginLoc(), Tok->getLocation().getLocWithOffset(-1)));
+  auto &SM = Context.getSourceManager();
+  // Attempt to remove trailing comments as well.
+  auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM,
+ 
Context.getLangOpts());
+  llvm::Optional PastNewLine =
+  firstLocAfterNewLine(Stmt.getEndLoc(), SM);
+  if (Tok && PastNewLine) {
+auto BeforeFirstTokenAfterComment = 
Tok->getLocation().getLocWithOffset(-1);
+// Remove until the end of the line or the end of a trailing comment which
+// ever comes first.
+auto End =
+SM.isBeforeInTranslationUnit(*PastNewLine, 
BeforeFirstTokenAfterComment)
+? *PastNewLine
+: BeforeFirstTokenAfterComment;
+Diagnostic << FixItHint::CreateRemoval(
+SourceRange(Stmt.getBeginLoc(), End));
   } else {
 Diagnostic << FixItHint::CreateRemoval(Stmt.getSourceRange());
   }

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
index b66a88e5cf81f..3ce151035d5be 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -596,8 +596,15 @@ void positiveUnusedReferenceIsRemoved() {
   // CHECK-FIXES: int i = 0; // Foo bar.
   auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment.
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 
'TrailingCommentRemoved' is copy-constructed from a const reference but is 
never used;
-  // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference(); 
// Trailing comment.
+  // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference();
+  // CHECK-FIXES-NOT: // Trailing comment.
   // clang-format on
+
+  auto UnusedAndUnnecessary = ExpensiveTypeReference();
+  // Comments on a new line should not be deleted.
+  // CHECK-MESSAGES: [[@LINE-2]]:8: warning: the variable 
'UnusedAndUnnecessary' is copy-constructed
+  // CHECK-FIXES-NOT: auto UnusedAndUnnecessary = ExpensiveTypeReference();
+  // CHECK-FIXES: // Comments on a new line should not be deleted.
 }
 
 void negativeloopedOverObjectIsModified() {



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] a189b3b - [clang-tidy] performance-for-range-copy: Don't trigger on implicit type conversions.

2021-03-02 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-03-02T20:02:48-05:00
New Revision: a189b3b9e8bb398d9fe8770956f8ad1d58c2a214

URL: 
https://github.com/llvm/llvm-project/commit/a189b3b9e8bb398d9fe8770956f8ad1d58c2a214
DIFF: 
https://github.com/llvm/llvm-project/commit/a189b3b9e8bb398d9fe8770956f8ad1d58c2a214.diff

LOG: [clang-tidy] performance-for-range-copy: Don't trigger on implicit type 
conversions.

This disables the check for false positive cases where implicit type conversion
through either an implicit single argument constructor or a member conversion
operator is triggered when constructing the loop variable.

Fix the test cases that meant to cover these cases.

Differential Revision: https://reviews.llvm.org/D97577

Reviewed-by: hokein

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp
clang-tools-extra/test/clang-tidy/checkers/performance-for-range-copy.cpp

Removed: 




diff  --git a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp
index 4b7a34f6c40f..8046301e3ce7 100644
--- a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -45,10 +45,14 @@ void ForRangeCopyCheck::registerMatchers(MatchFinder 
*Finder) {
   hasOverloadedOperatorName("*"),
   callee(
   cxxMethodDecl(returns(unless(hasCanonicalType(referenceType()));
+  auto NotConstructedByCopy = cxxConstructExpr(
+  hasDeclaration(cxxConstructorDecl(unless(isCopyConstructor();
+  auto ConstructedByConversion = 
cxxMemberCallExpr(callee(cxxConversionDecl()));
   auto LoopVar =
   varDecl(HasReferenceOrPointerTypeOrIsAllowed,
-  unless(hasInitializer(expr(hasDescendant(expr(anyOf(
-  materializeTemporaryExpr(), IteratorReturnsValueType)));
+  unless(hasInitializer(expr(hasDescendant(expr(
+  anyOf(materializeTemporaryExpr(), IteratorReturnsValueType,
+NotConstructedByCopy, ConstructedByConversion)));
   Finder->addMatcher(
   traverse(TK_AsIs,
cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar")))

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-for-range-copy.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/performance-for-range-copy.cpp
index e22650e10198..07b5116dfb14 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/performance-for-range-copy.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance-for-range-copy.cpp
@@ -60,13 +60,13 @@ void negativeConstReference() {
 
 void negativeUserDefinedConversion() {
   Convertible C[0];
-  for (const S &S1 : C) {
+  for (const S S1 : C) {
   }
 }
 
 void negativeImplicitConstructorConversion() {
   ConstructorConvertible C[0];
-  for (const S &S1 : C) {
+  for (const S S1 : C) {
   }
 }
 



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] fefe20b - [clang-tidy] performance-unnecessary-copy-initialization: Correctly match the type name of the thisPointertype.

2021-11-20 Thread Felix Berger via cfe-commits

Author: Felix Berger
Date: 2021-11-20T15:13:41-05:00
New Revision: fefe20b99313d6b0738806d1504652c3b7edb9e0

URL: 
https://github.com/llvm/llvm-project/commit/fefe20b99313d6b0738806d1504652c3b7edb9e0
DIFF: 
https://github.com/llvm/llvm-project/commit/fefe20b99313d6b0738806d1504652c3b7edb9e0.diff

LOG: [clang-tidy] performance-unnecessary-copy-initialization: Correctly match 
the type name of the thisPointertype.

The matching did not work correctly for pointer and reference types.

Differential Revision: https://reviews.llvm.org/D114212

Reviewed-by: courbet

Added: 


Modified: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-excluded-container-types.cpp

Removed: 




diff  --git 
a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp 
b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 2cdd7827ee42..514ce6f6e3b8 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -87,11 +87,9 @@ AST_MATCHER_FUNCTION_P(StatementMatcher, 
isConstRefReturningMethodCall,
   callee(cxxMethodDecl(
  returns(hasCanonicalType(matchers::isReferenceToConst(
  .bind(MethodDeclId)),
-  on(declRefExpr(to(
-  varDecl(
-  
unless(hasType(qualType(hasCanonicalType(hasDeclaration(namedDecl(
-  matchers::matchesAnyListedName(ExcludedContainerTypes
-  .bind(ObjectArgId);
+  on(declRefExpr(to(varDecl().bind(ObjectArgId,
+  thisPointerType(namedDecl(
+  unless(matchers::matchesAnyListedName(ExcludedContainerTypes);
 }
 
 AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningFunctionCall) {

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-excluded-container-types.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-excluded-container-types.cpp
index 6d1d28ad1498..88b850fe2ff8 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-excluded-container-types.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization-excluded-container-types.cpp
@@ -58,3 +58,13 @@ void excludedConstIncorrectType() {
   const auto E = C.secretlyMutates();
   E.constMethod();
 }
+
+void excludedConstIncorrectTypeAsPointer(ConstInCorrectType *C) {
+  const auto E = C->secretlyMutates();
+  E.constMethod();
+}
+
+void excludedConstIncorrectTypeAsReference(const ConstInCorrectType &C) {
+  const auto E = C.secretlyMutates();
+  E.constMethod();
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r289912 - [clang-tidy] Do not move parameter if only DeclRefExpr occurs inside of a loop

2016-12-15 Thread Felix Berger via cfe-commits
Author: flx
Date: Thu Dec 15 20:47:56 2016
New Revision: 289912

URL: http://llvm.org/viewvc/llvm-project?rev=289912&view=rev
Log:
[clang-tidy] Do not move parameter if only DeclRefExpr occurs inside of a loop

Summary: This fixes a bug where the performance-unnecessary-value-param check 
suggests a fix to move the parameter inside of a loop which could be invoked 
multiple times.

Reviewers: sbenza, aaron.ballman, alexfh

Subscribers: JDevlieghere, cfe-commits

Differential Revision: https://reviews.llvm.org/D27187

Modified:

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=289912&r1=289911&r2=289912&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
Thu Dec 15 20:47:56 2016
@@ -47,6 +47,17 @@ bool isReferencedOutsideOfCallExpr(const
   return !Matches.empty();
 }
 
+bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Stmt &Stmt,
+ ASTContext &Context) {
+  auto Matches =
+  match(findAll(declRefExpr(
+equalsNode(&DeclRef),
+unless(hasAncestor(stmt(anyOf(forStmt(), cxxForRangeStmt(),
+  whileStmt(), doStmt())),
+Stmt, Context);
+  return Matches.empty();
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@@ -105,6 +116,8 @@ void UnnecessaryValueParamCheck::check(c
   if (!IsConstQualified) {
 auto CanonicalType = Param->getType().getCanonicalType();
 if (AllDeclRefExprs.size() == 1 &&
+!hasLoopStmtAncestor(**AllDeclRefExprs.begin(), *Function->getBody(),
+ *Result.Context) &&
 ((utils::type_traits::hasNonTrivialMoveConstructor(CanonicalType) &&
   utils::decl_ref_expr::isCopyConstructorArgument(
   **AllDeclRefExprs.begin(), *Function->getBody(),

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=289912&r1=289911&r2=289912&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Thu Dec 15 20:47:56 2016
@@ -225,6 +225,15 @@ void PositiveMoveOnCopyAssignment(Expens
   // CHECK-FIXES: F = std::move(E);
 }
 
+// The argument could be moved but is not since copy statement is inside a 
loop.
+void PositiveNoMoveInsideLoop(ExpensiveMovableType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void PositiveNoMoveInsideLoop(const ExpensiveMovableType& E) 
{
+  for (;;) {
+auto F = E;
+  }
+}
+
 void PositiveConstRefNotMoveConstructible(ExpensiveToCopyType T) {
   // CHECK-MESSAGES: [[@LINE-1]]:63: warning: the parameter 'T' is copied
   // CHECK-FIXES: void PositiveConstRefNotMoveConstructible(const 
ExpensiveToCopyType& T) {


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r292491 - [clang-tidy] Do not trigger move fix for non-copy assignment operators in performance-unnecessary-value-param check

2017-01-19 Thread Felix Berger via cfe-commits
Author: flx
Date: Thu Jan 19 09:51:10 2017
New Revision: 292491

URL: http://llvm.org/viewvc/llvm-project?rev=292491&view=rev
Log:
[clang-tidy] Do not trigger move fix for non-copy assignment operators in 
performance-unnecessary-value-param check

Reviewers: alexfh, sbenza, malcolm.parsons

Subscribers: JDevlieghere, cfe-commits

Differential Revision: https://reviews.llvm.org/D28899

Modified:
clang-tools-extra/trunk/clang-tidy/utils/DeclRefExprUtils.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: clang-tools-extra/trunk/clang-tidy/utils/DeclRefExprUtils.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/DeclRefExprUtils.cpp?rev=292491&r1=292490&r2=292491&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/utils/DeclRefExprUtils.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/utils/DeclRefExprUtils.cpp Thu Jan 19 
09:51:10 2017
@@ -159,7 +159,8 @@ bool isCopyAssignmentArgument(const Decl
   parmVarDecl(hasType(matchers::isReferenceToConst(;
   auto Matches = match(
   decl(hasDescendant(
-  cxxOperatorCallExpr(UsedAsConstRefArg, 
hasOverloadedOperatorName("="))
+  cxxOperatorCallExpr(UsedAsConstRefArg, 
hasOverloadedOperatorName("="),
+  
callee(cxxMethodDecl(isCopyAssignmentOperator(
   .bind("operatorCallExpr"))),
   Decl, Context);
   return !Matches.empty();

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=292491&r1=292490&r2=292491&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Thu Jan 19 09:51:10 2017
@@ -247,6 +247,17 @@ void PositiveMoveOnCopyAssignment(Expens
   // CHECK-FIXES: F = std::move(E);
 }
 
+struct NotCopyAssigned {
+  NotCopyAssigned &operator=(const ExpensiveMovableType &);
+};
+
+void PositiveNoMoveForNonCopyAssigmentOperator(ExpensiveMovableType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:69: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void PositiveNoMoveForNonCopyAssigmentOperator(const 
ExpensiveMovableType& E) {
+  NotCopyAssigned N;
+  N = E;
+}
+
 // The argument could be moved but is not since copy statement is inside a 
loop.
 void PositiveNoMoveInsideLoop(ExpensiveMovableType E) {
   // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' is copied


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r309067 - [clang-tidy] Do not issue fixit for explicit template specializations

2017-07-25 Thread Felix Berger via cfe-commits
Author: flx
Date: Tue Jul 25 17:45:41 2017
New Revision: 309067

URL: http://llvm.org/viewvc/llvm-project?rev=309067&view=rev
Log:
[clang-tidy] Do not issue fixit for explicit template specializations

Summary:

Do not issue fixit in UnnecessaryValueParamCheck if the function is an explicit 
template specialization as this could cause build breakages.

Reviewers: alexfh

Subscribers: JDevlieghere, xazax.hun, cfe-commits

Differential Revision: https://reviews.llvm.org/D35718

Modified:

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=309067&r1=309066&r2=309067&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
Tue Jul 25 17:45:41 2017
@@ -58,6 +58,18 @@ bool hasLoopStmtAncestor(const DeclRefEx
   return Matches.empty();
 }
 
+bool isExplicitTemplateSpecialization(const FunctionDecl &Function) {
+  if (const auto *SpecializationInfo = 
Function.getTemplateSpecializationInfo())
+if (SpecializationInfo->getTemplateSpecializationKind() ==
+TSK_ExplicitSpecialization)
+  return true;
+  if (const auto *Method = llvm::dyn_cast(&Function))
+if (Method->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization &&
+Method->getMemberSpecializationInfo()->isExplicitSpecialization())
+  return true;
+  return false;
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@@ -133,9 +145,11 @@ void UnnecessaryValueParamCheck::check(c
   // 2. the function is virtual as it might break overrides
   // 3. the function is referenced outside of a call expression within the
   //compilation unit as the signature change could introduce build errors.
+  // 4. the function is an explicit template specialization.
   const auto *Method = llvm::dyn_cast(Function);
   if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
-  isReferencedOutsideOfCallExpr(*Function, *Result.Context))
+  isReferencedOutsideOfCallExpr(*Function, *Result.Context) ||
+  isExplicitTemplateSpecialization(*Function))
 return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
FunctionDecl = FunctionDecl->getPreviousDecl()) {

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=309067&r1=309066&r2=309067&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Tue Jul 25 17:45:41 2017
@@ -348,3 +348,14 @@ void fun() {
   ExpensiveToCopyType E;
   NegativeUsingConstructor S(E);
 }
+
+template
+void templateFunction(T) {
+}
+
+template<>
+void templateFunction(ExpensiveToCopyType E) {
+  // CHECK-MESSAGES: [[@LINE-1]]:64: warning: the parameter 'E' is copied
+  // CHECK-FIXES: void 
templateFunction(ExpensiveToCopyType E) {
+  E.constReference();
+}


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r288502 - [clang-tidy] Do not trigger unnecessary-value-param check on methods marked as final

2016-12-02 Thread Felix Berger via cfe-commits
Author: flx
Date: Fri Dec  2 08:44:16 2016
New Revision: 288502

URL: http://llvm.org/viewvc/llvm-project?rev=288502&view=rev
Log:
[clang-tidy] Do not trigger unnecessary-value-param check on methods marked as 
final

Summary: Virtual method overrides of dependent types cannot be recognized unless
they are marked as override or final.

Exclude methods marked as final from check and add test.

Reviewers: sbenza, hokein, alexfh

Subscribers: malcolm.parsons, JDevlieghere, cfe-commits

Differential Revision: https://reviews.llvm.org/D27248

Modified:

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=288502&r1=288501&r2=288502&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
Fri Dec  2 08:44:16 2016
@@ -61,7 +61,8 @@ void UnnecessaryValueParamCheck::registe
  unless(referenceType(),
   decl().bind("param"));
   Finder->addMatcher(
-  functionDecl(isDefinition(), unless(cxxMethodDecl(isOverride())),
+  functionDecl(isDefinition(),
+   unless(cxxMethodDecl(anyOf(isOverride(), isFinal(,
unless(isInstantiated()),
has(typeLoc(forEach(ExpensiveValueParamDecl))),
decl().bind("functionDecl")),

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=288502&r1=288501&r2=288502&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Fri Dec  2 08:44:16 2016
@@ -271,3 +271,21 @@ void PositiveMessageAndFixAsFunctionIsCa
 void ReferenceFunctionByCallingIt() {
   PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
 }
+
+// Virtual method overrides of dependent types cannot be recognized unless they
+// are marked as override or final. Test that check is not triggered on methods
+// marked with override or final.
+template 
+struct NegativeDependentTypeInterface {
+  virtual void Method(ExpensiveToCopyType E) = 0;
+};
+
+template 
+struct NegativeOverrideImpl : public NegativeDependentTypeInterface {
+  void Method(ExpensiveToCopyType E) override {}
+};
+
+template 
+struct NegativeFinalImpl : public NegativeDependentTypeInterface {
+  void Method(ExpensiveToCopyType E) final {}
+};


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-01 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a reviewer: alexfh.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

IsExpensiveToCopy can return false positives for incomplete types, so ignore 
them.

All existing ClangTidy tests that depend on this function still pass as the 
types are complete.


Repository:
  rL LLVM

https://reviews.llvm.org/D26195

Files:
  clang-tidy/utils/TypeTraits.cpp


Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&


Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-01 Thread Felix Berger via cfe-commits
flx added a comment.

In https://reviews.llvm.org/D26195#584712, @aaron.ballman wrote:

> Please add a test case with an incomplete type that would exercise this code 
> path, otherwise, LGTM.


Hi Aaron,

do you have any advise on how to add an incomplete type? When debugging this I 
had a compilation unit that failed to compile causing it, but I'm not sure this 
is a good way to add a test case.


Repository:
  rL LLVM

https://reviews.llvm.org/D26195



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26203: [ClangTidy - performance-unnecessary-value-param]: Do not issue fix for functions that are referenced outside of callExpr

2016-11-01 Thread Felix Berger via cfe-commits
flx created this revision.
flx added reviewers: alexfh, sbenza.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Suppress fixes for functions that are referenced within the compilation unit 
outside of a call expression as the signature change could break the code 
referencing the function.

We still issue a warning in this case so that users can decide to manually 
change the function signature.


Repository:
  rL LLVM

https://reviews.llvm.org/D26203

Files:
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,21 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void 
PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = 
&PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const 
ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -39,6 +39,14 @@
   return true;
 }
 
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+   ASTContext &Context) {
+  auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
+   unless(hasAncestor(callExpr(,
+   Context);
+  return !Matches.empty();
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@@ -118,10 +126,14 @@
   "invocation but only used as a const reference; "
   "consider making it a const reference")
   << paramNameOrIndex(Param->getName(), Index);
-  // Do not propose fixes in macros since we cannot place them correctly, or if
-  // function is virtual as it might break overrides.
+  // Do not propose fixes when:
+  // 1. in macros since we cannot place them correctly
+  // 2. the function is virtual as it might break overrides
+  // 3. the function is referenced outside of a call expression within the
+  //compilation unit as the signature change could introduce build errors.
   const auto *Method = llvm::dyn_cast(Function);
-  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()))
+  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
+  isReferencedOutsideOfCallExpr(*Function, *Result.Context))
 return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
FunctionDecl = FunctionDecl->getPreviousDecl()) {


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,21 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -39,6 +39,14 @@
   return true;
 }
 
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+   ASTContext &Context) {
+  auto Matches = match(declRefExpr(to(functionDec

[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-01 Thread Felix Berger via cfe-commits
flx added a comment.

In https://reviews.llvm.org/D26195#584730, @aaron.ballman wrote:

> In https://reviews.llvm.org/D26195#584724, @flx wrote:
>
> > In https://reviews.llvm.org/D26195#584712, @aaron.ballman wrote:
> >
> > > Please add a test case with an incomplete type that would exercise this 
> > > code path, otherwise, LGTM.
> >
> >
> > Hi Aaron,
> >
> > do you have any advise on how to add an incomplete type? When debugging 
> > this I had a compilation unit that failed to compile causing it, but I'm 
> > not sure this is a good way to add a test case.
>
>
> A type like `class C;` is an incomplete type, as is `void`, so perhaps you 
> can find a check that would let such a construct call through to 
> `isExpensiveToCopy()`.


Great, this works and I was able to see the check produce a false positive 
without the proposed change here, but the test code introduces a compile error 
now due to the incomplete type used in the function definition. Is there a way 
to suppress that?


Repository:
  rL LLVM

https://reviews.llvm.org/D26195



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-01 Thread Felix Berger via cfe-commits
flx created this revision.
flx added reviewers: alexfh, sbenza, aaron.ballman.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Repository:
  rL LLVM

https://reviews.llvm.org/D26207

Files:
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,12 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,8 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+if (!IsConstQualified &&
+!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,12 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,8 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+if (!IsConstQualified &&
+!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-01 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 76630.

Repository:
  rL LLVM

https://reviews.llvm.org/D26207

Files:
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,19 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,7 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,19 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,7 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-01 Thread Felix Berger via cfe-commits
flx added inline comments.



Comment at: test/clang-tidy/performance-unnecessary-value-param.cpp:242
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);

aaron.ballman wrote:
> This comment doesn't really match the test cases. The original code has two 
> *different* declarations (only one of which is a definition), not one 
> declaration and one redeclaration with the definition.
> 
> I think what is really happening is that it is adding the `&` qualifier to 
> the first declaration, and adding the `const` and `&` qualifiers to the 
> second declaration, and the result is that you get harmonization. But it 
> brings up a question to me; what happens with:
> ```
> void f1(ExpensiveToCopyType A) {
> }
> 
> void f1(const ExpensiveToCopyType A) {
> 
> }
> ```
> Does the fix-it try to create two definitions of the same function?
Good catch. I added the reverse case as well and modified the check slightly to 
make that case work as well.



Comment at: test/clang-tidy/performance-unnecessary-value-param.cpp:244
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {

aaron.ballman wrote:
> Is the `CHECK-MESSAGES` missing?
The message is only generated on the definition below, the declaration will 
only have a fix.


Repository:
  rL LLVM

https://reviews.llvm.org/D26207



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-01 Thread Felix Berger via cfe-commits
flx added a comment.

In https://reviews.llvm.org/D26195#585091, @aaron.ballman wrote:

> In https://reviews.llvm.org/D26195#584958, @flx wrote:
>
> > In https://reviews.llvm.org/D26195#584730, @aaron.ballman wrote:
> >
> > > In https://reviews.llvm.org/D26195#584724, @flx wrote:
> > >
> > > > In https://reviews.llvm.org/D26195#584712, @aaron.ballman wrote:
> > > >
> > > > > Please add a test case with an incomplete type that would exercise 
> > > > > this code path, otherwise, LGTM.
> > > >
> > > >
> > > > Hi Aaron,
> > > >
> > > > do you have any advise on how to add an incomplete type? When debugging 
> > > > this I had a compilation unit that failed to compile causing it, but 
> > > > I'm not sure this is a good way to add a test case.
> > >
> > >
> > > A type like `class C;` is an incomplete type, as is `void`, so perhaps 
> > > you can find a check that would let such a construct call through to 
> > > `isExpensiveToCopy()`.
> >
> >
> > Great, this works and I was able to see the check produce a false positive 
> > without the proposed change here, but the test code introduces a compile 
> > error now due to the incomplete type used in the function definition. Is 
> > there a way to suppress that?
>
>
> Unlikely -- fixing the compile error likely makes the type not expensive to 
> copy by using a pointer (or reference). This may be tricky to test because 
> the times when you would call `isExpensiveToCopy()` is with types that are 
> going to be logically required to be complete. I am not certain the compile 
> error is actually a problem though -- I would imagine your existing 
> false-positives (that you mentioned in the patch summary) are cases where 
> there is a compile error *and* a clang-tidy diagnostic, so the test may 
> simply be "check that there's only a compile error and no clang-tidy 
> diagnostic where there used to be a false-positive one."


That's exactly the case, my question here is how can I make the test succeed in 
the face of a compile error, i.e. by expecting the error as well?


Repository:
  rL LLVM

https://reviews.llvm.org/D26195



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-02 Thread Felix Berger via cfe-commits
flx added inline comments.



Comment at: test/clang-tidy/performance-unnecessary-value-param.cpp:242
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);

aaron.ballman wrote:
> flx wrote:
> > aaron.ballman wrote:
> > > This comment doesn't really match the test cases. The original code has 
> > > two *different* declarations (only one of which is a definition), not one 
> > > declaration and one redeclaration with the definition.
> > > 
> > > I think what is really happening is that it is adding the `&` qualifier 
> > > to the first declaration, and adding the `const` and `&` qualifiers to 
> > > the second declaration, and the result is that you get harmonization. But 
> > > it brings up a question to me; what happens with:
> > > ```
> > > void f1(ExpensiveToCopyType A) {
> > > }
> > > 
> > > void f1(const ExpensiveToCopyType A) {
> > > 
> > > }
> > > ```
> > > Does the fix-it try to create two definitions of the same function?
> > Good catch. I added the reverse case as well and modified the check 
> > slightly to make that case work as well.
> Can you add a test like this as well?
> ```
> void f1(ExpensiveToCopyType A); // Declared, not defined
> 
> void f1(const ExpensiveToCopyType A) {}
> void f1(const ExpensiveToCopyType &A) {}
> ```
> I'm trying to make sure this check does not suggest a fixit that breaks 
> existing code because of overload sets. I would expect a diagnostic for the 
> first two declarations, but no fixit suggestion for `void f1(const 
> ExpensiveToCopyType A)` because that would result in an ambiguous function 
> definition.
The current code suggests the following fixes:

-void f1(ExpensiveToCopyType A); // Declared, not defined
+void f1(const ExpensiveToCopyType& A); // Declared, not defined
 
-void f1(const ExpensiveToCopyType A) {}
+void f1(const ExpensiveToCopyType& A) {}
 void f1(const ExpensiveToCopyType &A) {}

and we get a warning message for the void f1(const ExpensiveToCopyType A) {}

I think the compiler sees "void f1(const ExpensiveToCopyType A) {}" as 
definition of "void f1(ExpensiveToCopyType A); // Declared, not defined" and 
thus both places get fixed.

Since the check is catching cases where the value argument is either modified 
or could be moved it and this is not the case here it is worth raising this 
issue of what looks like a very subtle difference in overrides.

My inclination is to leave this as is. What do you suggest we do?



Repository:
  rL LLVM

https://reviews.llvm.org/D26207



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-03 Thread Felix Berger via cfe-commits
flx marked an inline comment as done.
flx added inline comments.



Comment at: test/clang-tidy/performance-unnecessary-value-param.cpp:242
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);

aaron.ballman wrote:
> flx wrote:
> > aaron.ballman wrote:
> > > flx wrote:
> > > > aaron.ballman wrote:
> > > > > This comment doesn't really match the test cases. The original code 
> > > > > has two *different* declarations (only one of which is a definition), 
> > > > > not one declaration and one redeclaration with the definition.
> > > > > 
> > > > > I think what is really happening is that it is adding the `&` 
> > > > > qualifier to the first declaration, and adding the `const` and `&` 
> > > > > qualifiers to the second declaration, and the result is that you get 
> > > > > harmonization. But it brings up a question to me; what happens with:
> > > > > ```
> > > > > void f1(ExpensiveToCopyType A) {
> > > > > }
> > > > > 
> > > > > void f1(const ExpensiveToCopyType A) {
> > > > > 
> > > > > }
> > > > > ```
> > > > > Does the fix-it try to create two definitions of the same function?
> > > > Good catch. I added the reverse case as well and modified the check 
> > > > slightly to make that case work as well.
> > > Can you add a test like this as well?
> > > ```
> > > void f1(ExpensiveToCopyType A); // Declared, not defined
> > > 
> > > void f1(const ExpensiveToCopyType A) {}
> > > void f1(const ExpensiveToCopyType &A) {}
> > > ```
> > > I'm trying to make sure this check does not suggest a fixit that breaks 
> > > existing code because of overload sets. I would expect a diagnostic for 
> > > the first two declarations, but no fixit suggestion for `void f1(const 
> > > ExpensiveToCopyType A)` because that would result in an ambiguous 
> > > function definition.
> > The current code suggests the following fixes:
> > 
> > -void f1(ExpensiveToCopyType A); // Declared, not defined
> > +void f1(const ExpensiveToCopyType& A); // Declared, not defined
> >  
> > -void f1(const ExpensiveToCopyType A) {}
> > +void f1(const ExpensiveToCopyType& A) {}
> >  void f1(const ExpensiveToCopyType &A) {}
> > 
> > and we get a warning message for the void f1(const ExpensiveToCopyType A) {}
> > 
> > I think the compiler sees "void f1(const ExpensiveToCopyType A) {}" as 
> > definition of "void f1(ExpensiveToCopyType A); // Declared, not defined" 
> > and thus both places get fixed.
> > 
> > Since the check is catching cases where the value argument is either 
> > modified or could be moved it and this is not the case here it is worth 
> > raising this issue of what looks like a very subtle difference in overrides.
> > 
> > My inclination is to leave this as is. What do you suggest we do?
> > 
> I think this behavior isn't new with your changes, so we can leave it as is. 
> However, we should file a bug report about the bad behavior with overload 
> sets (and provide the example that's failing) so that we don't forget to come 
> back and fix the functionality.
Filed to track this: https://llvm.org/bugs/show_bug.cgi?id=30902 (


https://reviews.llvm.org/D26207



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-03 Thread Felix Berger via cfe-commits
flx removed rL LLVM as the repository for this revision.
flx updated this revision to Diff 76877.

https://reviews.llvm.org/D26207

Files:
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,19 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,10 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+// The parameter of each declaration needs to be checked individually as to
+// whether it is const or not as constness can differ between definition 
and
+// declaration.
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -237,3 +237,19 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
+}
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,10 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+// The parameter of each declaration needs to be checked individually as to
+// whether it is const or not as constness can differ between definition and
+// declaration.
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-04 Thread Felix Berger via cfe-commits
flx added a comment.

Aaron, do you have any other comments or does the patch look good to you?


https://reviews.llvm.org/D26207



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-04 Thread Felix Berger via cfe-commits
flx removed rL LLVM as the repository for this revision.
flx updated this revision to Diff 76928.

https://reviews.llvm.org/D26195

Files:
  clang-tidy/utils/TypeTraits.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,8 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,8 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-04 Thread Felix Berger via cfe-commits
flx added a comment.

In https://reviews.llvm.org/D26195#585917, @aaron.ballman wrote:

> In https://reviews.llvm.org/D26195#585198, @flx wrote:
>
> > In https://reviews.llvm.org/D26195#585091, @aaron.ballman wrote:
> >
> > > In https://reviews.llvm.org/D26195#584958, @flx wrote:
> > >
> > > > In https://reviews.llvm.org/D26195#584730, @aaron.ballman wrote:
> > > >
> > > > > In https://reviews.llvm.org/D26195#584724, @flx wrote:
> > > > >
> > > > > > In https://reviews.llvm.org/D26195#584712, @aaron.ballman wrote:
> > > > > >
> > > > > > > Please add a test case with an incomplete type that would 
> > > > > > > exercise this code path, otherwise, LGTM.
> > > > > >
> > > > > >
> > > > > > Hi Aaron,
> > > > > >
> > > > > > do you have any advise on how to add an incomplete type? When 
> > > > > > debugging this I had a compilation unit that failed to compile 
> > > > > > causing it, but I'm not sure this is a good way to add a test case.
> > > > >
> > > > >
> > > > > A type like `class C;` is an incomplete type, as is `void`, so 
> > > > > perhaps you can find a check that would let such a construct call 
> > > > > through to `isExpensiveToCopy()`.
> > > >
> > > >
> > > > Great, this works and I was able to see the check produce a false 
> > > > positive without the proposed change here, but the test code introduces 
> > > > a compile error now due to the incomplete type used in the function 
> > > > definition. Is there a way to suppress that?
> > >
> > >
> > > Unlikely -- fixing the compile error likely makes the type not expensive 
> > > to copy by using a pointer (or reference). This may be tricky to test 
> > > because the times when you would call `isExpensiveToCopy()` is with types 
> > > that are going to be logically required to be complete. I am not certain 
> > > the compile error is actually a problem though -- I would imagine your 
> > > existing false-positives (that you mentioned in the patch summary) are 
> > > cases where there is a compile error *and* a clang-tidy diagnostic, so 
> > > the test may simply be "check that there's only a compile error and no 
> > > clang-tidy diagnostic where there used to be a false-positive one."
> >
> >
> > That's exactly the case, my question here is how can I make the test 
> > succeed in the face of a compile error, i.e. by expecting the error as well?
>
>
> Doesn't `// CHECK-MESSAGES: :[[@LINE-1]]:3: error: blah blah blah` work?


Yes, that was needed. I also had to change the run command to add "-fix-errors" 
to still apply fixes in the face of compile errors. I also added you as 
reviewer, Aaron.


https://reviews.llvm.org/D26195



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-04 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 76934.

https://reviews.llvm.org/D26195

Files:
  clang-tidy/utils/TypeTraits.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,10 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,10 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r286008 - [clang-tidy] Ignore incomplete types when determining whether they are expensive to copy

2016-11-04 Thread Felix Berger via cfe-commits
Author: flx
Date: Fri Nov  4 15:29:22 2016
New Revision: 286008

URL: http://llvm.org/viewvc/llvm-project?rev=286008&view=rev
Log:
[clang-tidy] Ignore incomplete types when determining whether they are 
expensive to copy

Summary: IsExpensiveToCopy can return false positives for incomplete types, so 
ignore them.

All existing ClangTidy tests that depend on this function still pass as the 
types are complete.

Reviewers: alexfh, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D26195

Modified:
clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp?rev=286008&r1=286007&r2=286008&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp Fri Nov  4 15:29:22 
2016
@@ -41,7 +41,7 @@ bool hasDeletedCopyConstructor(QualType
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=286008&r1=286007&r2=286008&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Fri Nov  4 15:29:22 2016
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,10 @@ void PositiveConstRefNotMoveAssignable(E
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-04 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL286008: [clang-tidy] Ignore incomplete types when 
determining whether they are… (authored by flx).

Changed prior to commit:
  https://reviews.llvm.org/D26195?vs=76934&id=76935#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D26195

Files:
  clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
  
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp


Index: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,10 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
Index: clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
===
--- clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
+++ clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&


Index: clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
 
 // CHECK-FIXES: #include 
 
@@ -237,3 +237,10 @@
   ExpensiveToCopyType B;
   B = A;
 }
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
Index: clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
===
--- clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
+++ clang-tools-extra/trunk/clang-tidy/utils/TypeTraits.cpp
@@ -41,7 +41,7 @@
 
 llvm::Optional isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
-  if (Type->isDependentType())
+  if (Type->isDependentType() || Type->isIncompleteType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
  !classHasTrivialCopyAndDestroy(Type) &&
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r286010 - [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-04 Thread Felix Berger via cfe-commits
Author: flx
Date: Fri Nov  4 15:51:31 2016
New Revision: 286010

URL: http://llvm.org/viewvc/llvm-project?rev=286010&view=rev
Log:
[ClangTidy - performance-unnecessary-value-param] Only add "const" when current 
parameter is not already const qualified

Reviewers: alexfh, sbenza, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D26207

Modified:

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=286010&r1=286009&r2=286010&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
Fri Nov  4 15:51:31 2016
@@ -128,7 +128,10 @@ void UnnecessaryValueParamCheck::check(c
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+// The parameter of each declaration needs to be checked individually as to
+// whether it is const or not as constness can differ between definition 
and
+// declaration.
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=286010&r1=286009&r2=286010&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Fri Nov  4 15:51:31 2016
@@ -244,3 +244,19 @@ struct IncompleteType;
 void NegativeForIncompleteType(IncompleteType I) {
   // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
+}


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26207: [ClangTidy - performance-unnecessary-value-param] Only add "const" when current parameter is not already const qualified

2016-11-04 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL286010: [ClangTidy - performance-unnecessary-value-param] 
Only add "const" when current… (authored by flx).

Changed prior to commit:
  https://reviews.llvm.org/D26207?vs=76877&id=76940#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D26207

Files:
  clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp


Index: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,10 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+// The parameter of each declaration needs to be checked individually as to
+// whether it is const or not as constness can differ between definition 
and
+// declaration.
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }
Index: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -244,3 +244,19 @@
 void NegativeForIncompleteType(IncompleteType I) {
   // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
+  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
+}


Index: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -128,7 +128,10 @@
 const auto &CurrentParam = *FunctionDecl->getParamDecl(Index);
 Diag << utils::fixit::changeVarDeclToReference(CurrentParam,
*Result.Context);
-if (!IsConstQualified)
+// The parameter of each declaration needs to be checked individually as to
+// whether it is const or not as constness can differ between definition and
+// declaration.
+if (!CurrentParam.getType().getCanonicalType().isConstQualified())
   Diag << utils::fixit::changeVarDeclToConst(CurrentParam);
   }
 }
Index: clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -244,3 +244,19 @@
 void NegativeForIncompleteType(IncompleteType I) {
   // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
 }
+
+// Case where parameter in declaration is already const-qualified but not in
+// implementation. Make sure a second 'const' is not added to the declaration.
+void PositiveConstDeclaration(const ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveConstDeclaration(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
+}
+
+void PositiveNonConstDeclaration(ExpensiveToCopyType A);
+// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
+void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [

[PATCH] D26369: [ClangTidy] Move incomplete type test into separate test file

2016-11-07 Thread Felix Berger via cfe-commits
flx created this revision.
flx added reviewers: alexfh, aaron.ballman, sbenza.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Move in complete type test which does not compile into its own test file.


Repository:
  rL LLVM

https://reviews.llvm.org/D26369

Files:
  test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,25 +238,11 @@
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);
 // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
 void PositiveConstDeclaration(ExpensiveToCopyType A) {
   // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
   // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
 }
-
-void PositiveNonConstDeclaration(ExpensiveToCopyType A);
-// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
-void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
-  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
-  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
-}
Index: test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
+


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,25 +238,11 @@
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);
 // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
 void PositiveConstDeclaration(ExpensiveToCopyType A) {
   // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
   // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
 }
-
-void PositiveNonConstDeclaration(ExpensiveToCopyType A);
-// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
-void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
-  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
-  // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
-}
Index: test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+
+// Ensure that 

[PATCH] D26195: Ignore incomplete types when determining whether they are expensive to copy

2016-11-07 Thread Felix Berger via cfe-commits
flx added a comment.






Comment at: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp:241
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.

alexfh wrote:
> Please move this test to a separate test file and revert the RUN line here. 
Done in https://reviews.llvm.org/D26369.  


Repository:
  rL LLVM

https://reviews.llvm.org/D26195



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26369: [ClangTidy] Move incomplete type test into separate test file

2016-11-07 Thread Felix Berger via cfe-commits
flx removed rL LLVM as the repository for this revision.
flx updated this revision to Diff 77094.

https://reviews.llvm.org/D26369

Files:
  test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,13 +238,6 @@
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);
Index: test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
+


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,13 +238,6 @@
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);
Index: test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
+
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26369: [ClangTidy] Move incomplete type test into separate test file

2016-11-07 Thread Felix Berger via cfe-commits
flx marked an inline comment as done.
flx added inline comments.



Comment at: test/clang-tidy/performance-unnecessary-value-param.cpp:257
-
-void PositiveNonConstDeclaration(ExpensiveToCopyType A);
-// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);

aaron.ballman wrote:
> Why are these tests being removed?
They should not be removed. Restored them.


https://reviews.llvm.org/D26369



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26369: [ClangTidy] Move incomplete type test into separate test file

2016-11-07 Thread Felix Berger via cfe-commits
flx marked an inline comment as done.
flx added inline comments.



Comment at: test/clang-tidy/performance-unnecessary-value-param.cpp:257
-
-void PositiveNonConstDeclaration(ExpensiveToCopyType A);
-// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);

aaron.ballman wrote:
> flx wrote:
> > aaron.ballman wrote:
> > > Why are these tests being removed?
> > They should not be removed. Restored them.
> Yay code review process! :-)
Absolutely. Thanks for the quick review!


https://reviews.llvm.org/D26369



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r286155 - [clang-tidy] Move incomplete type test into separate test file

2016-11-07 Thread Felix Berger via cfe-commits
Author: flx
Date: Mon Nov  7 15:45:58 2016
New Revision: 286155

URL: http://llvm.org/viewvc/llvm-project?rev=286155&view=rev
Log:
[clang-tidy] Move incomplete type test into separate test file

Summary: Move in complete type test which does not compile into its own test 
file.

Reviewers: alexfh, sbenza, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D26369

Added:

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
Modified:

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Added: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp?rev=286155&view=auto
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
 (added)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
 Mon Nov  7 15:45:58 2016
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
+

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=286155&r1=286154&r2=286155&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Mon Nov  7 15:45:58 2016
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,13 +238,6 @@ void PositiveConstRefNotMoveAssignable(E
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26369: [ClangTidy] Move incomplete type test into separate test file

2016-11-07 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL286155: [clang-tidy] Move incomplete type test into separate 
test file (authored by flx).

Changed prior to commit:
  https://reviews.llvm.org/D26369?vs=77094&id=77095#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D26369

Files:
  
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
  
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp


Index: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
===
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
+}
+
Index: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- 
-fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,13 +238,6 @@
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 
'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);


Index: clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param-incomplete-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+
+// Ensure that incomplete types result in an error from the frontend and not a
+// clang-tidy diagnostic about IncompleteType being expensive to copy.
+struct IncompleteType;
+void NegativeForIncompleteType(IncompleteType I) {
+  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
+}
+
Index: clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -fix-errors -- --std=c++11
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
 
 // CHECK-FIXES: #include 
 
@@ -238,13 +238,6 @@
   B = A;
 }
 
-// Ensure that incomplete types result in an error from the frontend and not a
-// clang-tidy diagnostic about IncompleteType being expensive to copy.
-struct IncompleteType;
-void NegativeForIncompleteType(IncompleteType I) {
-  // CHECK-MESSAGES: [[@LINE-1]]:47: error: variable has incomplete type 'IncompleteType' [clang-diagnostic-error]
-}
-
 // Case where parameter in declaration is already const-qualified but not in
 // implementation. Make sure a second 'const' is not added to the declaration.
 void PositiveConstDeclaration(const ExpensiveToCopyType A);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26203: [ClangTidy - performance-unnecessary-value-param]: Do not issue fix for functions that are referenced outside of callExpr

2016-11-09 Thread Felix Berger via cfe-commits
flx removed rL LLVM as the repository for this revision.
flx updated this revision to Diff 77343.

https://reviews.llvm.org/D26203

Files:
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -259,4 +259,21 @@
 void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
   // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
   // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void 
PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = 
&PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const 
ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
 }
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -39,6 +39,14 @@
   return true;
 }
 
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+   ASTContext &Context) {
+  auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
+   unless(hasAncestor(callExpr(,
+   Context);
+  return !Matches.empty();
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@@ -118,10 +126,14 @@
   "invocation but only used as a const reference; "
   "consider making it a const reference")
   << paramNameOrIndex(Param->getName(), Index);
-  // Do not propose fixes in macros since we cannot place them correctly, or if
-  // function is virtual as it might break overrides.
+  // Do not propose fixes when:
+  // 1. the ParmVarDecl is in a macro, since we cannot place them correctly
+  // 2. the function is virtual as it might break overrides
+  // 3. the function is referenced outside of a call expression within the
+  //compilation unit as the signature change could introduce build errors.
   const auto *Method = llvm::dyn_cast(Function);
-  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()))
+  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
+  isReferencedOutsideOfCallExpr(*Function, *Result.Context))
 return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
FunctionDecl = FunctionDecl->getPreviousDecl()) {


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -259,4 +259,21 @@
 void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
   // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
   // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
 }
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -39,6 +39,14 @@
   return true;
 }
 
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+   ASTContext &Context) {
+  auto Matche

[PATCH] D26203: [ClangTidy - performance-unnecessary-value-param]: Do not issue fix for functions that are referenced outside of callExpr

2016-11-09 Thread Felix Berger via cfe-commits
flx marked an inline comment as done.
flx added a comment.

Thanks for the review!


https://reviews.llvm.org/D26203



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26453: [clang-tidy] Remove duplicated check from move-constructor-init

2016-11-09 Thread Felix Berger via cfe-commits
flx added a comment.

Is the modernize-pass-by-value check configurable in a way to only trigger when 
copied constructor arguments are not moved?

I think our use case has been to have move-constructor-init check enabled to 
catch cases that can be optimized but not trigger on every constructor that 
uses const& instead of value + move, i.e. modernizing is not prescribed, but 
catching cases where the argument is already passed by value and making them 
faster is desirable.


https://reviews.llvm.org/D26453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r286424 - [clang-tidy] Do not issue fix for functions that are referenced outside of callExpr

2016-11-09 Thread Felix Berger via cfe-commits
Author: flx
Date: Wed Nov  9 19:28:22 2016
New Revision: 286424

URL: http://llvm.org/viewvc/llvm-project?rev=286424&view=rev
Log:
[clang-tidy] Do not issue fix for functions that are referenced outside of 
callExpr

Summary: Suppress fixes for functions that are referenced within the
compilation unit outside of a call expression as the signature change
could break the code referencing the function.

We still issue a warning in this case so that users can decide to
manually change the function signature.

Reviewers: alexfh, sbenza, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D26203

Modified:

clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp

clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp?rev=286424&r1=286423&r2=286424&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp 
Wed Nov  9 19:28:22 2016
@@ -39,6 +39,14 @@ bool isSubset(const S &SubsetCandidate,
   return true;
 }
 
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+   ASTContext &Context) {
+  auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
+   unless(hasAncestor(callExpr(,
+   Context);
+  return !Matches.empty();
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@@ -118,10 +126,14 @@ void UnnecessaryValueParamCheck::check(c
   "invocation but only used as a const reference; "
   "consider making it a const reference")
   << paramNameOrIndex(Param->getName(), Index);
-  // Do not propose fixes in macros since we cannot place them correctly, or if
-  // function is virtual as it might break overrides.
+  // Do not propose fixes when:
+  // 1. the ParmVarDecl is in a macro, since we cannot place them correctly
+  // 2. the function is virtual as it might break overrides
+  // 3. the function is referenced outside of a call expression within the
+  //compilation unit as the signature change could introduce build errors.
   const auto *Method = llvm::dyn_cast(Function);
-  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()))
+  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
+  isReferencedOutsideOfCallExpr(*Function, *Result.Context))
 return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
FunctionDecl = FunctionDecl->getPreviousDecl()) {

Modified: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp?rev=286424&r1=286423&r2=286424&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
(original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp 
Wed Nov  9 19:28:22 2016
@@ -253,3 +253,21 @@ void PositiveNonConstDeclaration(const E
   // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
   // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
 }
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void 
PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = 
&PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const 
ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D26203: [ClangTidy - performance-unnecessary-value-param]: Do not issue fix for functions that are referenced outside of callExpr

2016-11-09 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL286424: [clang-tidy] Do not issue fix for functions that are 
referenced outside of… (authored by flx).

Changed prior to commit:
  https://reviews.llvm.org/D26203?vs=77343&id=77430#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D26203

Files:
  clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp


Index: 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ 
clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -253,3 +253,21 @@
   // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
   // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& 
A) {
 }
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void 
PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = 
&PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const 
ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}
Index: 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===
--- 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ 
clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -39,6 +39,14 @@
   return true;
 }
 
+bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
+   ASTContext &Context) {
+  auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
+   unless(hasAncestor(callExpr(,
+   Context);
+  return !Matches.empty();
+}
+
 } // namespace
 
 UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@@ -118,10 +126,14 @@
   "invocation but only used as a const reference; "
   "consider making it a const reference")
   << paramNameOrIndex(Param->getName(), Index);
-  // Do not propose fixes in macros since we cannot place them correctly, or if
-  // function is virtual as it might break overrides.
+  // Do not propose fixes when:
+  // 1. the ParmVarDecl is in a macro, since we cannot place them correctly
+  // 2. the function is virtual as it might break overrides
+  // 3. the function is referenced outside of a call expression within the
+  //compilation unit as the signature change could introduce build errors.
   const auto *Method = llvm::dyn_cast(Function);
-  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()))
+  if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
+  isReferencedOutsideOfCallExpr(*Function, *Result.Context))
 return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
FunctionDecl = FunctionDecl->getPreviousDecl()) {


Index: clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -253,3 +253,21 @@
   // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
   // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
 }
+
+void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
+}
+
+void ReferenceFunctionOutsideOfCallExpr() {
+  void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit;
+}
+
+void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
+  // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
+  // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
+}
+
+void ReferenceFunctionByCallingIt() {
+  PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
+}
Index: clang-tools-extra/trunk/clang-tidy/performance/UnnecessaryValuePar

[PATCH] D26453: [clang-tidy] Remove duplicated check from move-constructor-init

2016-11-11 Thread Felix Berger via cfe-commits
flx added a comment.

In https://reviews.llvm.org/D26453#590720, @malcolm.parsons wrote:

> Add ValuesOnly option to modernize-pass-by-value.


Thanks for doing this. Alex, would this work for us?


https://reviews.llvm.org/D26453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-09-14 Thread Felix Berger via cfe-commits
flx created this revision.
flx added reviewers: alexfh, sbenza, aaron.ballman.
flx added a subscriber: cfe-commits.

Add matcher that identifies arguments that are passed by value, are copy 
assigned to a class field and have a non-deleted move constructor. If the type 
is also expensive to copy issue diagnostic message that the field can be move 
constructed.

http://reviews.llvm.org/D12839

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tidy/misc/MoveConstructorInitCheck.h
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -76,3 +76,60 @@
   B Mem;
   N(N &&RHS) : Mem(move(RHS.Mem)) {}
 };
+
+
+struct Movable {
+  Movable(Movable&&) = default;
+  Movable(const Movable&) = default;
+  Movable& operator =(const Movable&) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable() = default;
+  TriviallyCopyable(TriviallyCopyable&&) = default;
+  TriviallyCopyable(const TriviallyCopyable&) = default;
+};
+
+struct Positive {
+  Positive(Movable M) : M_(M) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value parameter can be moved to avoid copy. [misc-move-constructor-init]
+  Movable M_;
+};
+
+struct NegativeMultipleInitializerReferences {
+  NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {}
+  Movable M_;
+  Movable n_;
+};
+
+struct NegativeReferencedInConstructorBody {
+  NegativeReferencedInConstructorBody(Movable M) : M_(M) {
+M_ = M;
+  }
+  Movable M_;
+};
+
+struct NegativeParamTriviallyCopyable {
+  NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}
+  TriviallyCopyable T_;
+};
+
+struct NegativeNotPassedByValue {
+  NegativeNotPassedByValue(const Movable& M) : M_(M) {}
+  NegativeNotPassedByValue(const Movable M) : M_(M) {}
+  NegativeNotPassedByValue(Movable& M) : M_(M) {}
+  NegativeNotPassedByValue(Movable* M) : M_(*M) {}
+  NegativeNotPassedByValue(const Movable* M) : M_(*M) {}
+  Movable M_;
+};
+
+struct Immovable {
+  Immovable(const Immovable&) = default;
+  Immovable(Immovable&&) = delete;
+};
+
+struct NegativeImmovableParameter {
+  NegativeImmovableParameter(Immovable I) : I_(I) {}
+  Immovable I_;
+};
Index: clang-tidy/misc/MoveConstructorInitCheck.h
===
--- clang-tidy/misc/MoveConstructorInitCheck.h
+++ clang-tidy/misc/MoveConstructorInitCheck.h
@@ -18,12 +18,21 @@
 /// The check flags user-defined move constructors that have a ctor-initializer
 /// initializing a member or base class through a copy constructor instead of a
 /// move constructor.
+/// It also flags constructor arguments that are passed by value, have a
+/// non-deleted move-constructor and are assigned to a class field by copy
+/// construction.
 class MoveConstructorInitCheck : public ClangTidyCheck {
 public:
   MoveConstructorInitCheck(StringRef Name, ClangTidyContext *Context)
   : ClangTidyCheck(Name, Context) {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void
+  handleMoveConstructor(const ast_matchers::MatchFinder::MatchResult &Result);
+  void
+  handleParamNotMoved(const ast_matchers::MatchFinder::MatchResult &Result);
 };
 
 } // namespace tidy
Index: clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -16,6 +16,48 @@
 namespace clang {
 namespace tidy {
 
+namespace {
+
+bool classHasTrivialCopyAndDestroy(QualType Type) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  return Record && Record->hasDefinition() &&
+ !Record->hasNonTrivialCopyConstructor() &&
+ !Record->hasNonTrivialDestructor();
+}
+
+AST_MATCHER(QualType, isExpensiveToCopy) {
+  // We can't reason about dependent types. Ignore them.
+  // If there's a template instantiation that results in what we consider
+  // excessive copying, we'll warn on them.
+  if (Node->isDependentType()) {
+return false;
+  }
+  // Ignore trivially copyable types.
+  if (Node->isScalarType() ||
+  Node.isTriviallyCopyableType(Finder->getASTContext()) ||
+  classHasTrivialCopyAndDestroy(Node)) {
+return false;
+  }
+  return true;
+}
+
+int parmVarDeclRefExprOccurences(const ParmVarDecl &MovableParam,
+ const CXXConstructorDecl &ConstructorDecl,
+ ASTContext &Context) {
+  int Occurrences = 0;
+  auto AllDeclRefs =
+  findAll(declRefExpr(to(parmVarDecl(equalsNode(&MovableParam);
+  auto Matches = match(AllDeclRefs, *ConstructorDecl.getBody(), Context);
+  Occurrences += Matches.size();
+  for (const auto* Initializer : C

Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-09-20 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 35204.
flx marked 10 inline comments as done.

http://reviews.llvm.org/D12839

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tidy/misc/MoveConstructorInitCheck.h
  clang-tidy/utils/CMakeLists.txt
  clang-tidy/utils/Matchers.h
  clang-tidy/utils/TypeTraits.cpp
  clang-tidy/utils/TypeTraits.h
  docs/clang-tidy/checks/misc-move-constructor-init.rst
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -76,3 +76,59 @@
   B Mem;
   N(N &&RHS) : Mem(move(RHS.Mem)) {}
 };
+
+struct Movable {
+  Movable(Movable &&) = default;
+  Movable(const Movable &) = default;
+  Movable &operator=(const Movable &) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable() = default;
+  TriviallyCopyable(TriviallyCopyable &&) = default;
+  TriviallyCopyable(const TriviallyCopyable &) = default;
+};
+
+struct Positive {
+  Positive(Movable M) : M_(M) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to avoid copy [misc-move-constructor-init]
+  Movable M_;
+};
+
+struct NegativeMultipleInitializerReferences {
+  NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {}
+  Movable M_;
+  Movable n_;
+};
+
+struct NegativeReferencedInConstructorBody {
+  NegativeReferencedInConstructorBody(Movable M) : M_(M) { M_ = M; }
+  Movable M_;
+};
+
+struct NegativeParamTriviallyCopyable {
+  NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}
+  NegativeParamTriviallyCopyable(int I) : I_(I) {}
+  TriviallyCopyable T_;
+  int I_;
+};
+
+struct NegativeNotPassedByValue {
+  NegativeNotPassedByValue(const Movable &M) : M_(M) {}
+  NegativeNotPassedByValue(const Movable M) : M_(M) {}
+  NegativeNotPassedByValue(Movable &M) : M_(M) {}
+  NegativeNotPassedByValue(Movable *M) : M_(*M) {}
+  NegativeNotPassedByValue(const Movable *M) : M_(*M) {}
+  Movable M_;
+};
+
+struct Immovable {
+  Immovable(const Immovable &) = default;
+  Immovable(Immovable &&) = delete;
+};
+
+struct NegativeImmovableParameter {
+  NegativeImmovableParameter(Immovable I) : I_(I) {}
+  Immovable I_;
+};
Index: docs/clang-tidy/checks/misc-move-constructor-init.rst
===
--- docs/clang-tidy/checks/misc-move-constructor-init.rst
+++ docs/clang-tidy/checks/misc-move-constructor-init.rst
@@ -5,3 +5,6 @@
 The check flags user-defined move constructors that have a ctor-initializer
 initializing a member or base class through a copy constructor instead of a
 move constructor.
+
+It also flags constructor arguments that are passed by value, have a non-deleted
+move-constructor and are assigned to a class field by copy construction.
Index: clang-tidy/utils/TypeTraits.h
===
--- clang-tidy/utils/TypeTraits.h
+++ clang-tidy/utils/TypeTraits.h
@@ -0,0 +1,31 @@
+//===--- TypeTraits.h - clang-tidy---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace tidy {
+namespace type_traits {
+
+/// Returns true if \c Type is defined has no non-trivial copy-constructor or
+/// destructor.
+bool classHasTrivialCopyAndDestroy(QualType Type);
+
+// \brief Returns true If \c Type is expensive to copy.
+bool isExpensiveToCopy(QualType Type, ASTContext &Context);
+
+} // type_traits
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -0,0 +1,38 @@
+//===--- TypeTraits.cpp - clang-tidy---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TypeTraits.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+namespace tidy {
+namespace type_traits {
+
+bool classHasTrivialCopyAndDestroy(QualType Type) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  return Record && Record->hasDefinition() &&
+ !Record->hasNonTrivialCopyCons

Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-09-20 Thread Felix Berger via cfe-commits
flx added inline comments.


Comment at: clang-tidy/misc/MoveConstructorInitCheck.cpp:38
@@ +37,3 @@
+  Node.isTriviallyCopyableType(Finder->getASTContext()) ||
+  classHasTrivialCopyAndDestroy(Node)) {
+return false;

aaron.ballman wrote:
> Why do you need classHasTrivialCopyAndDestroy() when you're already checking 
> if it's a trivially copyable type?
We also want to catch types that have non-trivial destructors which would be 
executed when the temporary copy goes out of scope.


Comment at: clang-tidy/misc/MoveConstructorInitCheck.cpp:44
@@ +43,3 @@
+
+int parmVarDeclRefExprOccurences(const ParmVarDecl &MovableParam,
+ const CXXConstructorDecl &ConstructorDecl,

aaron.ballman wrote:
> Should return unsigned, please.
Done. Is this an llvm convention?


Comment at: clang-tidy/misc/MoveConstructorInitCheck.cpp:120
@@ +119,3 @@
+  }
+  diag(InitArg->getLocStart(), "value parameter can be moved to avoid copy.");
+}

alexfh wrote:
> alexfh wrote:
> > aaron.ballman wrote:
> > > Perhaps: "argument can be moved to avoid a copy" instead?
> > nit: Please remove the trailing period.
> Does anything stop us from suggesting fixes here (inserting "std::move()" 
> around the argument and #include , if it's no there yet)?
How would I tread in the IncludeOrder style (i.e. Google vs LLVM)? Should this 
be a flag shared by all of ClangTidy or specific to this check?


Comment at: test/clang-tidy/misc-move-constructor-init.cpp:85
@@ +84,3 @@
+  Movable& operator =(const Movable&) = default;
+  ~Movable() {}
+};

aaron.ballman wrote:
> Why not = default?
We need to make the type non-trivially copyable by our definition above.


Comment at: test/clang-tidy/misc-move-constructor-init.cpp:113
@@ +112,3 @@
+
+struct NegativeParamTriviallyCopyable {
+  NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}

aaron.ballman wrote:
> Should also have a test for scalars
Added.


http://reviews.llvm.org/D12839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-09-27 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 35826.
flx marked 7 inline comments as done.
flx added a comment.

I changed the check to also produce a fix that wraps the argument in 
std::move().

When I modified the test include -isystem %S/Inputs/Headers it broke and only 
produces warnings but no fixes anymore. Is there a subtle difference in how 
tests with includes need to be invoked?


http://reviews.llvm.org/D12839

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tidy/misc/MoveConstructorInitCheck.h
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/utils/CMakeLists.txt
  clang-tidy/utils/IncludeSorter.cpp
  clang-tidy/utils/IncludeSorter.h
  clang-tidy/utils/Matchers.h
  clang-tidy/utils/TypeTraits.cpp
  clang-tidy/utils/TypeTraits.h
  docs/clang-tidy/checks/misc-move-constructor-init.rst
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -1,4 +1,8 @@
-// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t
+// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t -- -isystem %S/Inputs/Headers
+
+#include "j.h"
+#include 
+// CHECK-FIXES: #include 
 
 template  struct remove_reference  {typedef T type;};
 template  struct remove_reference  {typedef T type;};
@@ -76,3 +80,66 @@
   B Mem;
   N(N &&RHS) : Mem(move(RHS.Mem)) {}
 };
+
+struct Movable {
+  Movable(Movable &&) = default;
+  Movable(const Movable &) = default;
+  Movable &operator=(const Movable &) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable() = default;
+  TriviallyCopyable(TriviallyCopyable &&) = default;
+  TriviallyCopyable(const TriviallyCopyable &) = default;
+};
+
+struct Positive {
+  Positive(Movable M) : M_(M) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to avoid copy [misc-move-constructor-init]
+  // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
+  Movable M_;
+};
+
+struct NegativeMultipleInitializerReferences {
+  NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {}
+  Movable M_;
+  Movable n_;
+};
+
+struct NegativeReferencedInConstructorBody {
+  NegativeReferencedInConstructorBody(Movable M) : M_(M) { M_ = M; }
+  Movable M_;
+};
+
+struct NegativeParamTriviallyCopyable {
+  NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}
+  NegativeParamTriviallyCopyable(int I) : I_(I) {}
+
+  TriviallyCopyable T_;
+  int I_;
+};
+
+template  struct NegativeDependentType {
+  NegativeDependentType(T Value) : T_(Value) {}
+  T T_;
+};
+
+struct NegativeNotPassedByValue {
+  NegativeNotPassedByValue(const Movable &M) : M_(M) {}
+  NegativeNotPassedByValue(const Movable M) : M_(M) {}
+  NegativeNotPassedByValue(Movable &M) : M_(M) {}
+  NegativeNotPassedByValue(Movable *M) : M_(*M) {}
+  NegativeNotPassedByValue(const Movable *M) : M_(*M) {}
+  Movable M_;
+};
+
+struct Immovable {
+  Immovable(const Immovable &) = default;
+  Immovable(Immovable &&) = delete;
+};
+
+struct NegativeImmovableParameter {
+  NegativeImmovableParameter(Immovable I) : I_(I) {}
+  Immovable I_;
+};
Index: docs/clang-tidy/checks/misc-move-constructor-init.rst
===
--- docs/clang-tidy/checks/misc-move-constructor-init.rst
+++ docs/clang-tidy/checks/misc-move-constructor-init.rst
@@ -5,3 +5,6 @@
 The check flags user-defined move constructors that have a ctor-initializer
 initializing a member or base class through a copy constructor instead of a
 move constructor.
+
+It also flags constructor arguments that are passed by value, have a non-deleted
+move-constructor and are assigned to a class field by copy construction.
Index: clang-tidy/utils/TypeTraits.h
===
--- clang-tidy/utils/TypeTraits.h
+++ clang-tidy/utils/TypeTraits.h
@@ -0,0 +1,27 @@
+//===--- TypeTraits.h - clang-tidy---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace tidy {
+namespace type_traits {
+
+// \brief Returns true If \c Type is expensive to copy.
+bool isExpensiveToCopy(QualType Type, ASTContext &Context);
+
+} // type_traits
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_TYPETRAITS_H
Index: clang-tidy/utils/TypeTraits.cpp

Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-09-29 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 36049.
flx marked 3 inline comments as done.
flx added a comment.

I had to convert the line endings of mis-move-constructor-init.cpp to unix 
style otherwise the test would not correctly work. This took a long time to 
debug since the checks failed complaining that error messages that look exactly 
the same didn't match.

Let me know if this needs to be converted back to DOS line endings, but it 
looks like most other tests have unix line endings.


http://reviews.llvm.org/D12839

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tidy/misc/MoveConstructorInitCheck.h
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/utils/CMakeLists.txt
  clang-tidy/utils/IncludeSorter.cpp
  clang-tidy/utils/IncludeSorter.h
  clang-tidy/utils/Matchers.h
  clang-tidy/utils/TypeTraits.cpp
  clang-tidy/utils/TypeTraits.h
  docs/clang-tidy/checks/misc-move-constructor-init.rst
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -1,78 +1,145 @@
-// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t
-
-template  struct remove_reference  {typedef T type;};
-template  struct remove_reference  {typedef T type;};
-template  struct remove_reference {typedef T type;};
-
-template 
-typename remove_reference::type&& move(T&& arg) {
-  return static_cast::type&&>(arg);
-}
-
-struct C {
-  C() = default;
-  C(const C&) = default;
-};
-
-struct B {
-  B() {}
-  B(const B&) {}
-  B(B &&) {}
-};
-
-struct D : B {
-  D() : B() {}
-  D(const D &RHS) : B(RHS) {}
-  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
-  // CHECK-MESSAGES: 19:3: note: copy constructor being called
-  // CHECK-MESSAGES: 20:3: note: candidate move constructor here
-  D(D &&RHS) : B(RHS) {}
-};
-
-struct E : B {
-  E() : B() {}
-  E(const E &RHS) : B(RHS) {}
-  E(E &&RHS) : B(move(RHS)) {} // ok
-};
-
-struct F {
-  C M;
-
-  F(F &&) : M(C()) {} // ok
-};
-
-struct G {
-  G() = default;
-  G(const G&) = default;
-  G(G&&) = delete;
-};
-
-struct H : G {
-  H() = default;
-  H(const H&) = default;
-  H(H &&RHS) : G(RHS) {} // ok
-};
-
-struct I {
-  I(const I &) = default; // suppresses move constructor creation
-};
-
-struct J : I {
-  J(J &&RHS) : I(RHS) {} // ok
-};
-
-struct K {}; // Has implicit copy and move constructors, is trivially copyable
-struct L : K {
-  L(L &&RHS) : K(RHS) {} // ok
-};
-
-struct M {
-  B Mem;
-  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [misc-move-constructor-init]
-  M(M &&RHS) : Mem(RHS.Mem) {}
-};
-
-struct N {
-  B Mem;
-  N(N &&RHS) : Mem(move(RHS.Mem)) {}
-};
+// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t -- -std=c++11 -isystem %S/Inputs/Headers
+
+#include 
+
+// CHECK-FIXES: #include 
+
+template  struct remove_reference  {typedef T type;};
+template  struct remove_reference  {typedef T type;};
+template  struct remove_reference {typedef T type;};
+
+template 
+typename remove_reference::type&& move(T&& arg) {
+  return static_cast::type&&>(arg);
+}
+
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+struct B {
+  B() {}
+  B(const B&) {}
+  B(B &&) {}
+};
+
+struct D : B {
+  D() : B() {}
+  D(const D &RHS) : B(RHS) {}
+  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
+  // CHECK-MESSAGES: 23:3: note: copy constructor being called
+  // CHECK-MESSAGES: 24:3: note: candidate move constructor here
+  D(D &&RHS) : B(RHS) {}
+};
+
+struct E : B {
+  E() : B() {}
+  E(const E &RHS) : B(RHS) {}
+  E(E &&RHS) : B(move(RHS)) {} // ok
+};
+
+struct F {
+  C M;
+
+  F(F &&) : M(C()) {} // ok
+};
+
+struct G {
+  G() = default;
+  G(const G&) = default;
+  G(G&&) = delete;
+};
+
+struct H : G {
+  H() = default;
+  H(const H&) = default;
+  H(H &&RHS) : G(RHS) {} // ok
+};
+
+struct I {
+  I(const I &) = default; // suppresses move constructor creation
+};
+
+struct J : I {
+  J(J &&RHS) : I(RHS) {} // ok
+};
+
+struct K {}; // Has implicit copy and move constructors, is trivially copyable
+struct L : K {
+  L(L &&RHS) : K(RHS) {} // ok
+};
+
+struct M {
+  B Mem;
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [misc-move-constructor-init]
+  M(M &&RHS) : Mem(RHS.Mem) {}
+};
+
+struct N {
+  B Mem;
+  N(N &&RHS) : Mem(move(RHS.Mem)) {}
+};
+
+struct Movable {
+  Movable(Movable &&) = default;
+  Movable(const Movable &) = default;
+  Movable &operator=(const Movable &) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopya

Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-09-30 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 36151.
flx marked an inline comment as done.
flx added a comment.

Thanks for catching the last issues, Alex. I rebuilt and ran all tests using 
llvm-lit -v . for clang-tidy and they pass.


http://reviews.llvm.org/D12839

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tidy/misc/MoveConstructorInitCheck.h
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/utils/CMakeLists.txt
  clang-tidy/utils/IncludeSorter.cpp
  clang-tidy/utils/IncludeSorter.h
  clang-tidy/utils/Matchers.h
  clang-tidy/utils/TypeTraits.cpp
  clang-tidy/utils/TypeTraits.h
  docs/clang-tidy/checks/misc-move-constructor-init.rst
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -1,78 +1,145 @@
-// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t
-
-template  struct remove_reference  {typedef T type;};
-template  struct remove_reference  {typedef T type;};
-template  struct remove_reference {typedef T type;};
-
-template 
-typename remove_reference::type&& move(T&& arg) {
-  return static_cast::type&&>(arg);
-}
-
-struct C {
-  C() = default;
-  C(const C&) = default;
-};
-
-struct B {
-  B() {}
-  B(const B&) {}
-  B(B &&) {}
-};
-
-struct D : B {
-  D() : B() {}
-  D(const D &RHS) : B(RHS) {}
-  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
-  // CHECK-MESSAGES: 19:3: note: copy constructor being called
-  // CHECK-MESSAGES: 20:3: note: candidate move constructor here
-  D(D &&RHS) : B(RHS) {}
-};
-
-struct E : B {
-  E() : B() {}
-  E(const E &RHS) : B(RHS) {}
-  E(E &&RHS) : B(move(RHS)) {} // ok
-};
-
-struct F {
-  C M;
-
-  F(F &&) : M(C()) {} // ok
-};
-
-struct G {
-  G() = default;
-  G(const G&) = default;
-  G(G&&) = delete;
-};
-
-struct H : G {
-  H() = default;
-  H(const H&) = default;
-  H(H &&RHS) : G(RHS) {} // ok
-};
-
-struct I {
-  I(const I &) = default; // suppresses move constructor creation
-};
-
-struct J : I {
-  J(J &&RHS) : I(RHS) {} // ok
-};
-
-struct K {}; // Has implicit copy and move constructors, is trivially copyable
-struct L : K {
-  L(L &&RHS) : K(RHS) {} // ok
-};
-
-struct M {
-  B Mem;
-  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [misc-move-constructor-init]
-  M(M &&RHS) : Mem(RHS.Mem) {}
-};
-
-struct N {
-  B Mem;
-  N(N &&RHS) : Mem(move(RHS.Mem)) {}
-};
+// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t -- -std=c++11 -isystem %S/Inputs/Headers
+
+#include 
+
+// CHECK-FIXES: #include 
+
+template  struct remove_reference  {typedef T type;};
+template  struct remove_reference  {typedef T type;};
+template  struct remove_reference {typedef T type;};
+
+template 
+typename remove_reference::type&& move(T&& arg) {
+  return static_cast::type&&>(arg);
+}
+
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+struct B {
+  B() {}
+  B(const B&) {}
+  B(B &&) {}
+};
+
+struct D : B {
+  D() : B() {}
+  D(const D &RHS) : B(RHS) {}
+  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
+  // CHECK-MESSAGES: 23:3: note: copy constructor being called
+  // CHECK-MESSAGES: 24:3: note: candidate move constructor here
+  D(D &&RHS) : B(RHS) {}
+};
+
+struct E : B {
+  E() : B() {}
+  E(const E &RHS) : B(RHS) {}
+  E(E &&RHS) : B(move(RHS)) {} // ok
+};
+
+struct F {
+  C M;
+
+  F(F &&) : M(C()) {} // ok
+};
+
+struct G {
+  G() = default;
+  G(const G&) = default;
+  G(G&&) = delete;
+};
+
+struct H : G {
+  H() = default;
+  H(const H&) = default;
+  H(H &&RHS) : G(RHS) {} // ok
+};
+
+struct I {
+  I(const I &) = default; // suppresses move constructor creation
+};
+
+struct J : I {
+  J(J &&RHS) : I(RHS) {} // ok
+};
+
+struct K {}; // Has implicit copy and move constructors, is trivially copyable
+struct L : K {
+  L(L &&RHS) : K(RHS) {} // ok
+};
+
+struct M {
+  B Mem;
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [misc-move-constructor-init]
+  M(M &&RHS) : Mem(RHS.Mem) {}
+};
+
+struct N {
+  B Mem;
+  N(N &&RHS) : Mem(move(RHS.Mem)) {}
+};
+
+struct Movable {
+  Movable(Movable &&) = default;
+  Movable(const Movable &) = default;
+  Movable &operator=(const Movable &) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable() = default;
+  TriviallyCopyable(TriviallyCopyable &&) = default;
+  TriviallyCopyable(const TriviallyCopyable &) = default;
+};
+
+struct Positive {
+  Positive(Movable M) : M_(M) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value

Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-10-03 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 36433.
flx added a comment.

Updated patch to new cxx* matcher variants.


http://reviews.llvm.org/D12839

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tidy/misc/MoveConstructorInitCheck.h
  clang-tidy/modernize/PassByValueCheck.cpp
  clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
  clang-tidy/utils/CMakeLists.txt
  clang-tidy/utils/IncludeSorter.cpp
  clang-tidy/utils/IncludeSorter.h
  clang-tidy/utils/Matchers.h
  clang-tidy/utils/TypeTraits.cpp
  clang-tidy/utils/TypeTraits.h
  docs/clang-tidy/checks/misc-move-constructor-init.rst
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -1,78 +1,145 @@
-// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t
-
-template  struct remove_reference  {typedef T type;};
-template  struct remove_reference  {typedef T type;};
-template  struct remove_reference {typedef T type;};
-
-template 
-typename remove_reference::type&& move(T&& arg) {
-  return static_cast::type&&>(arg);
-}
-
-struct C {
-  C() = default;
-  C(const C&) = default;
-};
-
-struct B {
-  B() {}
-  B(const B&) {}
-  B(B &&) {}
-};
-
-struct D : B {
-  D() : B() {}
-  D(const D &RHS) : B(RHS) {}
-  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
-  // CHECK-MESSAGES: 19:3: note: copy constructor being called
-  // CHECK-MESSAGES: 20:3: note: candidate move constructor here
-  D(D &&RHS) : B(RHS) {}
-};
-
-struct E : B {
-  E() : B() {}
-  E(const E &RHS) : B(RHS) {}
-  E(E &&RHS) : B(move(RHS)) {} // ok
-};
-
-struct F {
-  C M;
-
-  F(F &&) : M(C()) {} // ok
-};
-
-struct G {
-  G() = default;
-  G(const G&) = default;
-  G(G&&) = delete;
-};
-
-struct H : G {
-  H() = default;
-  H(const H&) = default;
-  H(H &&RHS) : G(RHS) {} // ok
-};
-
-struct I {
-  I(const I &) = default; // suppresses move constructor creation
-};
-
-struct J : I {
-  J(J &&RHS) : I(RHS) {} // ok
-};
-
-struct K {}; // Has implicit copy and move constructors, is trivially copyable
-struct L : K {
-  L(L &&RHS) : K(RHS) {} // ok
-};
-
-struct M {
-  B Mem;
-  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [misc-move-constructor-init]
-  M(M &&RHS) : Mem(RHS.Mem) {}
-};
-
-struct N {
-  B Mem;
-  N(N &&RHS) : Mem(move(RHS.Mem)) {}
-};
+// RUN: %python %S/check_clang_tidy.py %s misc-move-constructor-init %t -- -std=c++11 -isystem %S/Inputs/Headers
+
+#include 
+
+// CHECK-FIXES: #include 
+
+template  struct remove_reference  {typedef T type;};
+template  struct remove_reference  {typedef T type;};
+template  struct remove_reference {typedef T type;};
+
+template 
+typename remove_reference::type&& move(T&& arg) {
+  return static_cast::type&&>(arg);
+}
+
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+struct B {
+  B() {}
+  B(const B&) {}
+  B(B &&) {}
+};
+
+struct D : B {
+  D() : B() {}
+  D(const D &RHS) : B(RHS) {}
+  // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
+  // CHECK-MESSAGES: 23:3: note: copy constructor being called
+  // CHECK-MESSAGES: 24:3: note: candidate move constructor here
+  D(D &&RHS) : B(RHS) {}
+};
+
+struct E : B {
+  E() : B() {}
+  E(const E &RHS) : B(RHS) {}
+  E(E &&RHS) : B(move(RHS)) {} // ok
+};
+
+struct F {
+  C M;
+
+  F(F &&) : M(C()) {} // ok
+};
+
+struct G {
+  G() = default;
+  G(const G&) = default;
+  G(G&&) = delete;
+};
+
+struct H : G {
+  H() = default;
+  H(const H&) = default;
+  H(H &&RHS) : G(RHS) {} // ok
+};
+
+struct I {
+  I(const I &) = default; // suppresses move constructor creation
+};
+
+struct J : I {
+  J(J &&RHS) : I(RHS) {} // ok
+};
+
+struct K {}; // Has implicit copy and move constructors, is trivially copyable
+struct L : K {
+  L(L &&RHS) : K(RHS) {} // ok
+};
+
+struct M {
+  B Mem;
+  // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [misc-move-constructor-init]
+  M(M &&RHS) : Mem(RHS.Mem) {}
+};
+
+struct N {
+  B Mem;
+  N(N &&RHS) : Mem(move(RHS.Mem)) {}
+};
+
+struct Movable {
+  Movable(Movable &&) = default;
+  Movable(const Movable &) = default;
+  Movable &operator=(const Movable &) = default;
+  ~Movable() {}
+};
+
+struct TriviallyCopyable {
+  TriviallyCopyable() = default;
+  TriviallyCopyable(TriviallyCopyable &&) = default;
+  TriviallyCopyable(const TriviallyCopyable &) = default;
+};
+
+struct Positive {
+  Positive(Movable M) : M_(M) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to avoid copy [misc-move-constructor-init]
+  // CHECK-FIXES: Positive(Movable M) : M_(std::m

Re: [PATCH] D12839: Extend MoveConstructorInitCheck to also flag constructor arguments passed by value and can be moved assigned to fields.

2015-10-06 Thread Felix Berger via cfe-commits
flx added a comment.

I don't have access, so that'd be great if you or Alex could submit the patch, 
thanks!



Comment at: clang-tidy/misc/MoveConstructorInitCheck.cpp:11
@@ -10,2 +10,3 @@
 #include "MoveConstructorInitCheck.h"
+#include "../utils/Matchers.h"
 #include "clang/AST/ASTContext.h"

aaron.ballman wrote:
> Errr, I'm not certain that we typically use relative paths for this sort of 
> thing. I see we do use relative paths for other things in clang-tidy, but 
> this is definitely an uncommon thing in the rest of the code base (outside of 
> test or example code).
> 
> Not saying you should change anything here, but we may want to consider 
> changing the paths at some point so we are more in line with the rest of the 
> LLVM projects in not using relative include paths.
Leaving this as is for now as all other ClangTidy specific includes I could 
find were relative as well. Not sure if non-relative includes require extra 
work in the build rules.


Comment at: clang-tidy/misc/MoveConstructorInitCheck.cpp:96
@@ +95,3 @@
+
+void MoveConstructorInitCheck::handleMoveConstructor(
+const MatchFinder::MatchResult &Result) {

alexfh wrote:
> Other checks have separate options for the include style (see 
> `PassByValueCheck.cpp`, for example), so this one should have its own option 
> too. If we ever decide to introduce a common option instead, it will be 
> easier to do this, if all usages of the `IncludeInserter` do the same thing 
> with the include style.
> 
> One thing I would change though, is to add the IncludeStyle <-> string 
> conversion functions instead of doing this in each check.
Done. I moved the conversion into IncludeSorter where the the enum is defined.


Comment at: clang-tidy/modernize/PassByValueCheck.cpp:121
@@ -120,4 +120,3 @@
 : ClangTidyCheck(Name, Context),
-  IncludeStyle(Options.get("IncludeStyle", "llvm") == "llvm" ?
-   IncludeSorter::IS_LLVM : IncludeSorter::IS_Google) {}
+  IncludeStyle(IncludeSorter::toIncludeStyle(Options.get("IncludeStyle", 
"llvm"))) {}
 

alexfh wrote:
> clang-format?
This is how clang-format formatted it. I used the following invocation:

clang-format --style=LLVM MoveConstructorInitCheck.cpp  > formatted

And then diffed to only update format changes in code I added.


Comment at: clang-tidy/utils/IncludeSorter.h:29
@@ +28,3 @@
+  // Converts "llvm" to IS_LLVM, otherwise returns IS_Google.
+  static IncludeStyle toIncludeStyle(const std::string &Value);
+

alexfh wrote:
> nit: The current name gives no hints at what is being converted to 
> IncludeStyle, but `parseIncludeStyle` would make it clear that the source is 
> a string.
Done, although the argument type uniquely identifies a function.


Comment at: clang-tidy/utils/Matchers.h:1
@@ +1,2 @@
+//===--- Matchers.h - 
clang-tidy---===//
+//

aaron.ballman wrote:
> You are missing header include guards.
Thanks for catching that. Done.


Comment at: clang-tidy/utils/TypeTraits.cpp:32
@@ +31,3 @@
+  // Ignore trivially copyable types.
+  return !(Type->isScalarType() || Type.isTriviallyCopyableType(Context) ||
+   classHasTrivialCopyAndDestroy(Type));

aaron.ballman wrote:
> No need to check for isScalarType() because isTriviallyCopyableType() already 
> does that correctly.
Done. Also demorganized the expression to make it easier to understand.


Comment at: clang-tidy/utils/TypeTraits.h:22
@@ +21,3 @@
+/// destructor.
+bool classHasTrivialCopyAndDestroy(QualType Type);
+

aaron.ballman wrote:
> I think this is an implementation detail more than a trait we want to expose.
Removed from header.


http://reviews.llvm.org/D12839



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-04 Thread Felix Berger via cfe-commits
flx added a comment.

Hi Alex,

could you take a look at the questions I posted in my last comment. Maybe there 
is some renaming work I can tackle while you review the change in more detail.


http://reviews.llvm.org/D16517



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-07 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 47159.
flx marked 12 inline comments as done.
flx added a comment.

Thanks for the review, Alex!

This is an intermediate updated patch that addresses your detailed comments. 
I'll rename the whole check in the next couple of days and will re-upload again.


http://reviews.llvm.org/D16517

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  clang-tidy/misc/UninitializedFieldCheck.cpp
  clang-tidy/misc/UninitializedFieldCheck.h
  docs/clang-tidy/checks/misc-uninitialized-field.rst
  test/clang-tidy/misc-uninitialized-field-cxx98.cpp
  test/clang-tidy/misc-uninitialized-field.cpp

Index: test/clang-tidy/misc-uninitialized-field.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-uninitialized-field.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s misc-uninitialized-field %t
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : J(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K
+  // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+  int I;
+  // CHECK-FIXES: int I{};
+  int J;
+  int K;
+  // CHECK-FIXES: int K{};
+};
+
+template 
+struct Template {
+  Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  T T1;
+  // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+  Template TInt;
+}
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+
+struct NegativeInClassInitialized {
+  int F = 0;
+
+  NegativeInClassInitialized() {}
+};
+
+struct NegativeConstructorDelegated {
+  int F;
+
+  NegativeConstructorDelegated(int F) : F(F) {}
+  NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
Index: test/clang-tidy/misc-uninitialized-field-cxx98.cpp
===
--- /dev/null
+++ test/clang-tidy/misc-uninitialized-field-cxx98.cpp
@@ -0,0 +1,65 @@
+// RUN: %check_clang_tidy %s misc-uninitialized-field %t -- -- -std=c++98
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
+  // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), G(), H() {}
+  int F;
+  bool G /* with comment */;
+  int *H;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() : F() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : /* some comment */ J(0), L(0), M(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K, N
+  // CHECK-FIXES: PositiveMixedFieldOrder() : I(), /* some comment */ J(0), K(), L(0), M(0), N() {}
+  int I;
+  int J;
+  int K;
+  int L;
+  int M;
+  int N;
+};
+
+struct PositiveAfterBaseInitializer : public Positiv

Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-08 Thread Felix Berger via cfe-commits
flx added inline comments.


Comment at: clang-tidy/misc/UninitializedFieldCheck.cpp:178
@@ +177,3 @@
+
+  SmallPtrSet FieldsToInit;
+  fieldsRequiringInit(MemberFields, FieldsToInit);

alexfh wrote:
> What about this? (relates to line 184 now)
My comment on this was not submitted, just in case. Here it is again:

I think he idea is to return immediately if we're delegating to another 
constructor here. Am I misunderstanding the API call?

The important part is that we return in that case.


Comment at: clang-tidy/misc/UninitializedFieldCheck.cpp:124
@@ +123,3 @@
+  std::vector OrderedFields;
+  OrderedFields.push_back({LastWrittenNonMemberInit, nullptr, {}});
+

alexfh wrote:
> `.emplace_back(...)`?
Gave a compile error. Probably because there is no explicit constructor with 
the 3 arguments.


Comment at: clang-tidy/misc/UninitializedFieldCheck.cpp:177
@@ +176,3 @@
+  for (CXXCtorInitializer *Init : Ctor->inits()) {
+if (Init->isDelegatingInitializer())
+  return;

alexfh wrote:
> I think, this is superfluous. `isMemberInitializer()` should be enough.
I think he idea is to return immediately if we're delegating to another 
constructor here. Is this covered through some other check?


Comment at: clang-tidy/misc/UninitializedFieldCheck.cpp:199
@@ +198,3 @@
+
+for (const auto *Field : FieldsToInit)
+  Builder << FixItHint::CreateInsertion(

alexfh wrote:
> nit: We don't use braces only for single-line `if/for` bodies. Same below.
Done. This seems really subtle though when it depends on line length instead of 
single statement inside of loop.


Comment at: test/clang-tidy/misc-uninitialized-field.cpp:1
@@ +1,2 @@
+// RUN: %check_clang_tidy %s misc-uninitialized-field %t
+

alexfh wrote:
> As usual: tests with templates and macros, please ;)
Thanks for the reminder. Added early return for code inside of macros. Added 
template test which revealed I had to suppress the check inside of instantiated 
constructors.


http://reviews.llvm.org/D16517



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-08 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 47280.
flx added a comment.

Renamed the check to: cppcoreguidelines-pro-type-member-init, note the extra 
dash between member and init to be consistent with the camelcase notation of 
the class name ProTypeMemberInitCheck.


http://reviews.llvm.org/D16517

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
  test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : J(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K
+  // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+  int I;
+  // CHECK-FIXES: int I{};
+  int J;
+  int K;
+  // CHECK-FIXES: int K{};
+};
+
+template 
+struct Template {
+  Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  T T1;
+  // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+  Template TInt;
+}
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+
+struct NegativeInClassInitialized {
+  int F = 0;
+
+  NegativeInClassInitialized() {}
+};
+
+struct NegativeConstructorDelegated {
+  int F;
+
+  NegativeConstructorDelegated(int F) : F(F) {}
+  NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
+  // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), G(), H() {}
+  int F;
+  bool G /* with comment */;
+  int *H;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() : F() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : /* some comment */ J(0), L(0), M(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize

[PATCH] D17064: Only invoke ForRangeCopyCheck on expensive-to-copy types.

2016-02-09 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a reviewer: alexfh.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Fix oversight not checking the value of the Optional returned by 
isExpensiveToCopy().

Repository:
  rL LLVM

http://reviews.llvm.org/D17064

Files:
  clang-tidy/performance/ForRangeCopyCheck.cpp
  test/clang-tidy/performance-for-range-copy.cpp

Index: test/clang-tidy/performance-for-range-copy.cpp
===
--- test/clang-tidy/performance-for-range-copy.cpp
+++ test/clang-tidy/performance-for-range-copy.cpp
@@ -127,6 +127,7 @@
 }
 
 void use(const Mutable &M);
+void use(int I);
 void useTwice(const Mutable &M1, const Mutable &M2);
 void useByValue(Mutable M);
 void useByConstValue(const Mutable M);
@@ -170,6 +171,30 @@
   }
 }
 
+void negativeConstCheapToCopy() {
+  for (const int I : View>()) {
+  }
+}
+
+void negativeConstCheapToCopyTypedef() {
+  typedef const int ConstInt;
+  for (ConstInt C  : View>()) {
+  }
+}
+
+void negativeCheapToCopy() {
+  for (int I : View>()) {
+use(I);
+  }
+}
+
+void negativeCheapToCopyTypedef() {
+  typedef int Int;
+  for (Int I : View>()) {
+use(I);
+  }
+}
+
 void positiveOnlyConstMethodInvoked() {
   for (auto M : View>()) {
 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but 
only used as const reference; consider making it a const reference 
[performance-for-range-copy]
Index: clang-tidy/performance/ForRangeCopyCheck.cpp
===
--- clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -135,7 +135,9 @@
   } else if (!LoopVar.getType().isConstQualified()) {
 return false;
   }
-  if (!type_traits::isExpensiveToCopy(LoopVar.getType(), Context))
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (!Expensive || !*Expensive)
 return false;
   auto Diagnostic =
   diag(LoopVar.getLocation(),
@@ -150,8 +152,9 @@
 bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
 const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
 ASTContext &Context) {
-  if (LoopVar.getType().isConstQualified() ||
-  !type_traits::isExpensiveToCopy(LoopVar.getType(), Context)) {
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive) {
 return false;
   }
   // Collect all DeclRefExprs to the loop variable and all CallExprs and


Index: test/clang-tidy/performance-for-range-copy.cpp
===
--- test/clang-tidy/performance-for-range-copy.cpp
+++ test/clang-tidy/performance-for-range-copy.cpp
@@ -127,6 +127,7 @@
 }
 
 void use(const Mutable &M);
+void use(int I);
 void useTwice(const Mutable &M1, const Mutable &M2);
 void useByValue(Mutable M);
 void useByConstValue(const Mutable M);
@@ -170,6 +171,30 @@
   }
 }
 
+void negativeConstCheapToCopy() {
+  for (const int I : View>()) {
+  }
+}
+
+void negativeConstCheapToCopyTypedef() {
+  typedef const int ConstInt;
+  for (ConstInt C  : View>()) {
+  }
+}
+
+void negativeCheapToCopy() {
+  for (int I : View>()) {
+use(I);
+  }
+}
+
+void negativeCheapToCopyTypedef() {
+  typedef int Int;
+  for (Int I : View>()) {
+use(I);
+  }
+}
+
 void positiveOnlyConstMethodInvoked() {
   for (auto M : View>()) {
 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
Index: clang-tidy/performance/ForRangeCopyCheck.cpp
===
--- clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -135,7 +135,9 @@
   } else if (!LoopVar.getType().isConstQualified()) {
 return false;
   }
-  if (!type_traits::isExpensiveToCopy(LoopVar.getType(), Context))
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (!Expensive || !*Expensive)
 return false;
   auto Diagnostic =
   diag(LoopVar.getLocation(),
@@ -150,8 +152,9 @@
 bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
 const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
 ASTContext &Context) {
-  if (LoopVar.getType().isConstQualified() ||
-  !type_traits::isExpensiveToCopy(LoopVar.getType(), Context)) {
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive) {
 return false;
   }
   // Collect all DeclRefExprs to the loop variable and all CallExprs and
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-10 Thread Felix Berger via cfe-commits
flx added inline comments.


Comment at: clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp:205
@@ +204,3 @@
+  Diag << FixItHint::CreateInsertion(
+  Field->getSourceRange().getEnd().getLocWithOffset(
+  Field->getName().size()),

alexfh wrote:
> Maybe Lexer::getLocForEndOfToken?
Tried:

Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(),
 Field->getName().size(),
 Result.Context->getSourceManager(),
 Result.Context->getLangOpts()),

but that placed the {} before the field name:

-  bool G /* with comment */;
+  bool {}G /* with comment */;
 




http://reviews.llvm.org/D16517



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-10 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 47590.
flx marked 3 inline comments as done.

http://reviews.llvm.org/D16517

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
  docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
  test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,107 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : J(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K
+  // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+  int I;
+  // CHECK-FIXES: int I{};
+  int J;
+  int K;
+  // CHECK-FIXES: int K{};
+};
+
+template 
+struct Template {
+  Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  T T1;
+  // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+  Template TInt;
+}
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+
+struct NegativeInClassInitialized {
+  int F = 0;
+
+  NegativeInClassInitialized() {}
+};
+
+struct NegativeConstructorDelegated {
+  int F;
+
+  NegativeConstructorDelegated(int F) : F(F) {}
+  NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
+  struct UninitializedField##FIELD {		 \
+UninitializedField##FIELD() {}		 \
+int FIELD;	 \
+  };		 \
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: G
+
+#define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \
+  ARGUMENT		\
+
+UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg {
+  UninitializedFieldInMacroArg() {}
+  int Field;
+});
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these built-in/pointer fields: Field
Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
+  // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), G(), H() {}
+  int F;
+  bool G /* with comment */;
+  int *H;
+  PositiveFieldBeforeCon

Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-10 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 47594.
flx added a comment.

Added comment that we're returning early if this constructor simply delegates 
to another constructor.


http://reviews.llvm.org/D16517

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
  docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
  test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,107 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : J(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K
+  // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+  int I;
+  // CHECK-FIXES: int I{};
+  int J;
+  int K;
+  // CHECK-FIXES: int K{};
+};
+
+template 
+struct Template {
+  Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  T T1;
+  // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+  Template TInt;
+}
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+
+struct NegativeInClassInitialized {
+  int F = 0;
+
+  NegativeInClassInitialized() {}
+};
+
+struct NegativeConstructorDelegated {
+  int F;
+
+  NegativeConstructorDelegated(int F) : F(F) {}
+  NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
+  struct UninitializedField##FIELD {		 \
+UninitializedField##FIELD() {}		 \
+int FIELD;	 \
+  };		 \
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: G
+
+#define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \
+  ARGUMENT		\
+
+UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg {
+  UninitializedFieldInMacroArg() {}
+  int Field;
+});
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these built-in/pointer fields: Field
Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
+  // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), 

Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-11 Thread Felix Berger via cfe-commits
flx updated this revision to Diff 47757.
flx marked 2 inline comments as done.

http://reviews.llvm.org/D16517

Files:
  clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
  docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
  test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : J(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K
+  // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
+  int I;
+  // CHECK-FIXES: int I{};
+  int J;
+  int K;
+  // CHECK-FIXES: int K{};
+};
+
+template 
+struct Template {
+  Template() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  int F;
+  // CHECK-FIXES: int F{};
+  T T1;
+  // CHECK-FIXES: T T1;
+};
+
+void instantiate() {
+  Template TInt;
+}
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+
+struct NegativeInClassInitialized {
+  int F = 0;
+
+  NegativeInClassInitialized() {}
+};
+
+struct NegativeConstructorDelegated {
+  int F;
+
+  NegativeConstructorDelegated(int F) : F(F) {}
+  NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
+};
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
+
+#define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
+  struct UninitializedField##FIELD {		 \
+UninitializedField##FIELD() {}		 \
+int FIELD;	 \
+  };		 \
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int FIELD;		
+
+UNINITIALIZED_FIELD_IN_MACRO_BODY(F);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+UNINITIALIZED_FIELD_IN_MACRO_BODY(G);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: G
+
+#define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \
+  ARGUMENT		\
+
+UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg {
+  UninitializedFieldInMacroArg() {}
+  int Field;
+});
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these built-in/pointer fields: Field
+// Ensure FIELD is not initialized since fixes inside of macros are disabled.
+// CHECK-FIXES: int Field;
Index: test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
===
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: c

Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-11 Thread Felix Berger via cfe-commits
flx added inline comments.


Comment at: clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp:206
@@ +205,3 @@
+  // Do not propose fixes in macros since we cannot place them correctly.
+  if (Ctor->getLocStart().isMacroID())
+return;

alexfh wrote:
> IIUC what this is doing, the offset should be `0` instead of 
> `Field->getName().size()`. I've tried 
> `Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0, 
> *Result.SourceManager, Result.Context->getLangOpts())` and it seems to work 
> fine on your tests.
Great, that worked.


http://reviews.llvm.org/D16517



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r260869 - Improve documentation

2016-02-14 Thread Felix Berger via cfe-commits
Author: flx
Date: Sun Feb 14 21:27:54 2016
New Revision: 260869

URL: http://llvm.org/viewvc/llvm-project?rev=260869&view=rev
Log:
Improve documentation

Modified:

clang-tools-extra/trunk/docs/clang-tidy/checks/performance-for-range-copy.rst

Modified: 
clang-tools-extra/trunk/docs/clang-tidy/checks/performance-for-range-copy.rst
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/performance-for-range-copy.rst?rev=260869&r1=260868&r2=260869&view=diff
==
--- 
clang-tools-extra/trunk/docs/clang-tidy/checks/performance-for-range-copy.rst 
(original)
+++ 
clang-tools-extra/trunk/docs/clang-tidy/checks/performance-for-range-copy.rst 
Sun Feb 14 21:27:54 2016
@@ -10,8 +10,8 @@ The check is only applied to loop variab
 which means they are not trivially copyable or have a non-trivial copy
 constructor or destructor.
 
-To ensure that it is safe to replace the copy with const reference the 
following
-heuristic is employed:
+To ensure that it is safe to replace the copy with a const reference the
+following heuristic is employed:
 
 1. The loop variable is const qualified.
 2. The loop variable is not const, but only const methods or operators are


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r260870 - [clang-tidy] Only invoke ForRangeCopyCheck on expensive-to-copy types.

2016-02-14 Thread Felix Berger via cfe-commits
Author: flx
Date: Sun Feb 14 21:36:23 2016
New Revision: 260870

URL: http://llvm.org/viewvc/llvm-project?rev=260870&view=rev
Log:
[clang-tidy] Only invoke ForRangeCopyCheck on expensive-to-copy types.

Summary:
Fix oversight not checking the value of the Optional returned by
isExpensiveToCopy().

Reviewers: alexfh

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D17064

Modified:
clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp

Modified: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp?rev=260870&r1=260869&r2=260870&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp Sun 
Feb 14 21:36:23 2016
@@ -135,7 +135,9 @@ bool ForRangeCopyCheck::handleConstValue
   } else if (!LoopVar.getType().isConstQualified()) {
 return false;
   }
-  if (!type_traits::isExpensiveToCopy(LoopVar.getType(), Context))
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (!Expensive || !*Expensive)
 return false;
   auto Diagnostic =
   diag(LoopVar.getLocation(),
@@ -150,8 +152,9 @@ bool ForRangeCopyCheck::handleConstValue
 bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
 const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
 ASTContext &Context) {
-  if (LoopVar.getType().isConstQualified() ||
-  !type_traits::isExpensiveToCopy(LoopVar.getType(), Context)) {
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive) {
 return false;
   }
   // Collect all DeclRefExprs to the loop variable and all CallExprs and

Modified: clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp?rev=260870&r1=260869&r2=260870&view=diff
==
--- clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp 
(original)
+++ clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp Sun 
Feb 14 21:36:23 2016
@@ -127,6 +127,7 @@ bool operator!=(const Mutable& M1, const
 }
 
 void use(const Mutable &M);
+void use(int I);
 void useTwice(const Mutable &M1, const Mutable &M2);
 void useByValue(Mutable M);
 void useByConstValue(const Mutable M);
@@ -170,6 +171,30 @@ void negativeNonConstNonMemberOperatorIn
   }
 }
 
+void negativeConstCheapToCopy() {
+  for (const int I : View>()) {
+  }
+}
+
+void negativeConstCheapToCopyTypedef() {
+  typedef const int ConstInt;
+  for (ConstInt C  : View>()) {
+  }
+}
+
+void negativeCheapToCopy() {
+  for (int I : View>()) {
+use(I);
+  }
+}
+
+void negativeCheapToCopyTypedef() {
+  typedef int Int;
+  for (Int I : View>()) {
+use(I);
+  }
+}
+
 void positiveOnlyConstMethodInvoked() {
   for (auto M : View>()) {
 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but 
only used as const reference; consider making it a const reference 
[performance-for-range-copy]


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D17064: Only invoke ForRangeCopyCheck on expensive-to-copy types.

2016-02-14 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL260870: [clang-tidy] Only invoke ForRangeCopyCheck on 
expensive-to-copy types. (authored by flx).

Changed prior to commit:
  http://reviews.llvm.org/D17064?vs=47419&id=47940#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D17064

Files:
  clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp

Index: clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
@@ -127,6 +127,7 @@
 }
 
 void use(const Mutable &M);
+void use(int I);
 void useTwice(const Mutable &M1, const Mutable &M2);
 void useByValue(Mutable M);
 void useByConstValue(const Mutable M);
@@ -170,6 +171,30 @@
   }
 }
 
+void negativeConstCheapToCopy() {
+  for (const int I : View>()) {
+  }
+}
+
+void negativeConstCheapToCopyTypedef() {
+  typedef const int ConstInt;
+  for (ConstInt C  : View>()) {
+  }
+}
+
+void negativeCheapToCopy() {
+  for (int I : View>()) {
+use(I);
+  }
+}
+
+void negativeCheapToCopyTypedef() {
+  typedef int Int;
+  for (Int I : View>()) {
+use(I);
+  }
+}
+
 void positiveOnlyConstMethodInvoked() {
   for (auto M : View>()) {
 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but 
only used as const reference; consider making it a const reference 
[performance-for-range-copy]
Index: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -135,7 +135,9 @@
   } else if (!LoopVar.getType().isConstQualified()) {
 return false;
   }
-  if (!type_traits::isExpensiveToCopy(LoopVar.getType(), Context))
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (!Expensive || !*Expensive)
 return false;
   auto Diagnostic =
   diag(LoopVar.getLocation(),
@@ -150,8 +152,9 @@
 bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
 const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
 ASTContext &Context) {
-  if (LoopVar.getType().isConstQualified() ||
-  !type_traits::isExpensiveToCopy(LoopVar.getType(), Context)) {
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive) {
 return false;
   }
   // Collect all DeclRefExprs to the loop variable and all CallExprs and


Index: clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/performance-for-range-copy.cpp
@@ -127,6 +127,7 @@
 }
 
 void use(const Mutable &M);
+void use(int I);
 void useTwice(const Mutable &M1, const Mutable &M2);
 void useByValue(Mutable M);
 void useByConstValue(const Mutable M);
@@ -170,6 +171,30 @@
   }
 }
 
+void negativeConstCheapToCopy() {
+  for (const int I : View>()) {
+  }
+}
+
+void negativeConstCheapToCopyTypedef() {
+  typedef const int ConstInt;
+  for (ConstInt C  : View>()) {
+  }
+}
+
+void negativeCheapToCopy() {
+  for (int I : View>()) {
+use(I);
+  }
+}
+
+void negativeCheapToCopyTypedef() {
+  typedef int Int;
+  for (Int I : View>()) {
+use(I);
+  }
+}
+
 void positiveOnlyConstMethodInvoked() {
   for (auto M : View>()) {
 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: loop variable is copied but only used as const reference; consider making it a const reference [performance-for-range-copy]
Index: clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -135,7 +135,9 @@
   } else if (!LoopVar.getType().isConstQualified()) {
 return false;
   }
-  if (!type_traits::isExpensiveToCopy(LoopVar.getType(), Context))
+  llvm::Optional Expensive =
+  type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
+  if (!Expensive || !*Expensive)
 return false;
   auto Diagnostic =
   diag(LoopVar.getLocation(),
@@ -150,8 +152,9 @@
 bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
 const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
 ASTContext &Context) {
-  if (LoopVar.getType().isConstQualified() ||
-  !type_traits::isExpensiveToCopy(LoopVar.getType(), Context)) {
+  llvm::Optional Expensive =
+  type_traits::isExpen

r260872 - Add isAnyPointer() matchers. Register missing matchers.

2016-02-14 Thread Felix Berger via cfe-commits
Author: flx
Date: Sun Feb 14 22:00:39 2016
New Revision: 260872

URL: http://llvm.org/viewvc/llvm-project?rev=260872&view=rev
Log:
Add isAnyPointer() matchers. Register missing matchers.

Summary:
The isAnyPointer() matcher is useful for http://reviews.llvm.org/D15623.

Reviewers: alexfh, klimek

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D15819

Modified:
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=260872&r1=260871&r2=260872&view=diff
==
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sun Feb 14 22:00:39 2016
@@ -3673,6 +3673,19 @@ AST_MATCHER(QualType, isAnyCharacter) {
 return Node->isAnyCharacterType();
 }
 
+ \brief Matches QualType nodes that are of any pointer type.
+///
+/// Given
+/// \code
+///   int *i = nullptr;
+///   int j;
+/// \endcode
+/// varDecl(hasType(isAnyPointer()))
+///   matches "int *i", but not "int j".
+AST_MATCHER(QualType, isAnyPointer) {
+  return Node->isAnyPointerType();
+}
+
 /// \brief Matches QualType nodes that are const-qualified, i.e., that
 /// include "top-level" const.
 ///

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=260872&r1=260871&r2=260872&view=diff
==
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Sun Feb 14 22:00:39 2016
@@ -264,6 +264,8 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(innerType);
   REGISTER_MATCHER(integerLiteral);
   REGISTER_MATCHER(isAnonymous);
+  REGISTER_MATCHER(isAnyCharacter);
+  REGISTER_MATCHER(isAnyPointer);
   REGISTER_MATCHER(isArrow);
   REGISTER_MATCHER(isBaseInitializer);
   REGISTER_MATCHER(isCatchAll);

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=260872&r1=260871&r2=260872&view=diff
==
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Sun Feb 14 22:00:39 2016
@@ -1479,6 +1479,14 @@ TEST(IsInteger, ReportsNoFalsePositives)
   to(varDecl(hasType(isInteger();
 }
 
+TEST(IsAnyPointer, MatchesPointers) {
+  EXPECT_TRUE(matches("int* i = nullptr;", varDecl(hasType(isAnyPointer();
+}
+
+TEST(IsAnyPointer, ReportsNoFalsePositives) {
+  EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isAnyPointer();
+}
+
 TEST(IsAnyCharacter, MatchesCharacters) {
   EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter();
 }


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16517: ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-14 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL260873: [clang-tidy] ClangTidy check to flag uninitialized 
builtin and pointer fields. (authored by flx).

Changed prior to commit:
  http://reviews.llvm.org/D16517?vs=47757&id=47942#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D16517

Files:
  clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt
  
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
  
clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst
  clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
  
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Index: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
@@ -0,0 +1,67 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++98
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  PositiveFieldBeforeConstructor() /* some comment */ {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() : F() /* some comment */ {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
+  // CHECK-FIXES: PositiveFieldAfterConstructor() : F(), G(), H() {}
+  int F;
+  bool G /* with comment */;
+  int *H;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/pointer fields: F
+// CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() : F() {}
+
+struct PositiveMixedFieldOrder {
+  PositiveMixedFieldOrder() : /* some comment */ J(0), L(0), M(0) {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: I, K, N
+  // CHECK-FIXES: PositiveMixedFieldOrder() : I(), /* some comment */ J(0), K(), L(0), M(0), N() {}
+  int I;
+  int J;
+  int K;
+  int L;
+  int M;
+  int N;
+};
+
+struct PositiveAfterBaseInitializer : public PositiveMixedFieldOrder {
+  PositiveAfterBaseInitializer() : PositiveMixedFieldOrder() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveAfterBaseInitializer() : PositiveMixedFieldOrder(), F() {}
+  int F;
+};
+
+struct NegativeFieldInitialized {
+  int F;
+
+  NegativeFieldInitialized() : F() {}
+};
+
+struct NegativeFieldInitializedInDefinition {
+  int F;
+
+  NegativeFieldInitializedInDefinition();
+};
+
+NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
+
+struct NegativeInitializedInBody {
+  NegativeInitializedInBody() { I = 0; }
+  int I;
+};
+
+
Index: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -0,0 +1,111 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t
+
+struct PositiveFieldBeforeConstructor {
+  int F;
+  // CHECK-FIXES: int F{};
+  PositiveFieldBeforeConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F
+  // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
+};
+
+struct PositiveFieldAfterConstructor {
+  PositiveFieldAfterConstructor() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G
+  // CHECK-FIXES: PositiveFieldAfterConstructor() {}
+  int F;
+  // CHECK-FIXES: int F{};
+  bool G /* with comment */;
+  // CHECK-FIXES: bool G{} /* with comment */;
+  PositiveFieldBeforeConstructor IgnoredField;
+};
+
+struct PositiveSeparateDefinition {
+  PositiveSeparateDefinition();
+  int F;
+  // CHECK-FIXES: int F{};
+};
+
+PositiveSeparateDefinition::PositiveSeparateDefinition() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these built-in/po

[clang-tools-extra] r260873 - [clang-tidy] ClangTidy check to flag uninitialized builtin and pointer fields.

2016-02-14 Thread Felix Berger via cfe-commits
Author: flx
Date: Sun Feb 14 22:27:56 2016
New Revision: 260873

URL: http://llvm.org/viewvc/llvm-project?rev=260873&view=rev
Log:
[clang-tidy] ClangTidy check to flag uninitialized builtin and pointer fields.

Summary:
This patch is a continuation of http://reviews.llvm.org/D10553 by Jonathan B 
Coe.

The main additions are:

1. For C++11 the check suggests in-class field initialization as fix. This
makes the fields future proof towards the addition of new constructors.
2 For older language versions the fields are added in the right position
in the initializer list with more tests.
3. User documentation.

Reviewers: alexfh, jbcoe

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D16517

Added:

clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp

clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h

clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst

clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp

clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt

clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt?rev=260873&r1=260872&r2=260873&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt 
(original)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt Sun Feb 
14 22:27:56 2016
@@ -7,6 +7,7 @@ add_clang_library(clangTidyCppCoreGuidel
   ProBoundsPointerArithmeticCheck.cpp
   ProTypeConstCastCheck.cpp
   ProTypeCstyleCastCheck.cpp
+  ProTypeMemberInitCheck.cpp
   ProTypeReinterpretCastCheck.cpp
   ProTypeStaticCastDowncastCheck.cpp
   ProTypeUnionAccessCheck.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=260873&r1=260872&r2=260873&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
 (original)
+++ 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
 Sun Feb 14 22:27:56 2016
@@ -16,6 +16,7 @@
 #include "ProBoundsPointerArithmeticCheck.h"
 #include "ProTypeConstCastCheck.h"
 #include "ProTypeCstyleCastCheck.h"
+#include "ProTypeMemberInitCheck.h"
 #include "ProTypeReinterpretCastCheck.h"
 #include "ProTypeStaticCastDowncastCheck.h"
 #include "ProTypeUnionAccessCheck.h"
@@ -39,6 +40,8 @@ public:
 "cppcoreguidelines-pro-type-const-cast");
 CheckFactories.registerCheck(
 "cppcoreguidelines-pro-type-cstyle-cast");
+CheckFactories.registerCheck(
+"cppcoreguidelines-pro-type-member-init");
 CheckFactories.registerCheck(
 "cppcoreguidelines-pro-type-reinterpret-cast");
 CheckFactories.registerCheck(

Added: 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp?rev=260873&view=auto
==
--- 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
(added)
+++ 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
Sun Feb 14 22:27:56 2016
@@ -0,0 +1,231 @@
+//===--- ProTypeMemberInitCheck.cpp - 
clang-tidy---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "ProTypeMemberInitCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace clang::ast_matchers;
+using llvm::SmallPtrSet;
+using llvm::SmallPtrSetImpl;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+namespace {
+
+AST_MATCHER(CXXConstructorDecl, isUserProvided) {
+  return Node.isUserProvided();
+}
+
+static void
+fieldsRequiringInit(const RecordDecl::field_range &Fields,
+SmallPtrSetImpl &FieldsToInit) {
+  for (const FieldDecl *F : Fields) {
+QualType Type = F->getType()

Re: r260872 - Add isAnyPointer() matchers. Register missing matchers.

2016-02-20 Thread Felix Berger via cfe-commits
On Mon, Feb 15, 2016 at 8:05 AM, Aaron Ballman 
wrote:

> On Sun, Feb 14, 2016 at 11:00 PM, Felix Berger via cfe-commits
>  wrote:
> > Author: flx
> > Date: Sun Feb 14 22:00:39 2016
> > New Revision: 260872
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=260872&view=rev
> > Log:
> > Add isAnyPointer() matchers. Register missing matchers.
> >
> > Summary:
> > The isAnyPointer() matcher is useful for http://reviews.llvm.org/D15623.
> >
> > Reviewers: alexfh, klimek
> >
> > Subscribers: cfe-commits
> >
> > Differential Revision: http://reviews.llvm.org/D15819
> >
> > Modified:
> > cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
> > cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
> > cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
> >
> > Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=260872&r1=260871&r2=260872&view=diff
> >
> ==
> > --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
> > +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sun Feb 14
> 22:00:39 2016
> > @@ -3673,6 +3673,19 @@ AST_MATCHER(QualType, isAnyCharacter) {
> >  return Node->isAnyCharacterType();
> >  }
> >
> > + \brief Matches QualType nodes that are of any pointer type.
> > +///
> > +/// Given
> > +/// \code
> > +///   int *i = nullptr;
> > +///   int j;
> > +/// \endcode
> > +/// varDecl(hasType(isAnyPointer()))
> > +///   matches "int *i", but not "int j".
> > +AST_MATCHER(QualType, isAnyPointer) {
> > +  return Node->isAnyPointerType();
> > +}
>
> The whole point to isAnyPointer() is for objective C types, where
> pointers are modeled differently. Can you add documentation, an
> example, and tests for that fact?
>
>
Thanks for making me look into this further. After looking through the
existing test cases and matchers I found there is already a pointerType()
matcher which is the matcher I originally wanted to expose.

I can do one of two things now:

   1. Keep the new isAnyPointer() matcher if we think it's useful and add
   an objc pointer test for it which is already in the works.
   2. Remove the matcher again since there is no real need for it and users
   could get the same by writing anyOf(pointerType(), objcObjectPointerType())

What do you think?


> ~Aaron
>
> > +
> >  /// \brief Matches QualType nodes that are const-qualified, i.e., that
> >  /// include "top-level" const.
> >  ///
> >
> > Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=260872&r1=260871&r2=260872&view=diff
> >
> ==
> > --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
> > +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Sun Feb 14 22:00:39
> 2016
> > @@ -264,6 +264,8 @@ RegistryMaps::RegistryMaps() {
> >REGISTER_MATCHER(innerType);
> >REGISTER_MATCHER(integerLiteral);
> >REGISTER_MATCHER(isAnonymous);
> > +  REGISTER_MATCHER(isAnyCharacter);
> > +  REGISTER_MATCHER(isAnyPointer);
> >REGISTER_MATCHER(isArrow);
> >REGISTER_MATCHER(isBaseInitializer);
> >REGISTER_MATCHER(isCatchAll);
> >
> > Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=260872&r1=260871&r2=260872&view=diff
> >
> ==
> > --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
> > +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Sun Feb 14
> 22:00:39 2016
> > @@ -1479,6 +1479,14 @@ TEST(IsInteger, ReportsNoFalsePositives)
> >to(varDecl(hasType(isInteger();
> >  }
> >
> > +TEST(IsAnyPointer, MatchesPointers) {
> > +  EXPECT_TRUE(matches("int* i = nullptr;",
> varDecl(hasType(isAnyPointer();
> > +}
> > +
> > +TEST(IsAnyPointer, ReportsNoFalsePositives) {
> > +  EXPECT_TRUE(notMatches("int i = 0;",
> varDecl(hasType(isAnyPointer();
> > +}
> > +
> >  TEST(IsAnyCharacter, MatchesCharacters) {
> >EXPECT_TRUE(matches("char i = 0;",
> varDecl(hasType(isAnyCharacter();
> >  }
> >
> >
> > ___
> > cfe-commits mailing list
> > cfe-commits@lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D17488: Extend UnnecessaryCopyInitialization check to trigger on non-const copies that can be safely converted to const references.

2016-02-20 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a reviewer: alexfh.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Move code shared between UnnecessaryCopyInitialization and ForRangeCopyCheck 
into utilities files.
Add more test cases for UnnecessaryCopyInitialization and disable fixes inside 
of macros.

Repository:
  rL LLVM

http://reviews.llvm.org/D17488

Files:
  clang-tidy/performance/ForRangeCopyCheck.cpp
  clang-tidy/performance/UnnecessaryCopyInitialization.cpp
  clang-tidy/performance/UnnecessaryCopyInitialization.h
  clang-tidy/utils/CMakeLists.txt
  clang-tidy/utils/DeclRefExprUtils.cpp
  clang-tidy/utils/DeclRefExprUtils.h
  clang-tidy/utils/FixItHintUtils.cpp
  clang-tidy/utils/FixItHintUtils.h
  test/clang-tidy/performance-unnecessary-copy-initialization.cpp

Index: test/clang-tidy/performance-unnecessary-copy-initialization.cpp
===
--- test/clang-tidy/performance-unnecessary-copy-initialization.cpp
+++ test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -4,6 +4,7 @@
   ExpensiveToCopyType() {}
   virtual ~ExpensiveToCopyType() {}
   const ExpensiveToCopyType &reference() const { return *this; }
+  void nonConstMethod() {}
 };
 
 struct TrivialToCopyType {
@@ -20,6 +21,11 @@
   return *Type;
 }
 
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
 void PositiveFunctionCall() {
   const auto AutoAssigned = ExpensiveTypeReference();
   // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
@@ -114,11 +120,53 @@
   static const auto StaticVar = Obj.reference();
 }
 
-void NegativeFunctionCallExpensiveTypeNonConstVariable() {
+void PositiveFunctionCallExpensiveTypeNonConstVariable() {
   auto AutoAssigned = ExpensiveTypeReference();
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoAssigned' is copy-constructed from a const reference but is only used as const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
+  // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
   auto AutoCopyConstructed(ExpensiveTypeReference());
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable
+  // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
   ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable
+  // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
   ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable
+  // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
+}
+
+void positiveNonConstVarInCodeBlock(const ExpensiveToCopyType &Obj) {
+  {
+auto Assigned = Obj.reference();
+// CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable
+// CHECK-FIXES: const auto& Assigned = Obj.reference();
+Assigned.reference();
+useAsConstReference(Assigned);
+useByValue(Assigned);
+  }
+}
+
+void negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType &Obj) {
+  {
+auto NonConstInvoked = Obj.reference();
+// CHECK-FIXES: auto NonConstInvoked = Obj.reference();
+NonConstInvoked.nonConstMethod();
+  }
+  {
+auto Reassigned = Obj.reference();
+// CHECK-FIXES: auto Reassigned = Obj.reference();
+Reassigned = ExpensiveToCopyType();
+  }
+  {
+auto MutatedByReference = Obj.reference();
+// CHECK-FIXES: auto MutatedByReference = Obj.reference();
+mutate(MutatedByReference);
+  }
+  {
+auto MutatedByPointer = Obj.reference();
+// CHECK-FIXES: auto MutatedByPointer = Obj.reference();
+mutate(&MutatedByPointer);
+  }
 }
 
 void NegativeMethodCallNonConstRef(ExpensiveToCopyType &Obj) {
@@ -146,11 +194,32 @@
   ExpensiveToCopyType Obj;
   const auto AutoAssigned = Obj.reference();
   const auto AutoCopyConstructed(Obj.reference());
-  const ExpensiveToCopyType VarAssigned = Obj.reference();
-  const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  ExpensiveToCopyType VarAssigned = Obj.reference();
+  ExpensiveToCopyType VarCopyConstructed(Obj.reference());
 }
 
 struct NegativeConstructor {
   NegativeConstructor(const ExpensiveToCopyType &Obj) : Obj(Obj) {}
   ExpensiveToCopyType Obj;
 };
+
+#define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE)	\
+  void functionWith##TYPE(const TYPE& T) {		\
+auto AssignedInMacro = T.reference();		\
+  }			\
+// Ensure fix is not applied.
+// CHECK-FIXES: auto AssignedInMacro = T.reference();
+
+
+UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the variable 'AssignedInMacro' is 

[PATCH] D17491: Add performance check to flag function parameters of expensive to copy types that can be safely converted to const references.

2016-02-21 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a reviewer: alexfh.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

The patch uses [[ http://reviews.llvm.org/D17488 | D17488 ]] as diff base. Once 
D17488 is submitted I'll update the diffbase to head.

Repository:
  rL LLVM

http://reviews.llvm.org/D17491

Files:
  clang-tidy/performance/CMakeLists.txt
  clang-tidy/performance/PerformanceTidyModule.cpp
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  clang-tidy/performance/UnnecessaryValueParamCheck.h
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/performance-unnecessary-value-param.rst
  test/clang-tidy/performance-unnecessary-value-param.cpp

Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- /dev/null
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -0,0 +1,160 @@
+// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t
+
+struct ExpensiveToCopyType {
+  const ExpensiveToCopyType & constReference() const {
+return *this;
+  }
+  void nonConstMethod() {}
+  virtual ~ExpensiveToCopyType() {}
+};
+
+void mutate(ExpensiveToCopyType &);
+void mutate(ExpensiveToCopyType *);
+void useAsConstReference(const ExpensiveToCopyType &);
+void useByValue(ExpensiveToCopyType);
+
+// This class simulates std::pair<>. It is trivially copy constructible
+// and trivially destructible, but not trivially copy assignable.
+class SomewhatTrivial {
+ public:
+  SomewhatTrivial();
+  SomewhatTrivial(const SomewhatTrivial&) = default;
+  ~SomewhatTrivial() = default;
+  SomewhatTrivial& operator=(const SomewhatTrivial&);
+};
+
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
+  // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making this a reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
+}
+
+void positiveExpensiveValue(ExpensiveToCopyType Obj);
+// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
+void positiveExpensiveValue(ExpensiveToCopyType Obj) {
+  // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
+  // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
+  Obj.constReference();
+  useAsConstReference(Obj);
+  auto Copy = Obj;
+  useByValue(Obj);
+}
+
+void positiveWithComment(const ExpensiveToCopyType /* important */ S);
+// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
+void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
+  // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
+  // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
+}
+
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
+// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
+void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
+  // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
+  // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
+  // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
+}
+
+struct PositiveConstValueConstructor {
+  PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
+  // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
+};
+
+template  void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
+  // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S'
+  // CHECK-FIXES: template  void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) {
+}
+
+void instantiated() {
+  templateWithNonTemplatizedParameter(ExpensiveToCopyType(), ExpensiveToCopyType());
+  templateWithNonTemplatizedParameter(ExpensiveToCopyType(), 5);
+}
+
+template  void negativeTemplateType(const T V) {
+}
+
+void negativeArray(const ExpensiveToCopyType[]) {
+}
+
+void negativePointer(ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstPointer(const ExpensiveToCopyType* Obj) {
+}
+
+void negativeConstReference(const ExpensiveToCopyType& Obj) {
+}
+
+void negativeReference(ExpensiveToCopyType& Obj) {
+}
+
+void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
+}
+
+void negativeSomewh

[clang-tools-extra] r268352 - [clang-tidy] ProTypeMemberInitCheck - check that field decls do not have in-class initializer.

2016-05-02 Thread Felix Berger via cfe-commits
Author: flx
Date: Mon May  2 20:41:19 2016
New Revision: 268352

URL: http://llvm.org/viewvc/llvm-project?rev=268352&view=rev
Log:
[clang-tidy] ProTypeMemberInitCheck - check that field decls do not have 
in-class initializer.

Reviewers: alexfh, JVApen, aaron.ballman

Subscribers: flx, aaron.ballman, cfe-commits

Differential Revision: http://reviews.llvm.org/D18300

Modified:

clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp

clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Modified: 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp?rev=268352&r1=268351&r2=268352&view=diff
==
--- 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
(original)
+++ 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
Mon May  2 20:41:19 2016
@@ -31,6 +31,8 @@ void fieldsRequiringInit(const RecordDec
  ASTContext &Context,
  SmallPtrSetImpl &FieldsToInit) {
   for (const FieldDecl *F : Fields) {
+if (F->hasInClassInitializer())
+  continue;
 QualType Type = F->getType();
 if (!F->hasInClassInitializer() &&
 type_traits::isTriviallyDefaultConstructible(Type, Context))

Modified: 
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp?rev=268352&r1=268351&r2=268352&view=diff
==
--- 
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
 (original)
+++ 
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
 Mon May  2 20:41:19 2016
@@ -85,6 +85,14 @@ struct NegativeInitializedInBody {
   int I;
 };
 
+struct A {};
+template  class AA;
+template  class NegativeTemplateConstructor {
+  NegativeTemplateConstructor(const AA &, A) {}
+  bool Bool{false};
+  // CHECK-FIXES: bool Bool{false};
+};
+
 #define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
   struct UninitializedField##FIELD { \
 UninitializedField##FIELD() {}   \


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18300: [clang-tidy] ProTypeMemberInitCheck - check that field decls do not have in-class initializer

2016-05-02 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL268352: [clang-tidy] ProTypeMemberInitCheck - check that 
field decls do not have in… (authored by flx).

Changed prior to commit:
  http://reviews.llvm.org/D18300?vs=51123&id=55934#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D18300

Files:
  
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp

Index: 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
===
--- 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ 
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -31,6 +31,8 @@
  ASTContext &Context,
  SmallPtrSetImpl &FieldsToInit) {
   for (const FieldDecl *F : Fields) {
+if (F->hasInClassInitializer())
+  continue;
 QualType Type = F->getType();
 if (!F->hasInClassInitializer() &&
 type_traits::isTriviallyDefaultConstructible(Type, Context))
Index: 
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- 
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
+++ 
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -85,6 +85,14 @@
   int I;
 };
 
+struct A {};
+template  class AA;
+template  class NegativeTemplateConstructor {
+  NegativeTemplateConstructor(const AA &, A) {}
+  bool Bool{false};
+  // CHECK-FIXES: bool Bool{false};
+};
+
 #define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
   struct UninitializedField##FIELD { \
 UninitializedField##FIELD() {}   \


Index: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -31,6 +31,8 @@
  ASTContext &Context,
  SmallPtrSetImpl &FieldsToInit) {
   for (const FieldDecl *F : Fields) {
+if (F->hasInClassInitializer())
+  continue;
 QualType Type = F->getType();
 if (!F->hasInClassInitializer() &&
 type_traits::isTriviallyDefaultConstructible(Type, Context))
Index: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
@@ -85,6 +85,14 @@
   int I;
 };
 
+struct A {};
+template  class AA;
+template  class NegativeTemplateConstructor {
+  NegativeTemplateConstructor(const AA &, A) {}
+  bool Bool{false};
+  // CHECK-FIXES: bool Bool{false};
+};
+
 #define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
   struct UninitializedField##FIELD { \
 UninitializedField##FIELD() {}   \
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D19849: [clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

2016-05-02 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a reviewer: alexfh.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Repository:
  rL LLVM

http://reviews.llvm.org/D19849

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -96,7 +96,7 @@
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to 
avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument M can be moved to 
avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };
Index: clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -109,8 +109,9 @@
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid 
copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam->getName();
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());


Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -96,7 +96,7 @@
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument M can be moved to avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };
Index: clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -109,8 +109,9 @@
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam->getName();
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19849: [clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

2016-05-03 Thread Felix Berger via cfe-commits
flx removed rL LLVM as the repository for this revision.
flx updated this revision to Diff 55975.

http://reviews.llvm.org/D19849

Files:
  clang-tidy/misc/MoveConstructorInitCheck.cpp
  test/clang-tidy/misc-move-constructor-init.cpp

Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -96,7 +96,7 @@
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to 
avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument 'M' can be moved 
to avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };
Index: clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -109,8 +109,9 @@
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid 
copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam;
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());


Index: test/clang-tidy/misc-move-constructor-init.cpp
===
--- test/clang-tidy/misc-move-constructor-init.cpp
+++ test/clang-tidy/misc-move-constructor-init.cpp
@@ -96,7 +96,7 @@
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument 'M' can be moved to avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };
Index: clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -109,8 +109,9 @@
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam;
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19849: [clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

2016-05-03 Thread Felix Berger via cfe-commits
flx marked an inline comment as done.
flx added a comment.

Done.


http://reviews.llvm.org/D19849



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19849: [clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

2016-05-03 Thread Felix Berger via cfe-commits
flx added a comment.

In http://reviews.llvm.org/D19849#419751, @aaron.ballman wrote:

> I'm not opposed to showing the name, but I'm not certain I understand under 
> what circumstances the name would be useful. Since this is triggering on move 
> constructors, and move constructors can only have one parameter, the name 
> seems wholly redundant, isn't it?


The case this is covering is when a value parameter can be moved, of which 
there can be many.


http://reviews.llvm.org/D19849



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D19865: [clang-tidy] - PerformanceUnnecesaryCopyInitialization - only trigger for decl stmts with single VarDecl.

2016-05-03 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a reviewer: alexfh.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

This fixes bug: https://llvm.org/bugs/show_bug.cgi?id=27325

Repository:
  rL LLVM

http://reviews.llvm.org/D19865

Files:
  clang-tidy/performance/UnnecessaryCopyInitialization.cpp
  test/clang-tidy/performance-unnecessary-copy-initialization.cpp

Index: test/clang-tidy/performance-unnecessary-copy-initialization.cpp
===
--- test/clang-tidy/performance-unnecessary-copy-initialization.cpp
+++ test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -338,3 +338,8 @@
   WeirdCopyCtorType neg_weird_1(orig, false);
   WeirdCopyCtorType neg_weird_2(orig, true);
 }
+
+void NegativeMultiDeclStmt() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy = orig, copy2;
+}
Index: clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===
--- clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -56,16 +56,15 @@
 
   auto localVarCopiedFrom = [](const internal::Matcher &CopyCtorArg) {
 return compoundStmt(
-   forEachDescendant(
+   forEachDescendant(declStmt(hasSingleDecl(
varDecl(hasLocalStorage(),
hasType(matchers::isExpensiveToCopy()),
hasInitializer(cxxConstructExpr(
   
hasDeclaration(cxxConstructorDecl(
   isCopyConstructor())),
   hasArgument(0, CopyCtorArg))
   .bind("ctorCall")))
-   .bind("newVarDecl")))
-.bind("blockStmt");
+   .bind("newVarDecl").bind("blockStmt");
   };
 
   Finder->addMatcher(


Index: test/clang-tidy/performance-unnecessary-copy-initialization.cpp
===
--- test/clang-tidy/performance-unnecessary-copy-initialization.cpp
+++ test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -338,3 +338,8 @@
   WeirdCopyCtorType neg_weird_1(orig, false);
   WeirdCopyCtorType neg_weird_2(orig, true);
 }
+
+void NegativeMultiDeclStmt() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy = orig, copy2;
+}
Index: clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===
--- clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -56,16 +56,15 @@
 
   auto localVarCopiedFrom = [](const internal::Matcher &CopyCtorArg) {
 return compoundStmt(
-   forEachDescendant(
+   forEachDescendant(declStmt(hasSingleDecl(
varDecl(hasLocalStorage(),
hasType(matchers::isExpensiveToCopy()),
hasInitializer(cxxConstructExpr(
   hasDeclaration(cxxConstructorDecl(
   isCopyConstructor())),
   hasArgument(0, CopyCtorArg))
   .bind("ctorCall")))
-   .bind("newVarDecl")))
-.bind("blockStmt");
+   .bind("newVarDecl").bind("blockStmt");
   };
 
   Finder->addMatcher(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19865: [clang-tidy] - PerformanceUnnecesaryCopyInitialization - only trigger for decl stmts with single VarDecl.

2016-05-03 Thread Felix Berger via cfe-commits
flx added a comment.

In http://reviews.llvm.org/D19865#419830, @alexfh wrote:

> Is it a workaround to avoid breaking the code by incorrect fixes?


Yes. We can't simply change the type of DeclStmt when we only look one of the 
VarDecls and how it is initialized.


Repository:
  rL LLVM

http://reviews.llvm.org/D19865



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] r268461 - [clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

2016-05-03 Thread Felix Berger via cfe-commits
Author: flx
Date: Tue May  3 18:07:44 2016
New Revision: 268461

URL: http://llvm.org/viewvc/llvm-project?rev=268461&view=rev
Log:
[clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

Reviewers: alexfh

Subscribers: aaron.ballman, cfe-commits

Differential Revision: http://reviews.llvm.org/D19849

Modified:
clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp

Modified: clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp?rev=268461&r1=268460&r2=268461&view=diff
==
--- clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp 
(original)
+++ clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp Tue 
May  3 18:07:44 2016
@@ -109,8 +109,9 @@ void MoveConstructorInitCheck::handlePar
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid 
copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam;
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());

Modified: clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp?rev=268461&r1=268460&r2=268461&view=diff
==
--- clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp 
(original)
+++ clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp Tue 
May  3 18:07:44 2016
@@ -96,7 +96,7 @@ struct TriviallyCopyable {
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to 
avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument 'M' can be moved 
to avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19849: [clang-tidy] MoveConstructorInitCheck - Add parameter name to check message.

2016-05-03 Thread Felix Berger via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL268461: [clang-tidy] MoveConstructorInitCheck - Add 
parameter name to check message. (authored by flx).

Changed prior to commit:
  http://reviews.llvm.org/D19849?vs=55975&id=56076#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D19849

Files:
  clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp

Index: clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
@@ -96,7 +96,7 @@
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to 
avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument 'M' can be moved 
to avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };
Index: clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -109,8 +109,9 @@
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid 
copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam;
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());


Index: clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
===
--- clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-move-constructor-init.cpp
@@ -96,7 +96,7 @@
 
 struct Positive {
   Positive(Movable M) : M_(M) {}
-  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument can be moved to avoid copy [misc-move-constructor-init]
+  // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument 'M' can be moved to avoid copy [misc-move-constructor-init]
   // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
   Movable M_;
 };
Index: clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
===
--- clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -109,8 +109,9 @@
   if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
*Result.Context) > 1)
 return;
-  auto DiagOut =
-  diag(InitArg->getLocStart(), "value argument can be moved to avoid copy");
+  auto DiagOut = diag(InitArg->getLocStart(),
+  "value argument %0 can be moved to avoid copy")
+ << MovableParam;
   DiagOut << FixItHint::CreateReplacement(
   InitArg->getSourceRange(),
   (Twine("std::move(") + MovableParam->getName() + ")").str());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19865: [clang-tidy] - PerformanceUnnecesaryCopyInitialization - only trigger for decl stmts with single VarDecl.

2016-05-05 Thread Felix Berger via cfe-commits
flx added a comment.

In http://reviews.llvm.org/D19865#419905, @flx wrote:

> In http://reviews.llvm.org/D19865#419830, @alexfh wrote:
>
> > Is it a workaround to avoid breaking the code by incorrect fixes?
>
>
> Yes. We can't simply change the type of DeclStmt when we only look one of the 
> VarDecls and how it is initialized.


Also, all tests still pass. Alex, do you have any particular concern with this 
approach?


Repository:
  rL LLVM

http://reviews.llvm.org/D19865



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D20010: [clang-tidy] UnnecessaryCopyInitialization - Extend to trigger on non-const "this" object argument if it is not modified

2016-05-05 Thread Felix Berger via cfe-commits
flx created this revision.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Also trigger the check in the following case:

void foo() {
  ExpensiveToCopy Obj;
  const auto UnnecessaryCopy = Obj.constReference();
  Obj.onlyUsedAsConst();
}

i.e. when the object the method is called on is not const but is never modified.

Repository:
  rL LLVM

http://reviews.llvm.org/D20010

Files:
  clang-tidy/performance/UnnecessaryCopyInitialization.cpp
  clang-tidy/performance/UnnecessaryCopyInitialization.h
  test/clang-tidy/performance-unnecessary-copy-initialization.cpp

Index: test/clang-tidy/performance-unnecessary-copy-initialization.cpp
===
--- test/clang-tidy/performance-unnecessary-copy-initialization.cpp
+++ test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -174,33 +174,57 @@
   }
 }
 
-void NegativeMethodCallNonConstRef(ExpensiveToCopyType &Obj) {
+void PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType &Obj) {
   const auto AutoAssigned = Obj.reference();
-  const auto AutoCopyConstructed(Obj.reference());
-  const ExpensiveToCopyType VarAssigned = Obj.reference();
-  const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const
+  // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
 }
 
-void NegativeMethodCallNonConst(ExpensiveToCopyType Obj) {
+void NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType &Obj) {
   const auto AutoAssigned = Obj.reference();
   const auto AutoCopyConstructed(Obj.reference());
   const ExpensiveToCopyType VarAssigned = Obj.reference();
   const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  mutate(&Obj);
+}
+
+void PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj) {
+  const auto AutoAssigned = Obj.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const
+  // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
+}
+
+void NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj) {
+  Obj.nonConstMethod();
+  const auto AutoAssigned = Obj.reference();
 }
 
-void NegativeMethodCallNonConstPointer(ExpensiveToCopyType *const Obj) {
+void PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType *const Obj) {
+  const auto AutoAssigned = Obj->reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const
+  // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
+  Obj->constMethod();
+}
+
+void NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType *const Obj) {
   const auto AutoAssigned = Obj->reference();
   const auto AutoCopyConstructed(Obj->reference());
   const ExpensiveToCopyType VarAssigned = Obj->reference();
   const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
+  mutate(Obj);
+}
+
+void PositiveLocalVarIsNotModified() {
+  ExpensiveToCopyType LocalVar;
+  const auto AutoAssigned = LocalVar.reference();
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const
+  // CHECK-FIXES: const auto& AutoAssigned = LocalVar.reference();
 }
 
-void NegativeObjIsNotParam() {
+void NegativeLocalVarIsModified() {
   ExpensiveToCopyType Obj;
   const auto AutoAssigned = Obj.reference();
-  const auto AutoCopyConstructed(Obj.reference());
-  ExpensiveToCopyType VarAssigned = Obj.reference();
-  ExpensiveToCopyType VarCopyConstructed(Obj.reference());
+  Obj = AutoAssigned;
 }
 
 struct NegativeConstructor {
Index: clang-tidy/performance/UnnecessaryCopyInitialization.h
===
--- clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -33,6 +33,7 @@
 
 private:
   void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
+  const VarDecl *ObjectArg,
   ASTContext &Context);
   void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
   const Stmt &BlockStmt, ASTContext &Context);
Index: clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===
--- clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -42,14 +42,14 @@
 unless(allOf(pointerType(), unless(pointerType(pointee(
 qualType(isConstQualified(;
 
-  // Match method call expressions where the this argument is a const
-  // type or const reference. This returned const reference is highly likely to
-  // outlive the local const reference of the variable being declared.
-  // The assumption is that the const reference being returned either points
-  // to a global static variable or to a member of the called object.
-  auto ConstRefReturningMethodCallOfConstParam = cxxMemberCallExpr(
+  // Matc

Re: [PATCH] D19865: [clang-tidy] - PerformanceUnnecesaryCopyInitialization - only trigger for decl stmts with single VarDecl.

2016-05-09 Thread Felix Berger via cfe-commits
flx added a comment.

In http://reviews.llvm.org/D19865#423140, @flx wrote:

> In http://reviews.llvm.org/D19865#419905, @flx wrote:
>
> > In http://reviews.llvm.org/D19865#419830, @alexfh wrote:
> >
> > > Is it a workaround to avoid breaking the code by incorrect fixes?
> >
> >
> > Yes. We can't simply change the type of DeclStmt when we only look one of 
> > the VarDecls and how it is initialized.
>
>
> Also, all tests still pass. Alex, do you have any particular concern with 
> this approach?




In http://reviews.llvm.org/D19865#423286, @alexfh wrote:

> In http://reviews.llvm.org/D19865#423140, @flx wrote:
>
> > In http://reviews.llvm.org/D19865#419905, @flx wrote:
> >
> > > In http://reviews.llvm.org/D19865#419830, @alexfh wrote:
> > >
> > > > Is it a workaround to avoid breaking the code by incorrect fixes?
> > >
> > >
> > > Yes. We can't simply change the type of DeclStmt when we only look one of 
> > > the VarDecls and how it is initialized.
> >
> >
> > Also, all tests still pass. Alex, do you have any particular concern with 
> > this approach?
>
>
> Even if we can't easily provide an automated fix (we could teach the check to 
> split declarations, but it might not worth the effort), we could still emit a 
> warning. WDYT?


Sounds good. Done. We now still issue the warning, but don't issue fixes when 
it's not a single decl.


http://reviews.llvm.org/D19865



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D19865: [clang-tidy] - PerformanceUnnecesaryCopyInitialization - only trigger for decl stmts with single VarDecl.

2016-05-09 Thread Felix Berger via cfe-commits
flx removed rL LLVM as the repository for this revision.
flx updated this revision to Diff 56573.

http://reviews.llvm.org/D19865

Files:
  clang-tidy/performance/UnnecessaryCopyInitialization.cpp
  clang-tidy/performance/UnnecessaryCopyInitialization.h
  test/clang-tidy/performance-unnecessary-copy-initialization.cpp

Index: test/clang-tidy/performance-unnecessary-copy-initialization.cpp
===
--- test/clang-tidy/performance-unnecessary-copy-initialization.cpp
+++ test/clang-tidy/performance-unnecessary-copy-initialization.cpp
@@ -338,3 +338,10 @@
   WeirdCopyCtorType neg_weird_1(orig, false);
   WeirdCopyCtorType neg_weird_2(orig, true);
 }
+
+void WarningOnlyMultiDeclStmt() {
+  ExpensiveToCopyType orig;
+  ExpensiveToCopyType copy = orig, copy2;
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
+  // CHECK-FIXES: ExpensiveToCopyType copy = orig, copy2;
+}
Index: clang-tidy/performance/UnnecessaryCopyInitialization.h
===
--- clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -33,9 +33,10 @@
 
 private:
   void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
-  ASTContext &Context);
+  bool IssueFix, ASTContext &Context);
   void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
-  const Stmt &BlockStmt, ASTContext &Context);
+  const Stmt &BlockStmt, bool IssueFix,
+  ASTContext &Context);
 };
 
 } // namespace performance
Index: clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===
--- clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -20,10 +20,6 @@
 
 void recordFixes(const VarDecl &Var, ASTContext &Context,
  DiagnosticBuilder &Diagnostic) {
-  // Do not propose fixes in macros since we cannot place them correctly.
-  if (Var.getLocation().isMacroID())
-return;
-
   Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context);
   if (!Var.getType().isLocalConstQualified())
 Diagnostic << utils::fixit::changeVarDeclToConst(Var);
@@ -57,14 +53,16 @@
   auto localVarCopiedFrom = [](const internal::Matcher &CopyCtorArg) {
 return compoundStmt(
forEachDescendant(
-   varDecl(hasLocalStorage(),
-   hasType(matchers::isExpensiveToCopy()),
-   hasInitializer(cxxConstructExpr(
-  hasDeclaration(cxxConstructorDecl(
-  isCopyConstructor())),
-  hasArgument(0, CopyCtorArg))
-  .bind("ctorCall")))
-   .bind("newVarDecl")))
+   declStmt(
+   has(varDecl(hasLocalStorage(),
+   hasType(matchers::isExpensiveToCopy()),
+   hasInitializer(
+   cxxConstructExpr(
+   hasDeclaration(cxxConstructorDecl(
+   isCopyConstructor())),
+   hasArgument(0, CopyCtorArg))
+   .bind("ctorCall")))
+   .bind("newVarDecl"))).bind("declStmt")))
 .bind("blockStmt");
   };
 
@@ -84,6 +82,11 @@
   const auto *OldVar = Result.Nodes.getNodeAs("oldVarDecl");
   const auto *BlockStmt = Result.Nodes.getNodeAs("blockStmt");
   const auto *CtorCall = Result.Nodes.getNodeAs("ctorCall");
+  // Do not propose fixes if the DeclStmt has multiple VarDecls or in macros
+  // since we cannot place them correctly.
+  bool IssueFix =
+  Result.Nodes.getNodeAs("declStmt")->isSingleDecl() &&
+  !NewVar->getLocation().isMacroID();
 
   // A constructor that looks like T(const T& t, bool arg = false) counts as a
   // copy only when it is called with default arguments for the arguments after
@@ -93,14 +96,16 @@
   return;
 
   if (OldVar == nullptr) {
-handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Result.Context);
+handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, *Result.Context);
   } else {
-handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Result.Context);
+handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, IssueFix,
+   *Result.Context);
   }
 }
 
 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn

[PATCH] D20170: [clang-tidy] TypeTraits - Type is not expensive to copy when it has a deleted copy constructor.

2016-05-11 Thread Felix Berger via cfe-commits
flx created this revision.
flx added reviewers: alexfh, sbenza.
flx added a subscriber: cfe-commits.
flx set the repository for this revision to rL LLVM.

Repository:
  rL LLVM

http://reviews.llvm.org/D20170

Files:
  clang-tidy/utils/TypeTraits.cpp
  test/clang-tidy/performance-unnecessary-value-param.cpp

Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -23,6 +23,12 @@
   SomewhatTrivial& operator=(const SomewhatTrivial&);
 };
 
+struct MoveOnlyType {
+  MoveOnlyType(const MoveOnlyType&) = delete;
+  ~MoveOnlyType();
+  void constMethod() const;
+};
+
 void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
 // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& 
Obj);
 void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
@@ -169,3 +175,7 @@
   NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
   // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = 
delete;
 };
+
+void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) {
+  M.constMethod();
+}
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -10,26 +10,42 @@
 #include "TypeTraits.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
 
 namespace clang {
 namespace tidy {
 namespace utils {
 namespace type_traits {
 
+using namespace ::clang::ast_matchers;
+
 namespace {
 bool classHasTrivialCopyAndDestroy(QualType Type) {
   auto *Record = Type->getAsCXXRecordDecl();
   return Record && Record->hasDefinition() &&
  !Record->hasNonTrivialCopyConstructor() &&
  !Record->hasNonTrivialDestructor();
 }
+
+bool hasDeletedCopyConstructor(QualType Type, ASTContext &Context) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  if (Record == nullptr || !Record->hasDefinition())
+return false;
+  auto Matches = match(cxxRecordDecl(hasMethod(
+   cxxConstructorDecl(isCopyConstructor(), isDeleted())
+   .bind("constructor"))),
+   *Record, Context);
+  return !Matches.empty();
+}
+
 } // namespace
 
 llvm::Optional isExpensiveToCopy(QualType Type, ASTContext &Context) {
   if (Type->isDependentType())
 return llvm::None;
   return !Type.isTriviallyCopyableType(Context) &&
- !classHasTrivialCopyAndDestroy(Type);
+ !classHasTrivialCopyAndDestroy(Type) &&
+ !hasDeletedCopyConstructor(Type, Context);
 }
 
 bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,


Index: test/clang-tidy/performance-unnecessary-value-param.cpp
===
--- test/clang-tidy/performance-unnecessary-value-param.cpp
+++ test/clang-tidy/performance-unnecessary-value-param.cpp
@@ -23,6 +23,12 @@
   SomewhatTrivial& operator=(const SomewhatTrivial&);
 };
 
+struct MoveOnlyType {
+  MoveOnlyType(const MoveOnlyType&) = delete;
+  ~MoveOnlyType();
+  void constMethod() const;
+};
+
 void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
 // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
 void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
@@ -169,3 +175,7 @@
   NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
   // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
 };
+
+void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) {
+  M.constMethod();
+}
Index: clang-tidy/utils/TypeTraits.cpp
===
--- clang-tidy/utils/TypeTraits.cpp
+++ clang-tidy/utils/TypeTraits.cpp
@@ -10,26 +10,42 @@
 #include "TypeTraits.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
 
 namespace clang {
 namespace tidy {
 namespace utils {
 namespace type_traits {
 
+using namespace ::clang::ast_matchers;
+
 namespace {
 bool classHasTrivialCopyAndDestroy(QualType Type) {
   auto *Record = Type->getAsCXXRecordDecl();
   return Record && Record->hasDefinition() &&
  !Record->hasNonTrivialCopyConstructor() &&
  !Record->hasNonTrivialDestructor();
 }
+
+bool hasDeletedCopyConstructor(QualType Type, ASTContext &Context) {
+  auto *Record = Type->getAsCXXRecordDecl();
+  if (Record == nullptr || !Record->hasDefinition())
+return false;
+  auto Matches = match(cxxRecordDecl(hasMethod(
+   cxxConstructorDecl(isCopyConstructor(), isDeleted())
+   .bind("constructor"))),
+   *Record, Context);
+  return !Matches.empty();
+}
+
 } // namespace
 
 llvm::

  1   2   >