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

Quelle  toolslong.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */


#include <algorithm>
#include <cassert>
#include <limits>
#include <map>
#include <string>
#include <iostream>

#include "clang/AST/Attr.h"
#include "clang/Basic/Builtins.h"

#include "config_clang.h"

#include "check.hxx"
#include "plugin.hxx"

namespace
{
bool isLong(QualType type)
{
    type = type.getNonReferenceType();
    // ignore sal_Int64
    if (type->getAs<TypedefType>())
        return false;
    // some parts of the STL have ::difference_type => long
    if (type->getAs<AutoType>() || type->getAs<DecltypeType>())
        return false;
    if (type->isSpecificBuiltinType(BuiltinType::Kind::Long))
        return true;
    auto arrayType = type->getAsArrayTypeUnsafe();
    if (arrayType)
        return isLong(arrayType->getElementType());
    if (type->isPointerType())
        return isLong(type->getPointeeType());
    return false;
}

enum class OverrideKind
{
    NO,
    YES,
    MAYBE
};

OverrideKind getOverrideKind(FunctionDecl const* decl)
{
    CXXMethodDecl const* m = dyn_cast<CXXMethodDecl>(decl);
    if (m == nullptr)
        return OverrideKind::NO;
    if (m->size_overridden_methods() != 0 || m->hasAttr<OverrideAttr>())
        return OverrideKind::YES;
    if (!dyn_cast<CXXRecordDecl>(m->getDeclContext())->hasAnyDependentBases())
        return OverrideKind::NO;
    return OverrideKind::MAYBE;
}

class ToolsLong : public loplugin::FilteringRewritePlugin<ToolsLong>
{
public:
    explicit ToolsLong(loplugin::InstantiationData const& data)
        : loplugin::FilteringRewritePlugin<ToolsLong>(data)
    {
    }

    virtual void run() override;

    bool VisitCStyleCastExpr(CStyleCastExpr* expr);

    bool VisitCXXStaticCastExpr(CXXStaticCastExpr* expr);

    bool VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr);

    bool WalkUpFromParmVarDecl(ParmVarDecl const* decl);
    bool VisitParmVarDecl(ParmVarDecl const* decl);

    bool WalkUpFromVarDecl(VarDecl const* decl);
    bool VisitVarDecl(VarDecl const* decl);

    bool WalkUpFromFieldDecl(FieldDecl const* decl);
    bool VisitFieldDecl(FieldDecl const* decl);

    bool WalkUpFromFunctionDecl(FunctionDecl const* decl);
    bool VisitFunctionDecl(FunctionDecl const* decl);

    bool VisitCallExpr(CallExpr const* expr);

private:
    bool rewrite(SourceLocation location);
    bool isExcludedFile(SourceLocation spellingLocation) const;
    /** sort by the reverse of source order, so we can do replacing from the end of the file backwards,
        which means we reduce the chances of having overlapping changes. */

    template <class T>
    std::vector<std::pair<T, bool>> reverseSourceOrder(std::map<T, boolconst& map) const
    {
        std::vector<std::pair<T, bool>> vec(map.begin(), map.end());
        std::sort(vec.begin(), vec.end(),
                  [&](std::pair<T, boolconst& lhs, std::pair<T, boolconst& rhs) {
                      return compiler.getSourceManager().getCharacterData(lhs.first->getBeginLoc())
                             > compiler.getSourceManager().getCharacterData(
                                   rhs.first->getBeginLoc());
                  });
        return vec;
    }

    std::map<VarDecl const*, bool> varDecls_;
    std::map<FieldDecl const*, bool> fieldDecls_;
    std::map<ParmVarDecl const*, bool> parmVarDecls_;
    std::map<FunctionDecl const*, bool> functionDecls_;
    std::map<CXXStaticCastExpr const*, bool> staticCasts_;
    std::map<CXXFunctionalCastExpr const*, bool> functionalCasts_;
};

void ToolsLong::run()
{
    if (!compiler.getLangOpts().CPlusPlus)
        return;

    StringRef fn(handler.getMainFileName());
    // sberg says this is fine
    if (loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/framegrabber.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/manager.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/player.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/avmedia/source/win/window.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/drivers/ado/AStatement.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/connectivity/source/drivers/ado/Awrapado.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/desktop/win32/source/loader.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/extensions/source/activex/SOActiveX.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/pyuno/source/module/pyuno.cxx")
        || loplugin::isSamePathname(fn, SRCDIR
                                    "/setup_native/source/win32/customactions/sellang/sellang.cxx")
        || loplugin::isSamePathname(fn, SRCDIR
                                    "/shell/source/win32/shlxthandler/ooofilt/stream_helper.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/shell/source/win32/zipfile/zipfile.cxx")
        || loplugin::isSamePathname(fn, SRCDIR "/ucb/source/ucp/webdav-curl/CurlSession.cxx"))
        return;
    // these are places where the external API is actually "long"
    if (loplugin::isSamePathname(fn, SRCDIR "/vcl/source/filter/jpeg/JpegReader.cxx"))
        return;
    if (loplugin::isSamePathname(fn, SRCDIR "/writerperfect/source/common/DirectoryStream.cxx"))
        return;
    if (loplugin::isSamePathname(fn, SRCDIR "/writerperfect/source/common/WPXSvInputStream.cxx"))
        return;
    if (loplugin::isSamePathname(fn,
                                 SRCDIR "/writerperfect/source/calc/MSWorksCalcImportFilter.cxx"))
        return;
    if (loplugin::isSamePathname(fn, SRCDIR "/writerperfect/qa/unit/WPXSvStreamTest.cxx"))
        return;
    if (loplugin::isSamePathname(fn, SRCDIR "/desktop/source/lib/init.cxx"))
        return;

    TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());

    for (auto const& dcl : reverseSourceOrder(varDecls_))
    {
        auto const decl = dcl.first;
        SourceLocation loc{ decl->getBeginLoc() };
        TypeSourceInfo* tsi = decl->getTypeSourceInfo();
        if (tsi != nullptr)
        {
            SourceLocation l{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getBeginLoc()) };
            SourceLocation end{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getEndLoc()) };
            assert(l.isFileID() && end.isFileID());
            if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end))
            {
                for (;;)
                {
                    unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(),
                                                           compiler.getLangOpts());
                    std::string s{ compiler.getSourceManager().getCharacterData(l), n };
                    if (s == "long")
                    {
                        loc = l;
                        break;
                    }
                    if (l == end)
                    {
                        break;
                    }
                    l = l.getLocWithOffset(std::max<unsigned>(n, 1));
                }
            }
        }
        if (!rewrite(loc))
        {
            report(DiagnosticsEngine::Warning, "VarDecl, use \"tools::Long\" instead of %0", loc)
                << decl->getType().getLocalUnqualifiedType() << decl->getSourceRange();
        }
    }
    for (auto const& dcl : reverseSourceOrder(fieldDecls_))
    {
        auto const decl = dcl.first;
        SourceLocation loc{ decl->getBeginLoc() };
        TypeSourceInfo* tsi = decl->getTypeSourceInfo();
        if (tsi != nullptr)
        {
            SourceLocation l{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getBeginLoc()) };
            SourceLocation end{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getEndLoc()) };
            assert(l.isFileID() && end.isFileID());
            if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end))
            {
                for (;;)
                {
                    unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(),
                                                           compiler.getLangOpts());
                    std::string s{ compiler.getSourceManager().getCharacterData(l), n };
                    if (s == "long")
                    {
                        loc = l;
                        break;
                    }
                    if (l == end)
                    {
                        break;
                    }
                    l = l.getLocWithOffset(std::max<unsigned>(n, 1));
                }
            }
        }
        if (!rewrite(loc))
        {
            report(DiagnosticsEngine::Warning, "FieldDecl, use \"tools::Long\" instead of %0", loc)
                << decl->getType().getLocalUnqualifiedType() << decl->getSourceRange();
        }
    }
    for (auto const& dcl : reverseSourceOrder(parmVarDecls_))
    {
        auto const decl = dcl.first;
        SourceLocation loc{ decl->getBeginLoc() };
        TypeSourceInfo* tsi = decl->getTypeSourceInfo();
        if (tsi != nullptr)
        {
            SourceLocation l{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getBeginLoc()) };
            SourceLocation end{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getEndLoc()) };
            assert(l.isFileID() && end.isFileID());
            if (l == end || (compiler.getSourceManager().isBeforeInTranslationUnit(l, end)))
            {
                for (;;)
                {
                    unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(),
                                                           compiler.getLangOpts());
                    std::string s{ compiler.getSourceManager().getCharacterData(l), n };
                    if (s == "long")
                    {
                        loc = l;
                        break;
                    }
                    if (l == end)
                    {
                        break;
                    }
                    l = l.getLocWithOffset(std::max<unsigned>(n, 1));
                }
            }
        }
        FunctionDecl const* f = dyn_cast_or_null<FunctionDecl>(decl->getDeclContext());
        if (f)
            f = f->getCanonicalDecl();
        OverrideKind k = f ? getOverrideKind(f) : OverrideKind::NO;
        if (k == OverrideKind::MAYBE || !rewrite(loc))
        {
            report(DiagnosticsEngine::Warning,
                   ("ParmVarDecl, use \"tools::Long\" instead of"
                    " %0%1"),
                   loc)
                << decl->getType().getNonReferenceType().getLocalUnqualifiedType()
                << (k == OverrideKind::MAYBE ? (" (unless this member function overrides a"
                                                " dependent base member function, even"
                                                " though it is not marked 'override')")
                                             : "")
                << decl->getSourceRange();
        }
    }
    for (auto const& dcl : functionDecls_)
    {
        auto const decl = dcl.first;
        SourceLocation loc{ decl->getBeginLoc() };
        SourceLocation l{ compiler.getSourceManager().getExpansionLoc(loc) };
        SourceLocation end{ compiler.getSourceManager().getExpansionLoc(
            decl->getNameInfo().getLoc()) };
        assert(l.isFileID() && end.isFileID());
        if (compiler.getSourceManager().isBeforeInTranslationUnit(l, end))
        {
            while (l != end)
            {
                unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(),
                                                       compiler.getLangOpts());
                std::string s{ compiler.getSourceManager().getCharacterData(l), n };
                if (s == "long")
                {
                    loc = l;
                    break;
                }
                l = l.getLocWithOffset(std::max<unsigned>(n, 1));
            }
        }
        if (rewrite(loc))
            continue;
        report(DiagnosticsEngine::Warning, "use \"tools::Long\" instead of %0 as return type%1",
               loc)
            << decl->getReturnType().getNonReferenceType().getLocalUnqualifiedType()
            << (getOverrideKind(decl) == OverrideKind::MAYBE
                    ? (" (unless this member function overrides a dependent"
                       " base member function, even though it is not marked"
                       " 'override')")
                    : "")
            << decl->getSourceRange();
    }

    for (auto const& dcl : staticCasts_)
    {
        auto const expr = dcl.first;
        SourceLocation loc{ expr->getBeginLoc() };
        TypeSourceInfo* tsi = expr->getTypeInfoAsWritten();
        if (tsi != nullptr)
        {
            SourceLocation l{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getBeginLoc()) };
            SourceLocation end{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getEndLoc()) };
            assert(l.isFileID() && end.isFileID());
            if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end))
            {
                for (;;)
                {
                    unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(),
                                                           compiler.getLangOpts());
                    std::string s{ compiler.getSourceManager().getCharacterData(l), n };
                    if (s == "long")
                    {
                        loc = l;
                        break;
                    }
                    if (l == end)
                    {
                        break;
                    }
                    l = l.getLocWithOffset(std::max<unsigned>(n, 1));
                }
            }
        }
        if (!rewrite(loc))
        {
            report(DiagnosticsEngine::Warning, "CXXStaticCastExpr, suspicious cast from %0 to %1",
                   expr->getBeginLoc())
                << expr->getSubExpr()->IgnoreParenImpCasts()->getType() << expr->getType()
                << expr->getSourceRange();
        }
    }

    for (auto const& dcl : functionalCasts_)
    {
        auto const expr = dcl.first;
        SourceLocation loc{ expr->getBeginLoc() };
        TypeSourceInfo* tsi = expr->getTypeInfoAsWritten();
        if (tsi != nullptr)
        {
            SourceLocation l{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getBeginLoc()) };
            SourceLocation end{ compiler.getSourceManager().getExpansionLoc(
                tsi->getTypeLoc().getEndLoc()) };
            assert(l.isFileID() && end.isFileID());
            if (l == end || compiler.getSourceManager().isBeforeInTranslationUnit(l, end))
            {
                for (;;)
                {
                    unsigned n = Lexer::MeasureTokenLength(l, compiler.getSourceManager(),
                                                           compiler.getLangOpts());
                    std::string s{ compiler.getSourceManager().getCharacterData(l), n };
                    if (s == "long")
                    {
                        loc = l;
                        break;
                    }
                    if (l == end)
                    {
                        break;
                    }
                    l = l.getLocWithOffset(std::max<unsigned>(n, 1));
                }
            }
        }
        if (!rewrite(loc))
        {
            report(DiagnosticsEngine::Warning,
                   "CXXFunctionalCastExpr, suspicious cast from %0 to %1", expr->getBeginLoc())
                << expr->getSubExpr()->IgnoreParenImpCasts()->getType() << expr->getType()
                << expr->getSourceRange();
        }
    }
}

bool ToolsLong::VisitCStyleCastExpr(CStyleCastExpr* expr)
{
    if (ignoreLocation(expr))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())))
        return true;
    auto const k = isLong(expr->getType());
    if (!k)
        return true;
    SourceLocation loc{ expr->getBeginLoc() };
    while (compiler.getSourceManager().isMacroArgExpansion(loc))
        loc = compiler.getSourceManager().getImmediateMacroCallerLoc(loc);
    if (compiler.getSourceManager().isMacroBodyExpansion(loc)
        && compiler.getSourceManager().isInSystemHeader(
               compiler.getSourceManager().getSpellingLoc(loc)))
    {
        return true;
    }
    report(DiagnosticsEngine::Warning, "CStyleCastExpr, suspicious cast from %0 to %1",
           expr->getBeginLoc())
        << expr->getSubExpr()->IgnoreParenImpCasts()->getType() << expr->getType()
        << expr->getSourceRange();
    return true;
}

bool ToolsLong::VisitCXXStaticCastExpr(CXXStaticCastExpr* expr)
{
    if (ignoreLocation(expr))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())))
        return true;
    auto const k = isLong(expr->getType());
    if (!k)
        return true;
    staticCasts_.insert({ expr, k });
    return true;
}

bool ToolsLong::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr* expr)
{
    if (ignoreLocation(expr))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(expr->getBeginLoc())))
        return true;
    auto const k = isLong(expr->getType());
    if (!k)
        return true;
    functionalCasts_.insert({ expr, k });
    return true;
}

bool ToolsLong::WalkUpFromParmVarDecl(ParmVarDecl const* decl) { return VisitParmVarDecl(decl); }

bool ToolsLong::VisitParmVarDecl(ParmVarDecl const* decl)
{
    if (ignoreLocation(decl))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation())))
        return true;
    auto const fbk = isLong(decl->getType());
    if (!fbk)
        return true;
    FunctionDecl const* f = dyn_cast<FunctionDecl>(decl->getDeclContext());
    if (f) // e.g.: typedef sal_Bool (* FuncPtr )( sal_Bool );
    {
        // ignore the function in include/test/cppunitasserthelper.hxx
        if (f->getIdentifier() && f->getName() == "assertEquals")
            return true;
        auto canonicalF = f->getCanonicalDecl();
        if (canonicalF->isDeletedAsWritten() && isa<CXXConversionDecl>(canonicalF))
            return true;
        if (auto const d = dyn_cast<CXXMethodDecl>(canonicalF))
        {
            if (d->isVirtual())
            {
                return true;
            }
        }
        // Only rewrite declarations in include files if a definition is
        // also seen, to avoid compilation of a definition (in a main file
        // only processed later) to fail with a "mismatch" error before the
        // rewriter had a chance to act upon the definition:
        bool ok = canonicalF->isDefined()
                  || compiler.getSourceManager().isInMainFile(
                         compiler.getSourceManager().getSpellingLoc(f->getNameInfo().getLoc()));
        if (!ok)
            return true;
    }
    parmVarDecls_.insert({ decl, fbk });
    return true;
}

bool ToolsLong::WalkUpFromVarDecl(VarDecl const* decl) { return VisitVarDecl(decl); }

bool ToolsLong::VisitVarDecl(VarDecl const* decl)
{
    if (ignoreLocation(decl))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation())))
        return true;
    auto k = isLong(decl->getType());
    if (!k)
        return true;
    varDecls_.insert({ decl, k });
    return true;
}

bool ToolsLong::WalkUpFromFieldDecl(FieldDecl const* decl) { return VisitFieldDecl(decl); }

bool ToolsLong::VisitFieldDecl(FieldDecl const* decl)
{
    if (ignoreLocation(decl))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation())))
        return true;
    auto k = isLong(decl->getType());
    if (!k)
        return true;
    TagDecl const* td = dyn_cast<TagDecl>(decl->getDeclContext());
    if (td == nullptr)
    {
        //TODO: ObjCInterface
        return true;
    }
    fieldDecls_.insert({ decl, k });
    return true;
}

bool ToolsLong::WalkUpFromFunctionDecl(FunctionDecl const* decl) { return VisitFunctionDecl(decl); }

bool ToolsLong::VisitFunctionDecl(FunctionDecl const* decl)
{
    if (ignoreLocation(decl))
        return true;
    if (isExcludedFile(compiler.getSourceManager().getSpellingLoc(decl->getLocation())))
        return true;
    auto const fbk = isLong(decl->getReturnType());
    if (!fbk)
        return true;
    if (decl->isDeletedAsWritten() && isa<CXXConversionDecl>(decl))
        return true;
    if (auto const d = dyn_cast<CXXMethodDecl>(decl))
    {
        if (d->isVirtual())
        {
            return true;
        }
    }
    if (decl->isDefined()
        || compiler.getSourceManager().isInMainFile(
               compiler.getSourceManager().getSpellingLoc(decl->getNameInfo().getLoc())))
    {
        functionDecls_.insert({ decl, fbk });
    }
    return true;
}

bool ToolsLong::VisitCallExpr(CallExpr const* expr)
{
    if (ignoreLocation(expr))
    {
        return true;
    }
    auto const d1 = expr->getDirectCallee();
    if (d1 == nullptr || !loplugin::DeclCheck(d1).Function("curl_easy_getinfo").GlobalNamespace())
    {
        return true;
    }
    if (expr->getNumArgs() != 3)
    {
        return true;
    }
    //TODO: Check expr->getArg(1) is CURLINFO_RESPONSE_CODE
    auto const e1 = dyn_cast<UnaryOperator>(expr->getArg(2)->IgnoreParenImpCasts());
    if (e1 == nullptr || e1->getOpcode() != UO_AddrOf)
    {
        return true;
    }
    auto const e2 = dyn_cast<DeclRefExpr>(e1->getSubExpr()->IgnoreParenImpCasts());
    if (e2 == nullptr)
    {
        return true;
    }
    auto const d2 = e2->getDecl();
    if (auto const d3 = dyn_cast<ParmVarDecl>(d2))
    {
        parmVarDecls_.erase(d3);
    }
    else if (auto const d4 = dyn_cast<VarDecl>(d2))
    {
        varDecls_.erase(d4);
    }
    else if (auto const d5 = dyn_cast<FieldDecl>(d2))
    {
        fieldDecls_.erase(d5);
    }
    return true;
}

bool ToolsLong::rewrite(SourceLocation location)
{
    if (rewriter != nullptr)
    {
        SourceLocation loc{ compiler.getSourceManager().getExpansionLoc(location) };
        unsigned n
            = Lexer::MeasureTokenLength(loc, compiler.getSourceManager(), compiler.getLangOpts());
        if (std::string(compiler.getSourceManager().getCharacterData(loc), n) == "long")
        {
            return replaceText(loc, n, "tools::Long");
        }
    }
    return false;
}

bool ToolsLong::isExcludedFile(SourceLocation spellingLocation) const
{
    if (isInUnoIncludeFile(spellingLocation))
        return true;
    auto f = getFilenameOfLocation(spellingLocation);
    return loplugin::hasPathnamePrefix(f, SRCDIR "/include/cppu/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/cppuhelper/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/registry/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/osl/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/rtl/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/sal/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/salhelper/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/typelib/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/include/LibreOfficeKit/"// TODO
           || loplugin::hasPathnamePrefix(f, SRCDIR "/bridges/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/codemaker/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/configmgr/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/cppu/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/cppuhelper/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/external/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/libreofficekit/"// TODO
           || loplugin::hasPathnamePrefix(f, SRCDIR "/registry/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/rtl/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/sal/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/salhelper/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/soltools/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/unoidl/")
           || loplugin::hasPathnamePrefix(f, SRCDIR "/workdir/");
}

loplugin::Plugin::Registration<ToolsLong> X("toolslong"true);
}

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

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

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© 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.