void PassByValueCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor");
  const auto *ParamDecl = Result.Nodes.getNodeAs<ParmVarDecl>("Param");
  const auto *Initializer =
      Result.Nodes.getNodeAs<CXXCtorInitializer>("Initializer");
  SourceManager &SM = *Result.SourceManager;

  // If the parameter is used or anything other than the copy, do not apply
  // the changes.
  if (!paramReferredExactlyOnce(Ctor, ParamDecl))
    return;

  // If the parameter is trivial to copy, don't move it. Moving a trivivally
  // copyable type will cause a problem with misc-move-const-arg
  if (ParamDecl->getType().isTriviallyCopyableType(*Result.Context)) 
    return;

  auto Diag = diag(ParamDecl->getLocStart(), "pass by value and use std::move");

  // Iterate over all declarations of the constructor.
  for (const ParmVarDecl *ParmDecl : collectParamDecls(Ctor, ParamDecl)) {
    auto ParamTL = ParmDecl->getTypeSourceInfo()->getTypeLoc();
    auto RefTL = ParamTL.getAs<ReferenceTypeLoc>();

    // Do not replace if it is already a value, skip.
    if (RefTL.isNull())
      continue;

    TypeLoc ValueTL = RefTL.getPointeeLoc();
    auto TypeRange = CharSourceRange::getTokenRange(ParmDecl->getLocStart(),
                                                    ParamTL.getLocEnd());
    std::string ValueStr =
        Lexer::getSourceText(
            CharSourceRange::getTokenRange(ValueTL.getSourceRange()), SM,
            Result.Context->getLangOpts())
            .str();
    ValueStr += ' ';
    Diag << FixItHint::CreateReplacement(TypeRange, ValueStr);
  }

  // Use std::move in the initialization list.
  Diag << FixItHint::CreateInsertion(Initializer->getRParenLoc(), ")")
       << FixItHint::CreateInsertion(
              Initializer->getLParenLoc().getLocWithOffset(1), "std::move(");

  if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
          Result.SourceManager->getFileID(Initializer->getSourceLocation()),
          "utility",
          /*IsAngled=*/true)) {
    Diag << *IncludeFixit;
  }
}
Example #2
0
 virtual void run(const ast_matchers::MatchFinder::MatchResult &result) {
   auto decl = result.Nodes.getNodeAs<CXXRecordDecl>("inheritsQListIterator");
   if (decl==nullptr) {
     return;
   }
   if (!decl->hasDefinition()) return; // this is needed so bases_begin doesn't crash
   auto it = decl->bases_begin();
   for (; it && it != decl->bases_end(); ++it) {
     auto str = getText(*result.SourceManager,it->getLocStart(),it->getLocEnd()) ;
     if (! findNreplace(str,"QListIterator<(\\w+)>","std::list<$1*>::iterator") ) return;
     Replace->insert(Replacement(*result.SourceManager, it, str));
   }
 }
Example #3
0
StmtResult Sema::ActOnDATA(ASTContext &C, SourceLocation Loc,
                           ArrayRef<Expr*> Objects,
                           ArrayRef<Expr*> Values,
                           Expr *StmtLabel) {
  DataValueIterator ValuesIt(Values);
  DataStmtEngine LHSVisitor(ValuesIt, *this, Diags, Loc);
  for(auto I : Objects) {
    LHSVisitor.Visit(I);
    if(LHSVisitor.IsDone()) break;
  }

  if(!ValuesIt.isEmpty()) {
    // more items than values
    auto FirstVal = ValuesIt.getActualValue();
    auto LastVal = ValuesIt.getActualLastValue();
    Diags.Report(FirstVal->getLocation(), diag::err_data_stmt_too_many_values)
      << SourceRange(FirstVal->getLocStart(), LastVal->getLocEnd());
  }

  auto Result = DataStmt::Create(C, Loc, Objects, Values,
                                 StmtLabel);
  if(StmtLabel) DeclareStatementLabel(StmtLabel, Result);
  return Result;
}