diff --git a/lib/constnessptr.h b/lib/constnessptr.h new file mode 100644 index 00000000000..89fea58719e --- /dev/null +++ b/lib/constnessptr.h @@ -0,0 +1,72 @@ +/* -*- C++ -*- + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2025 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//--------------------------------------------------------------------------- +#ifndef constnessPtrH +#define constnessPtrH +//--------------------------------------------------------------------------- + +#include "config.h" + +// as std::optional behaves similarly so we could use that instead of if we ever move to C++17. +// it is not a simple drop-in as our "operator bool()" indicates if the pointer is non-null +// whereas std::optional indicates if a value is set. +// +// This is similar to std::experimental::propagate_const +// see https://en.cppreference.com/w/cpp/experimental/propagate_const +template +class constness_ptr +{ +public: + explicit constness_ptr(T* p) + : mPtr(p) + {} + + T* get() NOEXCEPT { + return mPtr; + } + + const T* get() const NOEXCEPT { + return mPtr; + } + + T* operator->() NOEXCEPT { + return mPtr; + } + + const T* operator->() const NOEXCEPT { + return mPtr; + } + + T& operator*() NOEXCEPT { + return *mPtr; + } + + const T& operator*() const NOEXCEPT { + return *mPtr; + } + + explicit operator bool() const NOEXCEPT { + return mPtr != nullptr; + } + +private: + T* mPtr; +}; + +#endif // constnessPtrH diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 3d830e2894c..0d663db9a4a 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -133,6 +133,7 @@ + diff --git a/test/constness_ptr/constness_ptr_test.cpp b/test/constness_ptr/constness_ptr_test.cpp new file mode 100644 index 00000000000..267d2d00169 --- /dev/null +++ b/test/constness_ptr/constness_ptr_test.cpp @@ -0,0 +1,26 @@ +#include "constnessptr.h" +#include "utils.h" + +struct S +{ + void f(); + void f_c() const; +}; + +struct S1 +{ + explicit S1(S*s) : mS(s) {} + constness_ptr mS; +}; + +void f() +{ + S s; + S1 s1(&s); + s1.mS->f(); + s1.mS->f_c(); + utils::as_const(s1).mS->f_c(); +#ifdef BAD + utils::as_const(s1).mS->f(); +#endif +} diff --git a/test/constness_ptr/run.sh b/test/constness_ptr/run.sh new file mode 100644 index 00000000000..7870b47f372 --- /dev/null +++ b/test/constness_ptr/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/ +LIBDIR="$DIR"../../lib + +ec=0 +gcc -c constness_ptr_test.cpp -Wall -Wextra -I$LIBDIR || ec=1 +gcc -c constness_ptr_test.cpp -Wall -Wextra -I$LIBDIR -DBAD && ec=1 +exit $ec \ No newline at end of file diff --git a/tools/dmake/dmake.cpp b/tools/dmake/dmake.cpp index f85f65ae0d4..2c9a0d3a05f 100644 --- a/tools/dmake/dmake.cpp +++ b/tools/dmake/dmake.cpp @@ -468,6 +468,7 @@ int main(int argc, char **argv) libfiles_h.emplace("analyzer.h"); libfiles_h.emplace("calculate.h"); libfiles_h.emplace("config.h"); + libfiles_h.emplace("constnessptr.h"); libfiles_h.emplace("filesettings.h"); libfiles_h.emplace("findtoken.h"); libfiles_h.emplace("json.h");