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. 0a76b6bc7f), 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>
bb10
parent
3a8f895d35
commit
31c7b24aa5
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue