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; } }
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)); } }
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; }