path: root/src/corelib
diff options
authorMarc Mutz <>2016-04-01 23:55:25 +0200
committerMarc Mutz <>2016-04-26 16:36:40 +0000
commit31c7b24aa5f57fbe8258c9e9845c8d630af4aec1 (patch)
tree4ff8ecc6373f1d789f613df4d6042432a53427c0 /src/corelib
parent3a8f895d3529d59b7a1ea35705f86a2fcdeb35e4 (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 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 <> Change-Id: I1bbab257fb5f1c5042939c382a412b596112ff26 Reviewed-by: Stephen Kelly <>
Diffstat (limited to 'src/corelib')
5 files changed, 19 insertions, 6 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)
@@ -1117,6 +1123,12 @@
* 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)
- 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;
@@ -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>