diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2016-04-01 23:55:25 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2016-04-26 16:36:40 +0000 |
commit | 31c7b24aa5f57fbe8258c9e9845c8d630af4aec1 (patch) | |
tree | 4ff8ecc6373f1d789f613df4d6042432a53427c0 /src | |
parent | 3a8f895d3529d59b7a1ea35705f86a2fcdeb35e4 (diff) |
Silence MSVC warnings when using certain std algorithms
The MSVC STL warns when passing naked pointers as non-bounded
iterators to algorithms such as std::equal and std::copy, in
an attempt to inform users that the range specified by that
iterator has an implicit minimum size that the caller of the
algorithm must ensure is met:
warning C4996: 'std::_Equal1': Function call with parameters that may be unsafe - \
this call relies on the caller to check that the passed values are correct. To \
disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to \
use Visual C++ 'Checked Iterators'
When building Qt, as well as when building user projects with
qmake (cf. 0a76b6bc7f98900ea884cd10ccca1a332e5bdba5), we
globally disable this warning (with -D_SCL_SECURE_NO_WARNINGS),
but since we started using STL algorithms in public headers (e.g.
in qvector.h), users get this warning in their own projects now,
unless they, too, define said macro. But such a requirement is
against the Qt policy to have headers that are warning-free as
much as possible.
The suggested way of fixing this warning is to wrap the naked
pointer in a stdext::unchecked_array_iterator before passing it
to the algorithm, cf. examples in
https://msdn.microsoft.com/en-us/library/ttcz0bys%28v=vs.120%29.aspx
or, together with the capacity-made-explicit, in a
stdext::checked_array_iterator.
To avoid ifdefs for platforms that don't have these extensions
(which, incidentally, for the unchecked case, includes MSVC 2012),
wrap the calls in macros.
The end game here is to drop -D_SCL_SECURE_NO_WARNINGS, at least
for public headers, even though this commit also adds the wrapper
to implementation and private header files.
An alternative to the wrapper would have been the version of
std::equal that takes four iterators. However, that is a C++14
library feature, while this version of Qt still needs to compile
with a C++98 compiler, and, more importantly, there isn't, and
never will be, a corresponding 4-iterator version of std::copy.
Task-number: QTBUG-47948
Done-with: Stephen Kelly <steveire@gmail.com>
Change-Id: I1bbab257fb5f1c5042939c382a412b596112ff26
Reviewed-by: Stephen Kelly <ske@ableton.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qcompilerdetection.h | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 2 | ||||
-rw-r--r-- | src/corelib/tools/qlist.h | 2 | ||||
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 7 | ||||
-rw-r--r-- | src/corelib/tools/qvector.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qkeysequence.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qkeysequence_p.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/windows/accessible/iaccessible2.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/windows/array.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsinputcontext.cpp | 2 |
10 files changed, 33 insertions, 14 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index b11237dce5..25043dab75 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -94,6 +94,12 @@ # define Q_DECL_DEPRECATED_X(text) __declspec(deprecated(text)) # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) +# if _MSC_VER >= 1800 +# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) stdext::make_unchecked_array_iterator(x) +# endif +# if _MSC_VER >= 1500 +# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) +# endif /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ # if defined(__INTEL_COMPILER) # define Q_DECL_VARIABLE_DEPRECATED @@ -1117,6 +1123,12 @@ #ifndef Q_DECL_CONST_FUNCTION # define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION #endif +#ifndef QT_MAKE_UNCHECKED_ARRAY_ITERATOR +# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) (x) +#endif +#ifndef QT_MAKE_CHECKED_ARRAY_ITERATOR +# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) (x) +#endif /* * Warning/diagnostic handling diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 30a3204d3d..b3b35dc9b6 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -444,7 +444,7 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint if (!isArgvModified(argc, argv)) { origArgc = argc; origArgv = new char *[argc]; - std::copy(argv, argv + argc, origArgv); + std::copy(argv, argv + argc, QT_MAKE_CHECKED_ARRAY_ITERATOR(origArgv, argc)); } #endif // Q_OS_WIN && !Q_OS_WINRT diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 9a57a2c6a5..e04a6be1ab 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -846,7 +846,7 @@ inline bool QList<T>::op_eq_impl(const QList &l, QListData::ArrayCompatibleLayou const T *lb = reinterpret_cast<const T*>(l.p.begin()); const T *b = reinterpret_cast<const T*>(p.begin()); const T *e = reinterpret_cast<const T*>(p.end()); - return std::equal(b, e, lb); + return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(lb, l.p.size())); } template <typename T> diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index bb15d66439..8371352061 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -96,7 +96,8 @@ public: QVarLengthArray<T, Prealloc> &operator=(std::initializer_list<T> list) { resize(list.size()); - std::copy(list.begin(), list.end(), this->begin()); + std::copy(list.begin(), list.end(), + QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size())); return *this; } #endif @@ -467,7 +468,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA int l = int(aend - ptr); int n = l - f; if (QTypeInfo<T>::isComplex) { - std::copy(ptr + l, ptr + s, ptr + f); + std::copy(ptr + l, ptr + s, QT_MAKE_CHECKED_ARRAY_ITERATOR(ptr + f, s - f)); T *i = ptr + s; T *b = ptr + s - n; while (i != b) { @@ -489,7 +490,7 @@ bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, const T *rb = r.begin(); const T *b = l.begin(); const T *e = l.end(); - return std::equal(b, e, rb); + return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(rb, r.size())); } template <typename T, int Prealloc1, int Prealloc2> diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 3ce33fb477..691872cb36 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -767,7 +767,7 @@ bool QVector<T>::operator==(const QVector<T> &v) const const T *vb = v.d->begin(); const T *b = d->begin(); const T *e = d->end(); - return std::equal(b, e, vb); + return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(vb, v.d->size)); } template <typename T> diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 6bb80042ee..a0818b8d20 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1637,7 +1637,7 @@ QDataStream &operator>>(QDataStream &s, QKeySequence &keysequence) s >> keys[i]; } qAtomicDetach(keysequence.d); - std::copy(keys, keys + MaxKeys, keysequence.d->key); + std::copy(keys, keys + MaxKeys, QT_MAKE_CHECKED_ARRAY_ITERATOR(keysequence.d->key, MaxKeys)); return s; } diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h index 6d20f798b3..9525a343dc 100644 --- a/src/gui/kernel/qkeysequence_p.h +++ b/src/gui/kernel/qkeysequence_p.h @@ -70,7 +70,8 @@ public: } inline QKeySequencePrivate(const QKeySequencePrivate ©) : ref(1) { - std::copy(copy.key, copy.key + MaxKeyCount, key); + std::copy(copy.key, copy.key + MaxKeyCount, + QT_MAKE_CHECKED_ARRAY_ITERATOR(key, MaxKeyCount)); } QAtomicInt ref; int key[MaxKeyCount]; diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 7abb98f385..5e0794bd95 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -602,7 +602,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex // The IDL documents that the client must free with CoTaskMemFree arrayOfBindingsToReturn = coTaskMemAllocArray<BSTR>(numBindings); std::transform(keyBindings.constBegin(), keyBindings.constEnd(), - arrayOfBindingsToReturn, QStringToBSTR); + QT_MAKE_CHECKED_ARRAY_ITERATOR(arrayOfBindingsToReturn, numBindings), + QStringToBSTR); } } *keyBindings = arrayOfBindingsToReturn; @@ -986,7 +987,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **sele *selectedColumns = Q_NULLPTR; if (count) { *selectedColumns = coTaskMemAllocArray<long>(count); - std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedColumns); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), + QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedColumns, count)); } return count ? S_OK : S_FALSE; } @@ -1008,7 +1010,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selecte *selectedRows = Q_NULLPTR; if (count) { *selectedRows = coTaskMemAllocArray<long>(count); - std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedRows); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), + QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedRows, count)); } return count ? S_OK : S_FALSE; } @@ -1677,7 +1680,8 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface* if (count) { *outputAccessibles = coTaskMemAllocArray<IUnknown *>(count); std::transform(inputCells.constBegin(), inputCells.constEnd(), - *outputAccessibles, QWindowsAccessibility::wrap); + QT_MAKE_CHECKED_ARRAY_ITERATOR(*outputAccessibles, count), + QWindowsAccessibility::wrap); } return count > 0 ? S_OK : S_FALSE; } diff --git a/src/plugins/platforms/windows/array.h b/src/plugins/platforms/windows/array.h index ea08432a29..df98d782da 100644 --- a/src/plugins/platforms/windows/array.h +++ b/src/plugins/platforms/windows/array.h @@ -79,7 +79,8 @@ public: const T *oldData = data; data = new T[capacity]; if (oldData) { - std::copy(oldData, oldData + m_size, data); + std::copy(oldData, oldData + m_size, + QT_MAKE_CHECKED_ARRAY_ITERATOR(data, capacity)); delete [] oldData; } m_capacity = capacity; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 1faa00d095..4d4be3d858 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -650,7 +650,7 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv) reconv->dwTargetStrOffset = reconv->dwCompStrOffset; ushort *pastReconv = reinterpret_cast<ushort *>(reconv + 1); std::copy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(), - pastReconv); + QT_MAKE_UNCHECKED_ARRAY_ITERATOR(pastReconv)); return memSize; } |