diff options
22 files changed, 672 insertions, 35 deletions
diff --git a/compilerplugins/clang/reducevarscope.cxx b/compilerplugins/clang/reducevarscope.cxx new file mode 100644 index 000000000000..c293fd432e6a --- /dev/null +++ b/compilerplugins/clang/reducevarscope.cxx @@ -0,0 +1,550 @@ +/* -*- 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 <cassert> +#include <string> +#include <iostream> +#include <map> +#include <set> +#include <vector> +#include <unordered_map> +#include <unordered_set> + +#include "plugin.hxx" +#include "check.hxx" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/StmtVisitor.h" + +// Original idea from mike kaganski. +// Look for variables that can have their scoped reduced, which makes the code easier to read. + +// TODO when dealing with vars that are referenced in multiple child blocks, the check is very primitive +// and could be greatly improved. + +namespace +{ +class ReduceVarScope : public loplugin::FilteringPlugin<ReduceVarScope> +{ +public: + explicit ReduceVarScope(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + bool preRun() override + { + if (!compiler.getLangOpts().CPlusPlus) + return false; + // ignore some files with problematic macros + std::string fn(handler.getMainFileName()); + loplugin::normalizeDotDotInFilePath(fn); + // some declarations look better all together + if (fn == SRCDIR "/package/source/manifest/ManifestExport.cxx") + return false; + // storing pointer to OUString internal data + if (fn == SRCDIR "/connectivity/source/drivers/odbc/ODatabaseMetaDataResultSet.cxx" + || fn == SRCDIR "/sc/source/filter/excel/xestyle.cxx" + || fn == SRCDIR "/sw/source/filter/html/htmlflywriter.cxx" + || fn == SRCDIR "/unoxml/source/dom/element.cxx" + || fn == SRCDIR "/unoxml/source/dom/document.cxx" + || fn == SRCDIR "/sd/source/filter/eppt/pptx-animations.cxx") + return false; + if (fn == SRCDIR "/sal/qa/rtl/strings/nonconstarray.cxx") + return false; + return true; + } + + virtual void run() override + { + if (!preRun()) + return; + + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + postRun(); + } + + virtual void postRun() override + { + for (auto const& pair : maVarDeclMap) + { + auto varDecl = pair.first; + auto const& depthInfo = pair.second; + if (depthInfo.maDeclBlockPath.size() == depthInfo.maCommonBlockPath.size()) + continue; + if (maVarDeclToIgnoreSet.find(varDecl) != maVarDeclToIgnoreSet.end()) + continue; + auto it = maVarUseSourceRangeMap.find(varDecl); + if (it == maVarUseSourceRangeMap.end()) + continue; + report(DiagnosticsEngine::Warning, "can reduce scope of var", varDecl->getLocation()) + << varDecl->getSourceRange(); + for (SourceRange const& useRange : it->second) + report(DiagnosticsEngine::Note, "used here", useRange.getBegin()) << useRange; + } + } + + bool VisitUnaryOperator(UnaryOperator const* expr) + { + // if we take the address of it + UnaryOperator::Opcode op = expr->getOpcode(); + if (op == UO_AddrOf) + recordIgnore(expr->getSubExpr()); + return true; + } + + bool VisitDeclRefExpr(const DeclRefExpr*); + bool VisitVarDecl(const VarDecl*); + bool VisitLambdaExpr(const LambdaExpr*); + + bool PreTraverseFunctionDecl(FunctionDecl*); + bool PostTraverseFunctionDecl(FunctionDecl*, bool); + bool TraverseFunctionDecl(FunctionDecl*); + + bool PreTraverseCompoundStmt(CompoundStmt*); + bool PostTraverseCompoundStmt(CompoundStmt*, bool); + bool TraverseCompoundStmt(CompoundStmt*); + + bool PreTraverseWhileStmt(WhileStmt*); + bool PostTraverseWhileStmt(WhileStmt*, bool); + bool TraverseWhileStmt(WhileStmt*); + + bool PreTraverseDoStmt(DoStmt*); + bool PostTraverseDoStmt(DoStmt*, bool); + bool TraverseDoStmt(DoStmt*); + + bool PreTraverseCXXForRangeStmt(CXXForRangeStmt*); + bool PostTraverseCXXForRangeStmt(CXXForRangeStmt*, bool); + bool TraverseCXXForRangeStmt(CXXForRangeStmt*); + + bool PreTraverseForStmt(ForStmt*); + bool PostTraverseForStmt(ForStmt*, bool); + bool TraverseForStmt(ForStmt*); + + bool PreTraverseSwitchStmt(SwitchStmt*); + bool PostTraverseSwitchStmt(SwitchStmt*, bool); + bool TraverseSwitchStmt(SwitchStmt*); + +private: + struct DepthInfo + { + unsigned int mnFirstDepth = 0; + unsigned int mnFirstLoopDepth = 0; + std::vector<unsigned int> maDeclBlockPath = {}; + std::vector<unsigned int> maCommonBlockPath = {}; + }; + std::unordered_map<VarDecl const*, DepthInfo> maVarDeclMap; // varDecl->depth + std::unordered_set<VarDecl const*> maVarDeclToIgnoreSet; + std::map<VarDecl const*, std::vector<SourceRange>> maVarUseSourceRangeMap; + std::vector<unsigned int> maCurrentBlockPath; + unsigned int mnCurrentDepth = 0; + unsigned int mnCurrentLoopDepth = 0; + static unsigned int gnBlockId; + + bool isTypeOK(QualType qt); + bool isInitConstant(const VarDecl* varDecl); + + void recordIgnore(Expr const* expr) + { + for (;;) + { + expr = expr->IgnoreParenImpCasts(); + if (auto const e = dyn_cast<MemberExpr>(expr)) + { + if (isa<FieldDecl>(e->getMemberDecl())) + { + expr = e->getBase(); + continue; + } + } + if (auto const e = dyn_cast<ArraySubscriptExpr>(expr)) + { + expr = e->getBase(); + continue; + } + if (auto const e = dyn_cast<BinaryOperator>(expr)) + { + if (e->getOpcode() == BO_PtrMemD) + { + expr = e->getLHS(); + continue; + } + } + break; + } + auto const dre = dyn_cast<DeclRefExpr>(expr); + if (dre == nullptr) + return; + auto const var = dyn_cast<VarDecl>(dre->getDecl()); + if (var == nullptr) + return; + maVarDeclToIgnoreSet.insert(var); + } +}; + +unsigned int ReduceVarScope::gnBlockId = 0; + +bool ReduceVarScope::PreTraverseFunctionDecl(FunctionDecl* functionDecl) +{ + // Ignore functions that contains #ifdef-ery, can be quite tricky + // to make useful changes when this plugin fires in such functions + if (containsPreprocessingConditionalInclusion(functionDecl->getSourceRange())) + return false; + return true; +} + +bool ReduceVarScope::PostTraverseFunctionDecl(FunctionDecl*, bool) { return true; } + +bool ReduceVarScope::TraverseFunctionDecl(FunctionDecl* functionDecl) +{ + bool ret = true; + if (PreTraverseFunctionDecl(functionDecl)) + { + ret = FilteringPlugin::TraverseFunctionDecl(functionDecl); + PostTraverseFunctionDecl(functionDecl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseCompoundStmt(CompoundStmt*) +{ + assert(mnCurrentDepth != std::numeric_limits<unsigned int>::max()); + ++mnCurrentDepth; + ++gnBlockId; + maCurrentBlockPath.push_back(gnBlockId); + return true; +} + +bool ReduceVarScope::PostTraverseCompoundStmt(CompoundStmt*, bool) +{ + assert(mnCurrentDepth != 0); + --mnCurrentDepth; + maCurrentBlockPath.pop_back(); + return true; +} + +bool ReduceVarScope::TraverseCompoundStmt(CompoundStmt* decl) +{ + bool ret = true; + if (PreTraverseCompoundStmt(decl)) + { + ret = FilteringPlugin::TraverseCompoundStmt(decl); + PostTraverseCompoundStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseWhileStmt(WhileStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits<unsigned int>::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseWhileStmt(WhileStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseWhileStmt(WhileStmt* decl) +{ + bool ret = true; + if (PreTraverseWhileStmt(decl)) + { + ret = FilteringPlugin::TraverseWhileStmt(decl); + PostTraverseWhileStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseDoStmt(DoStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits<unsigned int>::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseDoStmt(DoStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseDoStmt(DoStmt* decl) +{ + bool ret = true; + if (PreTraverseDoStmt(decl)) + { + ret = FilteringPlugin::TraverseDoStmt(decl); + PostTraverseDoStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseSwitchStmt(SwitchStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits<unsigned int>::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseSwitchStmt(SwitchStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +// Consider a switch to be a loop, because weird things happen inside it +bool ReduceVarScope::TraverseSwitchStmt(SwitchStmt* decl) +{ + bool ret = true; + if (PreTraverseSwitchStmt(decl)) + { + ret = FilteringPlugin::TraverseSwitchStmt(decl); + PostTraverseSwitchStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseCXXForRangeStmt(CXXForRangeStmt*) +{ + assert(mnCurrentLoopDepth != std::numeric_limits<unsigned int>::max()); + ++mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::PostTraverseCXXForRangeStmt(CXXForRangeStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseCXXForRangeStmt(CXXForRangeStmt* decl) +{ + bool ret = true; + if (PreTraverseCXXForRangeStmt(decl)) + { + ret = FilteringPlugin::TraverseCXXForRangeStmt(decl); + PostTraverseCXXForRangeStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::PreTraverseForStmt(ForStmt* forStmt) +{ + assert(mnCurrentLoopDepth != std::numeric_limits<unsigned int>::max()); + ++mnCurrentLoopDepth; + + auto declStmt = dyn_cast_or_null<DeclStmt>(forStmt->getInit()); + if (declStmt) + { + if (declStmt->isSingleDecl()) + { + if (auto varDecl = dyn_cast_or_null<VarDecl>(declStmt->getSingleDecl())) + maVarDeclToIgnoreSet.insert(varDecl); + } + else + { + for (auto const& decl : declStmt->getDeclGroup()) + if (auto varDecl = dyn_cast_or_null<VarDecl>(decl)) + maVarDeclToIgnoreSet.insert(varDecl); + } + } + + return true; +} + +bool ReduceVarScope::PostTraverseForStmt(ForStmt*, bool) +{ + assert(mnCurrentLoopDepth != 0); + --mnCurrentLoopDepth; + return true; +} + +bool ReduceVarScope::TraverseForStmt(ForStmt* decl) +{ + bool ret = true; + if (PreTraverseForStmt(decl)) + { + ret = FilteringPlugin::TraverseForStmt(decl); + PostTraverseForStmt(decl, ret); + } + return ret; +} + +bool ReduceVarScope::VisitVarDecl(const VarDecl* varDecl) +{ + if (ignoreLocation(varDecl)) + return true; + if (varDecl->isExceptionVariable() || isa<ParmVarDecl>(varDecl)) + return true; + // ignore stuff in header files (which should really not be there, but anyhow) + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) + return true; + // Ignore macros like FD_ZERO + if (compiler.getSourceManager().isMacroBodyExpansion(compat::getBeginLoc(varDecl))) + return true; + if (varDecl->hasGlobalStorage()) + return true; + if (varDecl->isConstexpr()) + return true; + if (varDecl->isInitCapture()) + return true; + if (varDecl->isCXXForRangeDecl()) + return true; + if (!isTypeOK(varDecl->getType())) + return true; + + if (varDecl->hasInit() && !isInitConstant(varDecl)) + return true; + + maVarDeclMap[varDecl].mnFirstDepth = mnCurrentDepth; + maVarDeclMap[varDecl].mnFirstLoopDepth = mnCurrentLoopDepth; + maVarDeclMap[varDecl].maDeclBlockPath = maCurrentBlockPath; + + return true; +} + +bool ReduceVarScope::isInitConstant(const VarDecl* varDecl) +{ + // check for string or scalar literals + const Expr* initExpr = varDecl->getInit(); + if (auto e = dyn_cast<ExprWithCleanups>(initExpr)) + initExpr = e->getSubExpr(); + if (isa<clang::StringLiteral>(initExpr)) + return true; + if (auto constructExpr = dyn_cast<CXXConstructExpr>(initExpr)) + { + if (constructExpr->getNumArgs() == 0) + { + return true; // i.e., empty string + } + else + { + auto stringLit2 = dyn_cast<clang::StringLiteral>(constructExpr->getArg(0)); + if (stringLit2) + return true; + } + } + + auto const init = varDecl->getInit(); + if (init->isValueDependent()) + return false; + return init->isConstantInitializer(compiler.getASTContext(), false /*ForRef*/); +} + +bool ReduceVarScope::isTypeOK(QualType varType) +{ + // TODO improve this - requires more analysis because it's really easy to + // take a pointer to an array + if (varType->isArrayType()) + return false; + + if (varType.isCXX11PODType(compiler.getASTContext())) + return true; + if (!varType->isRecordType()) + return false; + auto recordDecl = dyn_cast_or_null<CXXRecordDecl>(varType->getAs<RecordType>()->getDecl()); + if (recordDecl && recordDecl->hasTrivialDestructor()) + return true; + auto const tc = loplugin::TypeCheck(varType); + // Safe types with destructors that don't do anything interesting + if (tc.Class("OString").Namespace("rtl").GlobalNamespace() + || tc.Class("OUString").Namespace("rtl").GlobalNamespace() + || tc.Class("OStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("OUStringBuffer").Namespace("rtl").GlobalNamespace() + || tc.Class("Color").GlobalNamespace() || tc.Class("Pair").GlobalNamespace() + || tc.Class("Point").GlobalNamespace() || tc.Class("Size").GlobalNamespace() + || tc.Class("Range").GlobalNamespace() || tc.Class("Selection").GlobalNamespace() + || tc.Class("Rectangle").Namespace("tools").GlobalNamespace()) + return true; + return false; +} + +bool ReduceVarScope::VisitDeclRefExpr(const DeclRefExpr* declRefExpr) +{ + if (ignoreLocation(declRefExpr)) + return true; + const Decl* decl = declRefExpr->getDecl(); + if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl)) + return true; + const VarDecl* varDecl = dyn_cast<VarDecl>(decl)->getCanonicalDecl(); + // ignore stuff in header files (which should really not be there, but anyhow) + if (!compiler.getSourceManager().isInMainFile(varDecl->getLocation())) + return true; + + auto varIt = maVarDeclMap.find(varDecl); + if (varIt == maVarDeclMap.end()) + return true; + + auto& depthInfo = varIt->second; + + // merge block paths to get common ancestor path + if (depthInfo.maCommonBlockPath.empty()) + depthInfo.maCommonBlockPath = maCurrentBlockPath; + else + { + auto len = std::min(depthInfo.maCommonBlockPath.size(), maCurrentBlockPath.size()); + unsigned int i = 0; + while (i < len && depthInfo.maCommonBlockPath[i] == maCurrentBlockPath[i]) + ++i; + depthInfo.maCommonBlockPath.resize(i); + if (depthInfo.maCommonBlockPath == depthInfo.maDeclBlockPath) + { + maVarDeclMap.erase(varIt); + maVarUseSourceRangeMap.erase(varDecl); + return true; + } + } + + // seen in a loop below initial decl + if (mnCurrentLoopDepth > depthInfo.mnFirstLoopDepth) + { + // TODO, we could additionally check if we are reading or writing to the var inside a loop + // We only need to exclude vars that are written to, or passed taken-addr-of, or have non-const method called, + // or passed as arg to non-const-ref parameter. + maVarDeclMap.erase(varIt); + maVarUseSourceRangeMap.erase(varDecl); + return true; + } + + auto it = maVarUseSourceRangeMap.find(varDecl); + if (it == maVarUseSourceRangeMap.end()) + it = maVarUseSourceRangeMap.emplace(varDecl, std::vector<SourceRange>()).first; + it->second.push_back(declRefExpr->getSourceRange()); + + return true; +} + +bool ReduceVarScope::VisitLambdaExpr(const LambdaExpr* lambdaExpr) +{ + if (ignoreLocation(lambdaExpr)) + return true; + for (auto captureIt = lambdaExpr->capture_begin(); captureIt != lambdaExpr->capture_end(); + ++captureIt) + { + const LambdaCapture& capture = *captureIt; + if (capture.capturesVariable()) + { + auto varDecl = capture.getCapturedVar(); + maVarDeclMap.erase(varDecl); + maVarUseSourceRangeMap.erase(varDecl); + } + } + return true; +} + +loplugin::Plugin::Registration<ReduceVarScope> reducevarscope("reducevarscope", false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/test/reducevarscope.cxx b/compilerplugins/clang/test/reducevarscope.cxx new file mode 100644 index 000000000000..ee600c988efe --- /dev/null +++ b/compilerplugins/clang/test/reducevarscope.cxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <rtl/ustring.hxx> + +void test1() +{ + int i = 2; // expected-error {{can reduce scope of var [loplugin:reducevarscope]}} + { + i = 3; // expected-note {{used here [loplugin:reducevarscope]}} + } + int j = 2; // expected-error {{can reduce scope of var [loplugin:reducevarscope]}} + { + j = 3; // expected-note {{used here [loplugin:reducevarscope]}} + { + j = 4; // expected-note {{used here [loplugin:reducevarscope]}} + } + } +} + +// negative test - seen inside a loop +void test2() +{ + int i = 2; + for (int j = 1; j < 10; ++j) + { + i = 3; + } +} + +// negative test - initial assignment from non-constant +void test3() +{ + int j = 1; + int i = j; + { + i = 3; + } +} + +// negative test +void test4() +{ + int i = 2; + { + i = 3; + } + i = 4; +} + +// negative test +void test5() +{ + int i = 2; + i = 3; +} + +// negative test - seen in 2 child blocks +void test6() +{ + int i; + { + i = 3; + } + { + i = 3; + } +} + +// TODO negative test - storing pointer to OUString data +// void test7() +// { +// OUString s; +// const sal_Unicode* p = nullptr; +// { +// p = s.getStr(); +// } +// auto p2 = p; +// (void)p2; +// } + +// negative test - passing var into lambda +void test8() +{ + int i; + auto l1 = [&]() { i = 1; }; + (void)l1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx index fe9ef7dbd2b4..070f1edd966b 100644 --- a/cppuhelper/source/servicemanager.cxx +++ b/cppuhelper/source/servicemanager.cxx @@ -1912,13 +1912,13 @@ void cppuhelper::ServiceManager::preloadImplementations() { if (aModule.is() && !rEntry.second->environment.isEmpty()) { - OUString aSymFactory; oslGenericFunction fpFactory; css::uno::Environment aTargetEnv; css::uno::Reference<css::uno::XInterface> xFactory; if(rEntry.second->constructorName.isEmpty()) { + OUString aSymFactory; // expand full name component factory symbol if (rEntry.second->prefix == "direct") aSymFactory = rEntry.second->name.replace('.', '_') + "_" COMPONENT_GETFACTORY; diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 27e21a881540..526f00518910 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -2202,7 +2202,6 @@ void VclMetafileProcessor2D::processTransparencePrimitive2D( static_cast<sal_Int32>(ceil(aViewRange.getMaxY()))); const tools::Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic)); Size aSizePixel(aRectPixel.GetSize()); - const Point aEmptyPoint; ScopedVclPtrInstance<VirtualDevice> aBufferDevice; const sal_uInt32 nMaxQuadratPixels(500000); const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight()); @@ -2258,6 +2257,7 @@ void VclMetafileProcessor2D::processTransparencePrimitive2D( VclPixelProcessor2D aBufferProcessor(aViewInfo, *aBufferDevice); // draw content using pixel renderer + const Point aEmptyPoint; aBufferProcessor.process(rContent); const Bitmap aBmContent(aBufferDevice->GetBitmap(aEmptyPoint, aSizePixel)); diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index 3829ffe562df..bd1d1f082455 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -2211,9 +2211,9 @@ void FormulaCompiler::CreateStringFromTokenArray( OUStringBuffer& rBuffer ) else if ( FormulaGrammar::isOOXML( meGrammar ) ) { // Scan token array for missing args and rewrite if present. - MissingConventionOOXML aConv; if (pArr->NeedsOoxmlRewrite()) { + MissingConventionOOXML aConv; pArr = pArr->RewriteMissing( aConv ); maArrIterator = FormulaTokenArrayPlainIterator( *pArr ); } diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx index 92f60254ec8f..37dd26979ced 100644 --- a/formula/source/core/api/token.cxx +++ b/formula/source/core/api/token.cxx @@ -1389,12 +1389,11 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention & ++nFn; // all following operations on _that_ function pCtx[ nFn ].mpFunc = aIter.PeekPrevNoSpaces(); pCtx[ nFn ].mnCurArg = 0; - OpCode eOp; if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress) pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF else if ((rConv.isODFF() || rConv.isOOXML()) && pCtx[ nFn ].mpFunc) { - eOp = pCtx[ nFn ].mpFunc->GetOpCode(); + OpCode eOp = pCtx[ nFn ].mpFunc->GetOpCode(); if (eOp == ocDBCount || eOp == ocDBCount2) pOcds[ nOcds++ ] = nFn; // entering DCOUNT() or DCOUNTA() if ODFF or OOXML } diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx index 23bd70300135..0c52a2b3cf45 100644 --- a/i18nlangtag/source/languagetag/languagetag.cxx +++ b/i18nlangtag/source/languagetag/languagetag.cxx @@ -2241,12 +2241,11 @@ LanguageTag & LanguageTag::makeFallback() else if (maBcp47 == "en-GB-oxendict") aVec.emplace_back("en-GB-oed"); - OUString aScript; OUString aVariants( getVariants()); OUString aTmp; if (hasScript()) { - aScript = getScript(); + OUString aScript = getScript(); bool bHaveLanguageScriptVariant = false; if (!aCountry.isEmpty()) { diff --git a/i18npool/qa/cppunit/test_breakiterator.cxx b/i18npool/qa/cppunit/test_breakiterator.cxx index 36f145e79958..864387415124 100644 --- a/i18npool/qa/cppunit/test_breakiterator.cxx +++ b/i18npool/qa/cppunit/test_breakiterator.cxx @@ -123,12 +123,11 @@ void TestBreakIterator::testLineBreaking() //See https://bz.apache.org/ooo/show_bug.cgi?id=19716 { - OUString aTest("aaa]aaa"); - aLocale.Language = "en"; aLocale.Country = "US"; { + OUString aTest("aaa]aaa"); //Here we want the line break to move the whole lot to the next line i18n::LineBreakResults aResult = m_xBreak->getLineBreak(aTest, aTest.getLength()-2, aLocale, 0, aHyphOptions, aUserOptions); @@ -1030,13 +1029,12 @@ void TestBreakIterator::testChinese() lang::Locale aLocale; aLocale.Language = "zh"; aLocale.Country = "CN"; - i18n::Boundary aBounds; { const sal_Unicode CHINESE[] = { 0x6A35, 0x6A30, 0x69FE, 0x8919, 0xD867, 0xDEDB }; OUString aTest(CHINESE, SAL_N_ELEMENTS(CHINESE)); - aBounds = m_xBreak->getWordBoundary(aTest, 4, aLocale, + i18n::Boundary aBounds = m_xBreak->getWordBoundary(aTest, 4, aLocale, i18n::WordType::DICTIONARY_WORD, true); CPPUNIT_ASSERT(aBounds.startPos == 4 && aBounds.endPos == 6); } diff --git a/idlc/source/idlc.cxx b/idlc/source/idlc.cxx index 5984ca759448..c1d09b4c1b2e 100644 --- a/idlc/source/idlc.cxx +++ b/idlc/source/idlc.cxx @@ -273,8 +273,8 @@ OUString Idlc::processDocumentation() static void lcl_writeString(::osl::File & rFile, ::osl::FileBase::RC & o_rRC, OString const& rString) { - sal_uInt64 nWritten(0); if (::osl::FileBase::E_None == o_rRC) { + sal_uInt64 nWritten(0); o_rRC = rFile.write(rString.getStr(), rString.getLength(), nWritten); if (static_cast<sal_uInt64>(rString.getLength()) != nWritten) { o_rRC = ::osl::FileBase::E_INVAL; //? diff --git a/idlc/source/options.cxx b/idlc/source/options.cxx index 0ab0a9cc32d2..1b74a2367578 100644 --- a/idlc/source/options.cxx +++ b/idlc/source/options.cxx @@ -168,9 +168,9 @@ bool Options::checkCommandFile (std::vector< std::string > & rArgs, char const * bool Options::badOption(char const * reason, std::string const & rArg) { - OStringBuffer message; if (reason != nullptr) { + OStringBuffer message; message.append(reason); message.append(" option '"); message.append(rArg.c_str()); message.append("'"); throw IllegalArgument(message.makeStringAndClear()); } diff --git a/l10ntools/source/cfgmerge.cxx b/l10ntools/source/cfgmerge.cxx index e02e497d5d21..5715bd1c1d14 100644 --- a/l10ntools/source/cfgmerge.cxx +++ b/l10ntools/source/cfgmerge.cxx @@ -164,7 +164,6 @@ void CfgParser::ExecuteAnalyzedToken( int nToken, char *pToken ) sLastWhitespace += sToken; OString sTokenName; - OString sTokenId; bool bOutput = true; @@ -222,6 +221,7 @@ void CfgParser::ExecuteAnalyzedToken( int nToken, char *pToken ) } break; } + OString sTokenId; if ( !sSearch.isEmpty()) { OString sTemp = sToken.copy( sToken.indexOf( sSearch )); diff --git a/l10ntools/source/helpmerge.cxx b/l10ntools/source/helpmerge.cxx index abab8a5a03a1..10a9de923175 100644 --- a/l10ntools/source/helpmerge.cxx +++ b/l10ntools/source/helpmerge.cxx @@ -192,7 +192,6 @@ void HelpParser::MergeSingleFile( XMLFile* file , MergeDataFile* pMergeDataFile void HelpParser::ProcessHelp( LangHashMap* aLangHM , const OString& sCur , ResData *pResData , MergeDataFile* pMergeDataFile ){ XMLElement* pXMLElement = nullptr; - MergeEntrys *pEntrys = nullptr; if( sCur.equalsIgnoreAsciiCase("en-US") ) return; @@ -228,7 +227,7 @@ void HelpParser::ProcessHelp( LangHashMap* aLangHM , const OString& sCur , ResDa } else if( pMergeDataFile ) { - pEntrys = pMergeDataFile->GetMergeEntrys( pResData ); + MergeEntrys *pEntrys = pMergeDataFile->GetMergeEntrys( pResData ); if( pEntrys != nullptr) { pEntrys->GetText( sNewText, sCur, true ); diff --git a/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx b/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx index 988306757a96..f60e2c7b83fe 100644 --- a/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx +++ b/lingucomponent/source/hyphenator/hyphen/hyphenimp.cxx @@ -258,7 +258,6 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo sal_Int16 minLen = rHelper.GetMinWordLength(); bool bNoHyphenateCaps = rHelper.IsNoHyphenateCaps(); - HyphenDict *dict = nullptr; rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW; Reference< XHyphenatedWord > xRes; @@ -285,7 +284,7 @@ Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWo } // otherwise hyphenate the word with that dictionary - dict = mvDicts[k].aPtr; + HyphenDict *dict = mvDicts[k].aPtr; eEnc = mvDicts[k].eEnc; CharClass * pCC = mvDicts[k].apCC.get(); diff --git a/linguistic/source/hyphdsp.cxx b/linguistic/source/hyphdsp.cxx index 4ce8d4aa099d..be33885880d3 100644 --- a/linguistic/source/hyphdsp.cxx +++ b/linguistic/source/hyphdsp.cxx @@ -88,7 +88,6 @@ Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord( if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=' && aText[ nTextLen - 1 ] != '[') { sal_Int16 nHyphenationPos = -1; - sal_Int32 nHyphenPos = -1; sal_Int16 nOrigHyphPos = -1; OUStringBuffer aTmp( nTextLen ); @@ -149,6 +148,7 @@ Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord( } } #endif + sal_Int32 nHyphenPos = -1; if (aText[ nOrigHyphPos ] == '[') // alternative hyphenation { sal_Int16 split = 0; diff --git a/sc/qa/unit/ucalc_sort.cxx b/sc/qa/unit/ucalc_sort.cxx index 64acbcc1eab0..829fa82b56e0 100644 --- a/sc/qa/unit/ucalc_sort.cxx +++ b/sc/qa/unit/ucalc_sort.cxx @@ -41,7 +41,6 @@ void Test::testSort() // We need a drawing layer in order to create caption objects. m_pDoc->InitDrawLayer(&getDocShell()); - ScRange aDataRange; ScAddress aPos(0,0,0); { const char* aData[][2] = { @@ -52,7 +51,7 @@ void Test::testSort() }; clearRange(m_pDoc, ScRange(0, 0, 0, 1, SAL_N_ELEMENTS(aData), 0)); - aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData)); + ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData)); CPPUNIT_ASSERT_EQUAL_MESSAGE("failed to insert range data at correct position", aPos, aDataRange.aStart); } @@ -80,6 +79,7 @@ void Test::testSort() pNote = m_pDoc->GetNote(1, 0, 0); CPPUNIT_ASSERT(pNote); + ScRange aDataRange; clearRange(m_pDoc, ScRange(0, 0, 0, 1, 9, 0)); // Clear A1:B10. { // 0 = empty cell diff --git a/slideshow/source/engine/shapes/drawinglayeranimation.cxx b/slideshow/source/engine/shapes/drawinglayeranimation.cxx index 371f7058d1d6..0b37071fb644 100644 --- a/slideshow/source/engine/shapes/drawinglayeranimation.cxx +++ b/slideshow/source/engine/shapes/drawinglayeranimation.cxx @@ -305,7 +305,7 @@ double ActivityImpl::GetMixerState( sal_uInt32 nTime ) sal_uInt32 ActivityImpl::GetStepWidthLogic() const { // #i69847# Assuming higher DPI - sal_uInt32 const PIXEL_TO_LOGIC = 30; + constexpr sal_uInt32 PIXEL_TO_LOGIC = 30; sal_uInt32 nRetval(0); diff --git a/solenv/CompilerTest_compilerplugins_clang.mk b/solenv/CompilerTest_compilerplugins_clang.mk index a8cc4ad731af..b707954c3319 100644 --- a/solenv/CompilerTest_compilerplugins_clang.mk +++ b/solenv/CompilerTest_compilerplugins_clang.mk @@ -58,6 +58,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \ compilerplugins/clang/test/passparamsbyref \ compilerplugins/clang/test/passstuffbyref \ compilerplugins/clang/test/pointerbool \ + compilerplugins/clang/test/reducevarscope \ compilerplugins/clang/test/redundantcast \ compilerplugins/clang/test/redundantfcast \ compilerplugins/clang/test/redundantinline \ diff --git a/sot/source/sdstor/stgavl.cxx b/sot/source/sdstor/stgavl.cxx index 0c78054045f0..98a86f3edb96 100644 --- a/sot/source/sdstor/stgavl.cxx +++ b/sot/source/sdstor/stgavl.cxx @@ -284,7 +284,7 @@ void StgAvlNode::StgEnum( short& n ) bool StgAvlNode::Insert( StgAvlNode** pRoot, StgAvlNode* pIns ) { - StgAvlNode* pPivot, *pHeavy, *pNewRoot, *pParent, *pPrev; + StgAvlNode* pPivot, *pHeavy, *pParent, *pPrev; if ( !pRoot ) return false; @@ -310,6 +310,7 @@ bool StgAvlNode::Insert( StgAvlNode** pRoot, StgAvlNode* pIns ) short nDelta = pPivot->Adjust( &pHeavy, pIns ); if( pPivot->m_nBalance >= 2 || pPivot->m_nBalance <= -2 ) { + StgAvlNode* pNewRoot; pHeavy = ( nDelta < 0 ) ? pPivot->m_pRight : pPivot->m_pLeft; // left imbalance if( nDelta > 0 ) diff --git a/stoc/source/defaultregistry/defaultregistry.cxx b/stoc/source/defaultregistry/defaultregistry.cxx index 92adf4642938..ff4c2483e34b 100644 --- a/stoc/source/defaultregistry/defaultregistry.cxx +++ b/stoc/source/defaultregistry/defaultregistry.cxx @@ -807,13 +807,12 @@ sal_Bool SAL_CALL NestedKeyImpl::createLink( const OUString& aLinkName, const OU throw InvalidRegistryException(); } - OUString linkName; OUString resolvedName; sal_Int32 lastIndex = aLinkName.lastIndexOf('/'); if ( lastIndex > 0 ) { - linkName = aLinkName.copy(0, lastIndex); + OUString linkName = aLinkName.copy(0, lastIndex); resolvedName = computeName(linkName); @@ -862,13 +861,12 @@ void SAL_CALL NestedKeyImpl::deleteLink( const OUString& rLinkName ) throw InvalidRegistryException(); } - OUString linkName; OUString resolvedName; sal_Int32 lastIndex = rLinkName.lastIndexOf('/'); if ( lastIndex > 0 ) { - linkName = rLinkName.copy(0, lastIndex); + OUString linkName = rLinkName.copy(0, lastIndex); resolvedName = computeName(linkName); @@ -905,13 +903,12 @@ OUString SAL_CALL NestedKeyImpl::getLinkTarget( const OUString& rLinkName ) throw InvalidRegistryException(); } - OUString linkName; OUString resolvedName; sal_Int32 lastIndex = rLinkName.lastIndexOf('/'); if ( lastIndex > 0 ) { - linkName = rLinkName.copy(0, lastIndex); + OUString linkName = rLinkName.copy(0, lastIndex); resolvedName = computeName(linkName); diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index a1430890f010..8f1aca1a64b4 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -2613,7 +2613,6 @@ bool SwDrawTextInfo::ApplyAutoColor( vcl::Font* pFont ) std::optional<Color> pCol; if (GetFont()) pCol = GetFont()->GetBackColor(); - Color aColor; if( ! pCol || COL_TRANSPARENT == *pCol ) { const SvxBrushItem* pItem; @@ -2631,8 +2630,7 @@ bool SwDrawTextInfo::ApplyAutoColor( vcl::Font* pFont ) if (aFillAttributes && aFillAttributes->isUsed()) { // First see if fill attributes provide a color. - aColor = Color(aFillAttributes->getAverageColor(aGlobalRetoucheColor.getBColor())); - pCol = aColor; + pCol = Color(aFillAttributes->getAverageColor(aGlobalRetoucheColor.getBColor())); } // If not, then fall back to the old brush item. diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx index c4dadd35dc74..acdcede9d6f9 100644 --- a/writerfilter/source/dmapper/PropertyMap.cxx +++ b/writerfilter/source/dmapper/PropertyMap.cxx @@ -1389,10 +1389,10 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl ) uno::Reference< text::XTextRange > xRange; aFramedRedlines[i] >>= xRange; uno::Reference< beans::XPropertySet > xRangeProperties; - OUString sTableName; - OUString sCellName; if ( xRange.is() ) { + OUString sTableName; + OUString sCellName; xRangeProperties.set( xRange, uno::UNO_QUERY_THROW ); if (xRangeProperties->getPropertySetInfo()->hasPropertyByName("TextTable")) { diff --git a/xmlhelp/source/cxxhelp/provider/databases.cxx b/xmlhelp/source/cxxhelp/provider/databases.cxx index 5c42fa2349e5..5353f6e82ac3 100644 --- a/xmlhelp/source/cxxhelp/provider/databases.cxx +++ b/xmlhelp/source/cxxhelp/provider/databases.cxx @@ -781,9 +781,9 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const OUString& jar, if( ! it->second.is() ) { - OUString zipFile; try { + OUString zipFile; // Extension jar file? Search for ? sal_Int32 nQuestionMark1 = jar.indexOf( '?' ); sal_Int32 nQuestionMark2 = jar.lastIndexOf( '?' ); |