summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/constparams.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/constparams.cxx')
-rw-r--r--compilerplugins/clang/constparams.cxx595
1 files changed, 0 insertions, 595 deletions
diff --git a/compilerplugins/clang/constparams.cxx b/compilerplugins/clang/constparams.cxx
deleted file mode 100644
index 95c8184009d7..000000000000
--- a/compilerplugins/clang/constparams.cxx
+++ /dev/null
@@ -1,595 +0,0 @@
-/* -*- 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 <string>
-#include <unordered_set>
-#include <unordered_map>
-#include <iostream>
-
-#include "config_clang.h"
-
-#include "plugin.hxx"
-#include "compat.hxx"
-#include "check.hxx"
-#include "functionaddress.hxx"
-
-#if CLANG_VERSION >= 110000
-#include "clang/AST/ParentMapContext.h"
-#endif
-
-/**
- Find pointer and reference params that can be declared const.
-
- This is not a sophisticated analysis. It deliberately skips all of the hard cases for now.
- It is an exercise in getting the most benefit for the least effort.
-*/
-namespace
-{
-
-class ConstParams:
- public loplugin::FunctionAddress<loplugin::FilteringPlugin<ConstParams>>
-{
-public:
- explicit ConstParams(loplugin::InstantiationData const & data): FunctionAddress(data) {}
-
- virtual void run() override {
- std::string fn(handler.getMainFileName());
- loplugin::normalizeDotDotInFilePath(fn);
- if (loplugin::hasPathnamePrefix(fn, SRCDIR "/sal/")
- || fn == SRCDIR "/jurt/source/pipe/staticsalhack.cxx"
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/bridges/")
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/binaryurp/")
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/stoc/")
- || loplugin::hasPathnamePrefix(fn, WORKDIR "/YaccTarget/unoidl/source/sourceprovider-parser.cxx")
- // some weird calling through a function pointer
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/svtools/source/table/defaultinputhandler.cxx")
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/sdext/source/pdfimport/test/pdfunzip.cxx")
- // windows only
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/basic/source/sbx/sbxdec.cxx")
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/sfx2/source/doc/syspath.cxx")
- // ignore this for now
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/libreofficekit")
- // FunctionAddress not working well enough here
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/pyuno/source/module/pyuno_struct.cxx")
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/pyuno/source/module/pyuno.cxx")
- || loplugin::hasPathnamePrefix(fn, SRCDIR "/sw/source/filter/ascii/ascatr.cxx")
- )
- return;
-
- TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
-
- for (const ParmVarDecl *pParmVarDecl : interestingParamSet) {
- auto functionDecl = parmToFunction[pParmVarDecl];
- auto canonicalDecl = functionDecl->getCanonicalDecl();
- if (getFunctionsWithAddressTaken().find(canonicalDecl)
- != getFunctionsWithAddressTaken().end())
- {
- continue;
- }
- std::string fname = functionDecl->getQualifiedNameAsString();
- report(
- DiagnosticsEngine::Warning,
- "this parameter can be const %0",
- compat::getBeginLoc(pParmVarDecl))
- << fname << pParmVarDecl->getSourceRange();
- if (canonicalDecl->getLocation() != functionDecl->getLocation()) {
- unsigned idx = pParmVarDecl->getFunctionScopeIndex();
- const ParmVarDecl* pOther = canonicalDecl->getParamDecl(idx);
- report(
- DiagnosticsEngine::Note,
- "canonical parameter declaration here",
- compat::getBeginLoc(pOther))
- << pOther->getSourceRange();
- }
- //functionDecl->dump();
- }
- }
-
- bool TraverseFunctionDecl(FunctionDecl *);
- bool TraverseCXXMethodDecl(CXXMethodDecl * f);
- bool TraverseCXXConstructorDecl(CXXConstructorDecl * f);
- bool VisitDeclRefExpr(const DeclRefExpr *);
-
-private:
- bool CheckTraverseFunctionDecl(FunctionDecl *);
- bool checkIfCanBeConst(const Stmt*, const ParmVarDecl*);
- // integral or enumeration or const * or const &
- bool isOkForParameter(const QualType& qt);
- bool isPointerOrReferenceToNonConst(const QualType& qt);
-
- std::unordered_set<const ParmVarDecl*> interestingParamSet;
- std::unordered_map<const ParmVarDecl*, const FunctionDecl*> parmToFunction;
- FunctionDecl* currentFunctionDecl = nullptr;
-};
-
-bool ConstParams::TraverseFunctionDecl(FunctionDecl * functionDecl)
-{
- // We cannot short-circuit the traverse here entirely without breaking the
- // loplugin::FunctionAddress stuff.
- auto prev = currentFunctionDecl;
- if (CheckTraverseFunctionDecl(functionDecl))
- currentFunctionDecl = functionDecl;
- auto rv = FunctionAddress::TraverseFunctionDecl(functionDecl);
- currentFunctionDecl = prev;
- return rv;
-}
-bool ConstParams::TraverseCXXMethodDecl(CXXMethodDecl * f)
-{
- auto prev = currentFunctionDecl;
- if (CheckTraverseFunctionDecl(f))
- currentFunctionDecl = f;
- auto rv = FunctionAddress::TraverseCXXMethodDecl(f);
- currentFunctionDecl = prev;
- return rv;
-}
-bool ConstParams::TraverseCXXConstructorDecl(CXXConstructorDecl * f)
-{
- auto prev = currentFunctionDecl;
- if (CheckTraverseFunctionDecl(f))
- currentFunctionDecl = f;
- auto rv = FunctionAddress::TraverseCXXConstructorDecl(f);
- currentFunctionDecl = prev;
- return rv;
-}
-
-bool ConstParams::CheckTraverseFunctionDecl(FunctionDecl * functionDecl)
-{
- if (ignoreLocation(functionDecl) || !functionDecl->isThisDeclarationADefinition()) {
- return false;
- }
- // ignore stuff that forms part of the stable URE interface
- if (isInUnoIncludeFile(functionDecl)) {
- return false;
- }
- if (functionDecl->isDeleted())
- return false;
- // ignore virtual methods
- if (isa<CXXMethodDecl>(functionDecl)
- && dyn_cast<CXXMethodDecl>(functionDecl)->isVirtual() ) {
- return false;
- }
- // ignore C main
- if (functionDecl->isMain()) {
- return false;
- }
-
- // ignore the macros from include/tools/link.hxx
- auto canonicalDecl = functionDecl->getCanonicalDecl();
- if (compiler.getSourceManager().isMacroBodyExpansion(compat::getBeginLoc(canonicalDecl))
- || compiler.getSourceManager().isMacroArgExpansion(compat::getBeginLoc(canonicalDecl))) {
- StringRef name { Lexer::getImmediateMacroName(
- compat::getBeginLoc(canonicalDecl), compiler.getSourceManager(), compiler.getLangOpts()) };
- if (name.startswith("DECL_LINK") || name.startswith("DECL_STATIC_LINK"))
- return false;
- auto loc2 = compat::getImmediateExpansionRange(compiler.getSourceManager(), compat::getBeginLoc(canonicalDecl)).first;
- if (compiler.getSourceManager().isMacroBodyExpansion(loc2))
- {
- StringRef name2 { Lexer::getImmediateMacroName(
- loc2, compiler.getSourceManager(), compiler.getLangOpts()) };
- if (name2.startswith("DECL_DLLPRIVATE_LINK"))
- return false;
- }
- }
-
- if (functionDecl->getIdentifier())
- {
- StringRef name = functionDecl->getName();
- if ( name == "file_write"
- || name == "SalMainPipeExchangeSignal_impl"
- || name.startswith("SbRtl_")
- || name == "GoNext"
- || name == "GoPrevious"
- || name.startswith("Read_F_")
- // UNO component entry points
- || name.endswith("component_getFactory")
- || name == "egiGraphicExport"
- || name == "etiGraphicExport"
- || name == "epsGraphicExport"
- // callback for some external code?
- || name == "ScAddInAsyncCallBack"
- // used as function pointers
- || name == "Read_Footnote"
- || name == "Read_Field"
- || name == "Read_And"
- // passed as a LINK<> to another method
- || name == "GlobalBasicErrorHdl_Impl"
- // template
- || name == "extract_throw" || name == "readProp"
- // callbacks
- || name == "signalDragDropReceived" || name == "signal_column_clicked" || name == "signal_key_press"
- )
- return false;
-
- }
-
- std::string fqn = functionDecl->getQualifiedNameAsString();
- if ( fqn == "connectivity::jdbc::GlobalRef::set"
- || fqn == "(anonymous namespace)::ReorderNotifier::operator()"
- || fqn == "static_txtattr_cast")
- return false;
-
- // calculate the ones we want to check
- bool foundInterestingParam = false;
- for (const ParmVarDecl *pParmVarDecl : functionDecl->parameters()) {
- // ignore unused params
- if (pParmVarDecl->getName().empty()
- || pParmVarDecl->hasAttr<UnusedAttr>())
- continue;
- auto const type = loplugin::TypeCheck(pParmVarDecl->getType());
- if (!( type.Pointer().NonConst()
- || type.LvalueReference().NonConst()))
- continue;
- // since we normally can't change typedefs, just ignore them
- if (isa<TypedefType>(pParmVarDecl->getType()))
- continue;
- // some typedefs turn into these
- if (isa<DecayedType>(pParmVarDecl->getType()))
- continue;
- // TODO ignore these for now, has some effects I don't understand
- if (type.Pointer().Pointer())
- continue;
- // const is meaningless when applied to function pointer types
- if (pParmVarDecl->getType()->isFunctionPointerType())
- continue;
- interestingParamSet.insert(pParmVarDecl);
- parmToFunction[pParmVarDecl] = functionDecl;
- foundInterestingParam = true;
- }
- return foundInterestingParam;
-}
-
-bool ConstParams::VisitDeclRefExpr( const DeclRefExpr* declRefExpr )
-{
- if (!currentFunctionDecl)
- return true;
- const ParmVarDecl* parmVarDecl = dyn_cast_or_null<ParmVarDecl>(declRefExpr->getDecl());
- if (!parmVarDecl)
- return true;
- if (interestingParamSet.find(parmVarDecl) == interestingParamSet.end())
- return true;
- if (!checkIfCanBeConst(declRefExpr, parmVarDecl))
- interestingParamSet.erase(parmVarDecl);
- return true;
-}
-
-// Walk up from a statement that contains a DeclRefExpr, checking if the usage means that the
-// related ParamVarDecl can be const.
-bool ConstParams::checkIfCanBeConst(const Stmt* stmt, const ParmVarDecl* parmVarDecl)
-{
- const Stmt* parent = getParentStmt( stmt );
- if (!parent)
- {
- // check if we're inside a CXXCtorInitializer
- auto parentsRange = compiler.getASTContext().getParents(*stmt);
- if ( parentsRange.begin() != parentsRange.end())
- {
- if (auto cxxConstructorDecl = dyn_cast_or_null<CXXConstructorDecl>(parentsRange.begin()->get<Decl>()))
- {
- for ( auto cxxCtorInitializer : cxxConstructorDecl->inits())
- {
- if ( cxxCtorInitializer->getInit() == stmt)
- {
- if (cxxCtorInitializer->isAnyMemberInitializer())
- {
- // if the member is not pointer-to-const or ref-to-const or value, we cannot make the param const
- auto fieldDecl = cxxCtorInitializer->getAnyMember();
- auto tc = loplugin::TypeCheck(fieldDecl->getType());
- if (tc.Pointer() || tc.LvalueReference())
- return tc.Pointer().Const() || tc.LvalueReference().Const();
- else
- return true;
- }
- else
- {
- // probably base initialiser, but no simple way to look up the relevant constructor decl
- return false;
- }
- }
- }
- }
- if (auto varDecl = dyn_cast_or_null<VarDecl>(parentsRange.begin()->get<Decl>()))
- {
- return isOkForParameter(varDecl->getType());
- }
- }
- parmVarDecl->dump();
- stmt->dump();
- report(
- DiagnosticsEngine::Warning,
- "no parent?",
- compat::getBeginLoc(stmt))
- << stmt->getSourceRange();
- return false;
- }
-
- if (auto unaryOperator = dyn_cast<UnaryOperator>(parent)) {
- UnaryOperator::Opcode op = unaryOperator->getOpcode();
- if (op == UO_AddrOf || op == UO_PreInc || op == UO_PostInc
- || op == UO_PreDec || op == UO_PostDec) {
- return false;
- }
- if (op == UO_Deref) {
- return checkIfCanBeConst(parent, parmVarDecl);
- }
- return true;
- } else if (auto binaryOp = dyn_cast<BinaryOperator>(parent)) {
- BinaryOperator::Opcode op = binaryOp->getOpcode();
- if (binaryOp->getRHS() == stmt && op == BO_Assign) {
- return isOkForParameter(binaryOp->getLHS()->getType());
- }
- if (binaryOp->getRHS() == stmt) {
- return true;
- }
- if (op == BO_Assign || op == BO_PtrMemD || op == BO_PtrMemI || op == BO_MulAssign
- || op == BO_DivAssign || op == BO_RemAssign || op == BO_AddAssign
- || op == BO_SubAssign || op == BO_ShlAssign || op == BO_ShrAssign
- || op == BO_AndAssign || op == BO_XorAssign || op == BO_OrAssign) {
- return false;
- }
- // for pointer arithmetic need to check parent
- if (binaryOp->getType()->isPointerType()) {
- return checkIfCanBeConst(parent, parmVarDecl);
- }
- return true;
- } else if (auto constructExpr = dyn_cast<CXXConstructExpr>(parent)) {
- const CXXConstructorDecl * constructorDecl = constructExpr->getConstructor();
- for (unsigned i = 0; i < constructExpr->getNumArgs(); ++i) {
- if (constructExpr->getArg(i) == stmt) {
- return isOkForParameter(constructorDecl->getParamDecl(i)->getType());
- }
- }
- } else if (auto operatorCallExpr = dyn_cast<CXXOperatorCallExpr>(parent)) {
- const CXXMethodDecl* calleeMethodDecl = dyn_cast_or_null<CXXMethodDecl>(operatorCallExpr->getDirectCallee());
- if (calleeMethodDecl) {
- // unary operator
- if (calleeMethodDecl->getNumParams() == 0)
- return calleeMethodDecl->isConst();
- // Same logic as CXXOperatorCallExpr::isAssignmentOp(), which our supported clang
- // doesn't have yet.
- auto Opc = operatorCallExpr->getOperator();
- if (Opc == OO_Equal || Opc == OO_StarEqual ||
- Opc == OO_SlashEqual || Opc == OO_PercentEqual ||
- Opc == OO_PlusEqual || Opc == OO_MinusEqual ||
- Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual ||
- Opc == OO_AmpEqual || Opc == OO_CaretEqual ||
- Opc == OO_PipeEqual)
- {
- if (operatorCallExpr->getArg(0) == stmt) // assigning to the param
- return false;
- // not all operator= take a const&
- return isOkForParameter(calleeMethodDecl->getParamDecl(0)->getType());
- }
- if (operatorCallExpr->getOperator() == OO_Subscript && operatorCallExpr->getArg(1) == stmt)
- return true;
- if (operatorCallExpr->getOperator() == OO_EqualEqual || operatorCallExpr->getOperator() == OO_ExclaimEqual)
- return true;
- // binary operator
- if (operatorCallExpr->getArg(0) == stmt)
- return calleeMethodDecl->isConst();
- unsigned const n = std::min(
- operatorCallExpr->getNumArgs(),
- calleeMethodDecl->getNumParams() + 1);
- for (unsigned i = 1; i < n; ++i)
- if (operatorCallExpr->getArg(i) == stmt) {
- auto qt = calleeMethodDecl->getParamDecl(i - 1)->getType();
- return isOkForParameter(qt);
- }
- } else {
- const Expr* callee = operatorCallExpr->getCallee()->IgnoreParenImpCasts();
- const DeclRefExpr* dr = dyn_cast<DeclRefExpr>(callee);
- const FunctionDecl* calleeFunctionDecl = nullptr;
- if (dr) {
- calleeFunctionDecl = dyn_cast<FunctionDecl>(dr->getDecl());
- }
- if (calleeFunctionDecl) {
- for (unsigned i = 0; i < operatorCallExpr->getNumArgs(); ++i) {
- if (operatorCallExpr->getArg(i) == stmt) {
- return isOkForParameter(calleeFunctionDecl->getParamDecl(i)->getType());
- }
- }
- }
- }
- return false;
- } else if (auto callExpr = dyn_cast<CallExpr>(parent)) {
- QualType functionType = callExpr->getCallee()->getType();
- if (functionType->isFunctionPointerType()) {
- functionType = functionType->getPointeeType();
- }
- if (const FunctionProtoType* prototype = functionType->getAs<FunctionProtoType>()) {
- // TODO could do better
- if (prototype->isVariadic()) {
- return false;
- }
- if (callExpr->getCallee() == stmt) {
- return true;
- }
- for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) {
- if (callExpr->getArg(i) == stmt) {
- return isOkForParameter(prototype->getParamType(i));
- }
- }
- }
- const FunctionDecl* calleeFunctionDecl = callExpr->getDirectCallee();
- if (calleeFunctionDecl)
- {
- if (auto memberCallExpr = dyn_cast<CXXMemberCallExpr>(parent)) {
- const MemberExpr* memberExpr = dyn_cast<MemberExpr>(stmt);
- if (memberExpr && memberCallExpr->getImplicitObjectArgument() == memberExpr->getBase())
- {
- const CXXMethodDecl* calleeMethodDecl = dyn_cast<CXXMethodDecl>(calleeFunctionDecl);
- return calleeMethodDecl->isConst();
- }
- }
- // TODO could do better
- if (calleeFunctionDecl->isVariadic()) {
- return false;
- }
- if (callExpr->getCallee() == stmt) {
- return true;
- }
- for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) {
- if (i >= calleeFunctionDecl->getNumParams()) // can happen in template code
- return false;
- if (callExpr->getArg(i) == stmt) {
- return isOkForParameter(calleeFunctionDecl->getParamDecl(i)->getType());
- }
- }
- }
- return false;
- } else if (auto callExpr = dyn_cast<ObjCMessageExpr>(parent)) {
- if (callExpr->getInstanceReceiver() == stmt) {
- return true;
- }
- if (auto const method = callExpr->getMethodDecl()) {
- // TODO could do better
- if (method->isVariadic()) {
- return false;
- }
- assert(method->param_size() == callExpr->getNumArgs());
- for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) {
- if (callExpr->getArg(i) == stmt) {
- return isOkForParameter(
- method->param_begin()[i]->getType());
- }
- }
- }
- } else if (isa<CXXReinterpretCastExpr>(parent)) {
- return false;
- } else if (isa<CXXConstCastExpr>(parent)) {
- return false;
- } else if (isa<CastExpr>(parent)) { // all other cast expression subtypes
- if (auto e = dyn_cast<ExplicitCastExpr>(parent)) {
- if (loplugin::TypeCheck(e->getTypeAsWritten()).Void()) {
- if (auto const sub = dyn_cast<DeclRefExpr>(
- e->getSubExpr()->IgnoreParenImpCasts()))
- {
- if (sub->getDecl() == parmVarDecl)
- return false;
- }
- }
- }
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (isa<MemberExpr>(parent)) {
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (auto arraySubscriptExpr = dyn_cast<ArraySubscriptExpr>(parent)) {
- if (arraySubscriptExpr->getIdx() == stmt)
- return true;
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (isa<ParenExpr>(parent)) {
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (isa<DeclStmt>(parent)) {
- // TODO could do better here, but would require tracking the target(s)
- //return false;
- } else if (isa<ReturnStmt>(parent)) {
- return !isPointerOrReferenceToNonConst(currentFunctionDecl->getReturnType());
- } else if (isa<InitListExpr>(parent)) {
- return false;
- } else if (isa<IfStmt>(parent)) {
- return true;
- } else if (isa<WhileStmt>(parent)) {
- return true;
- } else if (isa<ForStmt>(parent)) {
- return true;
- } else if (isa<CompoundStmt>(parent)) {
- return true;
- } else if (isa<SwitchStmt>(parent)) {
- return true;
- } else if (isa<DoStmt>(parent)) {
- return true;
- } else if (isa<CXXDeleteExpr>(parent)) {
- return false;
- } else if (isa<VAArgExpr>(parent)) {
- return false;
- } else if (isa<CXXDependentScopeMemberExpr>(parent)) {
- return false;
- } else if (isa<MaterializeTemporaryExpr>(parent)) {
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (auto conditionalExpr = dyn_cast<ConditionalOperator>(parent)) {
- if (conditionalExpr->getCond() == stmt)
- return true;
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (isa<UnaryExprOrTypeTraitExpr>(parent)) {
- return false; // ???
- } else if (auto cxxNewExpr = dyn_cast<CXXNewExpr>(parent)) {
- for (unsigned i = 0; i < cxxNewExpr->getNumPlacementArgs(); ++i)
- if (cxxNewExpr->getPlacementArg(i) == stmt)
- return false;
- return true; // ???
- } else if (auto lambdaExpr = dyn_cast<LambdaExpr>(parent)) {
- for (auto it = lambdaExpr->capture_begin(); it != lambdaExpr->capture_end(); ++it)
- {
- if (it->capturesVariable() && it->getCapturedVar() == parmVarDecl)
- return it->getCaptureKind() != LCK_ByRef;
- }
- return false;
- } else if (isa<CXXTypeidExpr>(parent)) {
- return true;
- } else if (isa<ParenListExpr>(parent)) {
- return false; // could be improved, seen in constructors when calling base class constructor
- } else if (isa<CXXUnresolvedConstructExpr>(parent)) {
- return false;
- } else if (isa<UnresolvedMemberExpr>(parent)) {
- return false;
- } else if (isa<PackExpansionExpr>(parent)) {
- return false;
- } else if (isa<ExprWithCleanups>(parent)) {
- return checkIfCanBeConst(parent, parmVarDecl);
- } else if (isa<CaseStmt>(parent)) {
- return true;
- } else if (isa<CXXPseudoDestructorExpr>(parent)) {
- return false;
- } else if (isa<CXXDependentScopeMemberExpr>(parent)) {
- return false;
- } else if (isa<ObjCIvarRefExpr>(parent)) {
- return checkIfCanBeConst(parent, parmVarDecl);
- }
- parent->dump();
- parmVarDecl->dump();
- report(
- DiagnosticsEngine::Warning,
- "oh dear, what can the matter be?",
- compat::getBeginLoc(parent))
- << parent->getSourceRange();
- return true;
-}
-
-bool ConstParams::isOkForParameter(const QualType& qt) {
- if (qt->isIntegralOrEnumerationType())
- return true;
- auto const type = loplugin::TypeCheck(qt);
- if (type.Pointer()) {
- return bool(type.Pointer().Const());
- } else if (type.LvalueReference().Const().Pointer()) {
- // If we have a method that takes (T* t) and it calls std::vector<T*>::push_back
- // then the type of push_back is T * const &
- // There is probably a more elegant way to check this, but it will probably require
- // recalculating types while walking up the AST.
- return false;
- } else if (type.LvalueReference()) {
- return bool(type.LvalueReference().Const());
- }
- return false;
-}
-
-bool ConstParams::isPointerOrReferenceToNonConst(const QualType& qt) {
- auto const type = loplugin::TypeCheck(qt);
- if (type.Pointer()) {
- return !bool(type.Pointer().Const());
- } else if (type.LvalueReference()) {
- return !bool(type.LvalueReference().Const());
- }
- return false;
-}
-
-loplugin::Plugin::Registration< ConstParams > X("constparams", false);
-
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */