Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/compilerplugins/clang/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 6 kB image not shown  

Quelle  moveparam.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * Based on LLVM/Clang.
 *
 * This file is distributed under the University of Illinois Open Source
 * License. See LICENSE.TXT for details.
 *
 */


#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <set>
#include <unordered_set>
#include "config_clang.h"
#include "plugin.hxx"
#include "check.hxx"

/*
Look for places where we can pass by move && param and so avoid
unnecessary copies.
Empirically, when we are passing a container type to a function, 80% of the time,
we are passing a local temporary that can be moved instead of being copied.

TODO this could be a lot smarter, with ignoring false+ e.g. when copying a param
in a loop
*/


namespace
{
class MoveParam : public loplugin::FilteringPlugin<MoveParam>
{
public:
    explicit MoveParam(loplugin::InstantiationData const& data)
        : FilteringPlugin(data)
    {
    }

    virtual bool preRun() override
    {
        std::string fn(handler.getMainFileName());
        loplugin::normalizeDotDotInFilePath(fn);
        if (loplugin::hasPathnamePrefix(fn, SRCDIR "/filter/source/msfilter/escherex.cxx"))
            return false;
        if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/docshell/docfunc.cxx"))
            return false;
        if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sc/source/ui/view/viewfunc.cxx"))
            return false;
        if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basegfx/source/polygon/b2dpolygontools.cxx"))
            return false;
        if (loplugin::hasPathnamePrefix(fn, SRCDIR "/basegfx/source/polygon/b3dpolygontools.cxx"))
            return false;
        if (loplugin::hasPathnamePrefix(fn, SRCDIR "/connectivity/source/commontools/dbtools.cxx"))
            return false;
        return true;
    }

    virtual void run() override
    {
        if (preRun())
            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
    }

    bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr*);
    bool VisitCXXConstructExpr(const CXXConstructExpr*);

    bool isContainerType(QualType qt);
};

bool MoveParam::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr* callExpr)
{
    if (ignoreLocation(callExpr))
        return true;
    if (!callExpr->isAssignmentOp())
        return true;
    auto qt = callExpr->getType();
    if (!isContainerType(qt))
        return true;
    auto declRef = dyn_cast<DeclRefExpr>(callExpr->getArg(1)->IgnoreParenImpCasts());
    if (!declRef)
        return true;

    auto parmVarDecl = dyn_cast_or_null<ParmVarDecl>(declRef->getDecl());
    if (!parmVarDecl)
        return true;

    if (!loplugin::TypeCheck(parmVarDecl->getType()).LvalueReference().Const())
        return true;

    StringRef aFileName = getFilenameOfLocation(
        compiler.getSourceManager().getSpellingLoc(parmVarDecl->getBeginLoc()));
    if (loplugin::hasPathnamePrefix(aFileName,
                                    SRCDIR "/svx/source/sidebar/line/LineWidthValueSet.cxx"))
        return true;

    report(DiagnosticsEngine::Warning, "rather use move && param1", callExpr->getBeginLoc());

    return true;
}

bool MoveParam::VisitCXXConstructExpr(const CXXConstructExpr* constructExpr)
{
    if (ignoreLocation(constructExpr->getBeginLoc()))
        return true;
    if (isInUnoIncludeFile(constructExpr->getBeginLoc()))
        return true;

    auto qt = constructExpr->getType();
    if (!isContainerType(qt))
        return true;

    if (constructExpr->getNumArgs() != 1)
        return true;

    auto declRef = dyn_cast<DeclRefExpr>(constructExpr->getArg(0)->IgnoreParenImpCasts());
    if (!declRef)
        return true;

    auto parmVarDecl = dyn_cast_or_null<ParmVarDecl>(declRef->getDecl());
    if (!parmVarDecl)
        return true;

    if (!loplugin::TypeCheck(parmVarDecl->getType()).LvalueReference().Const())
        return true;

    StringRef aFileName = getFilenameOfLocation(
        compiler.getSourceManager().getSpellingLoc(parmVarDecl->getBeginLoc()));
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR
                                    "/include/drawinglayer/primitive2d/Primitive2DContainer.hxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName,
                                    SRCDIR "/include/drawinglayer/primitive3d/baseprimitive3d.hxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/svx/source/svdraw/svdmrkv.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/include/editeng/swafopt.hxx"))
        return true;
    if (loplugin::hasPathnamePrefix(
            aFileName, SRCDIR "/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName,
                                    SRCDIR "/chart2/source/tools/InternalDataProvider.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sc/source/core/data/attrib.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/sw/source/core/doc/docfmt.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/configmgr/source/modifications.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName, SRCDIR "/svx/source/dialog/srchdlg.cxx"))
        return true;
    if (loplugin::hasPathnamePrefix(aFileName,
                                    SRCDIR "/stoc/source/servicemanager/servicemanager.cxx"))
        return true;

    report(DiagnosticsEngine::Warning, "rather use move && param3", constructExpr->getBeginLoc());

    return true;
}

bool MoveParam::isContainerType(QualType qt)
{
    auto tc = loplugin::TypeCheck(qt);
    return tc.Class("Primitive2DContainer")
               .Namespace("primitive2d")
               .Namespace("drawinglayer")
               .GlobalNamespace()
           || tc.ClassOrStruct("sorted_vector").Namespace("o3tl").GlobalNamespace()
           || tc.ClassOrStruct("array").StdNamespace() || tc.ClassOrStruct("vector").StdNamespace()
           || tc.ClassOrStruct("deque").StdNamespace()
           || tc.ClassOrStruct("forward_list").StdNamespace()
           || tc.ClassOrStruct("list").StdNamespace() || tc.ClassOrStruct("set").StdNamespace()
           || tc.ClassOrStruct("map").StdNamespace() || tc.ClassOrStruct("multiset").StdNamespace()
           || tc.ClassOrStruct("multimap").StdNamespace()
           || tc.ClassOrStruct("unordered_set").StdNamespace()
           || tc.ClassOrStruct("unordered_map").StdNamespace()
           || tc.ClassOrStruct("unordered_multiset").StdNamespace()
           || tc.ClassOrStruct("unordered_multimap").StdNamespace()
           || tc.ClassOrStruct("stack").StdNamespace() || tc.ClassOrStruct("queue").StdNamespace()
           || tc.ClassOrStruct("priority_queue").StdNamespace();
}

/** off by default because it needs some hand-holding */
loplugin::Plugin::Registration<MoveParam> moveparam("moveparam"false);

// namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.