From 936c19b7a079c3ad229cbfe35eefb81253bb2d24 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 15:41:28 -0700 Subject: [PATCH 01/15] add template specializations to avoid DATAPTR use --- ChangeLog | 5 +++++ inst/NEWS.Rd | 4 +++- inst/include/Rcpp/internal/r_vector.h | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e46bdd3c9..0c5d40941 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2024-06-11 Kevin Ushey + + * inst/include/Rcpp/internal/r_vector.h: Use template specializations to + avoid DATAPTR usage + 2024-06-02 Dirk Eddelbuettel * inst/include/Rcpp/internal/export.h: More R_xlen_t switching diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 88e36c3c7..bafb9da6d 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -9,9 +9,11 @@ \itemize{ \item Set R_NO_REMAP if not already defined (Dirk in \ghpr{1296}) \item Add variadic templates to be used instead of generated code - (Andrew Johnson in \ghpr{1303} + (Andrew Johnson in \ghpr{1303}) \item Count variables were switches to \code{size_t} to avoid warnings about conversion-narrowing (Dirk in \ghpr{1307}) + \item Rcpp now avoids the usage of the (non-API) DATAPTR function when + accessing the contents of Rcpp Vector objects where possible. } \item Changes in Rcpp Deployment: \itemize{ diff --git a/inst/include/Rcpp/internal/r_vector.h b/inst/include/Rcpp/internal/r_vector.h index efdf3c8e3..589c75fed 100644 --- a/inst/include/Rcpp/internal/r_vector.h +++ b/inst/include/Rcpp/internal/r_vector.h @@ -32,6 +32,21 @@ typename Rcpp::traits::storage_type::type* r_vector_start(SEXP x) { return reinterpret_cast(dataptr(x)); } +// add specializations to avoid use of dataptr +#define RCPP_VECTOR_START_IMPL(__RTYPE__, __ACCESSOR__) \ + template <> \ + inline typename Rcpp::traits::storage_type<__RTYPE__>::type* r_vector_start<__RTYPE__>(SEXP x) { \ + return __ACCESSOR__(x); \ + } + +RCPP_VECTOR_START_IMPL(LGLSXP, LOGICAL); +RCPP_VECTOR_START_IMPL(INTSXP, INTEGER); +RCPP_VECTOR_START_IMPL(RAWSXP, RAW); +RCPP_VECTOR_START_IMPL(CPLXSXP, COMPLEX); +RCPP_VECTOR_START_IMPL(REALSXP, REAL); + +#undef RCPP_VECTOR_START_IMPL + /** * The value 0 statically casted to the appropriate type for * the given SEXP type From d48a6ed7765c2703bba833bb6a5566302128bc30 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 15:56:36 -0700 Subject: [PATCH 02/15] also implement bounds checking in vector access --- ChangeLog | 2 ++ inst/include/Rcpp/vector/traits.h | 53 ++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0c5d40941..18557b78f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ * inst/include/Rcpp/internal/r_vector.h: Use template specializations to avoid DATAPTR usage + * inst/include/Rcpp/vector/traits.h: Implement bounds checks in + r_vector_cache access 2024-06-02 Dirk Eddelbuettel diff --git a/inst/include/Rcpp/vector/traits.h b/inst/include/Rcpp/vector/traits.h index 1e01d93dc..c41484aac 100644 --- a/inst/include/Rcpp/vector/traits.h +++ b/inst/include/Rcpp/vector/traits.h @@ -35,22 +35,59 @@ namespace traits{ typedef typename r_vector_const_proxy::type const_proxy ; typedef typename storage_type::type storage_type ; - r_vector_cache() : start(0){} ; + r_vector_cache() : start(0), size(0) {} ; + inline void update( const VECTOR& v ) { - start = ::Rcpp::internal::r_vector_start(v) ; + start = ::Rcpp::internal::r_vector_start(v) ; + size = v.size(); } + inline iterator get() const { return start; } inline const_iterator get_const() const { return start; } - inline proxy ref() { return *start ;} - inline proxy ref(R_xlen_t i) { return start[i] ; } + inline proxy ref() { +#ifndef RCPP_NO_BOUNDS_CHECK + check_index(0) ; +#endif + return start[0]; + } + + inline proxy ref() const { +#ifndef RCPP_NO_BOUNDS_CHECK + check_index(0) ; +#endif + return start[0] ; + } + + inline proxy ref(R_xlen_t i) { +#ifndef RCPP_NO_BOUNDS_CHECK + check_index(i) ; +#endif + return start[i] ; + } - inline proxy ref() const { return *start ;} - inline proxy ref(R_xlen_t i) const { return start[i] ; } - private: - iterator start ; + inline proxy ref(R_xlen_t i) const { +#ifndef RCPP_NO_BOUNDS_CHECK + check_index(i) ; +#endif + return start[i] ; + } + + private: + +#ifndef RCPP_NO_BOUNDS_CHECK + void check_index(R_xlen_t i) const { + if (i >= size) { + stop("index error"); + } + } +#endif + + iterator start ; + R_xlen_t size ; } ; + template class StoragePolicy = PreserveStorage> class proxy_cache{ public: From 84c885aa258a7bd828940eda72531855db6ade76 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:02:00 -0700 Subject: [PATCH 03/15] tweak error message --- inst/include/Rcpp/vector/traits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/include/Rcpp/vector/traits.h b/inst/include/Rcpp/vector/traits.h index c41484aac..e4dcd773a 100644 --- a/inst/include/Rcpp/vector/traits.h +++ b/inst/include/Rcpp/vector/traits.h @@ -79,7 +79,7 @@ namespace traits{ #ifndef RCPP_NO_BOUNDS_CHECK void check_index(R_xlen_t i) const { if (i >= size) { - stop("index error"); + stop("subscript out of bounds (index %s >= vector size %s)", i, size); } } #endif From 3addbc957928afba418f472af60b0f7eb1c56a2a Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:10:07 -0700 Subject: [PATCH 04/15] add tests; implement bounds check for proxy --- inst/include/Rcpp/vector/traits.h | 56 +++++++++++-------------------- inst/tinytest/cpp/Vector.cpp | 12 +++++++ inst/tinytest/test_vector.R | 4 +++ 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/inst/include/Rcpp/vector/traits.h b/inst/include/Rcpp/vector/traits.h index e4dcd773a..de8cb9fbb 100644 --- a/inst/include/Rcpp/vector/traits.h +++ b/inst/include/Rcpp/vector/traits.h @@ -45,44 +45,21 @@ namespace traits{ inline iterator get() const { return start; } inline const_iterator get_const() const { return start; } - inline proxy ref() { -#ifndef RCPP_NO_BOUNDS_CHECK - check_index(0) ; -#endif - return start[0]; - } - - inline proxy ref() const { -#ifndef RCPP_NO_BOUNDS_CHECK - check_index(0) ; -#endif - return start[0] ; - } - - inline proxy ref(R_xlen_t i) { -#ifndef RCPP_NO_BOUNDS_CHECK - check_index(i) ; -#endif - return start[i] ; - } + inline proxy ref() { check_index(0); return start[0] ;} + inline proxy ref(R_xlen_t i) { check_index(i); return start[i] ; } - - inline proxy ref(R_xlen_t i) const { -#ifndef RCPP_NO_BOUNDS_CHECK - check_index(i) ; -#endif - return start[i] ; - } + inline proxy ref() const { check_index(0); return start[0] ;} + inline proxy ref(R_xlen_t i) const { check_index(i); return start[i] ; } private: -#ifndef RCPP_NO_BOUNDS_CHECK void check_index(R_xlen_t i) const { +#ifndef RCPP_NO_BOUNDS_CHECK if (i >= size) { stop("subscript out of bounds (index %s >= vector size %s)", i, size); } - } #endif + } iterator start ; R_xlen_t size ; @@ -102,18 +79,25 @@ namespace traits{ void update( const VECTOR& v ){ p = const_cast(&v) ; } - inline iterator get() const { return iterator( proxy(*p, 0 ) ) ;} - // inline const_iterator get_const() const { return const_iterator( *p ) ;} - inline const_iterator get_const() const { return const_iterator( const_proxy(*p, 0) ) ; } + inline iterator get() const { check_index(0); return iterator( proxy(*p, 0 ) ) ;} + inline const_iterator get_const() const { check_index(0); return const_iterator( const_proxy(*p, 0) ) ; } - inline proxy ref() { return proxy(*p,0) ; } - inline proxy ref(R_xlen_t i) { return proxy(*p,i);} + inline proxy ref() { check_index(0); return proxy(*p,0) ; } + inline proxy ref(R_xlen_t i) { check_index(i); return proxy(*p,i);} - inline const_proxy ref() const { return const_proxy(*p,0) ; } - inline const_proxy ref(R_xlen_t i) const { return const_proxy(*p,i);} + inline const_proxy ref() const { check_index(0); return const_proxy(*p,0) ; } + inline const_proxy ref(R_xlen_t i) const { check_index(i); return const_proxy(*p,i);} private: VECTOR* p ; + + void check_index(R_xlen_t i) const { +#ifndef RCPP_NO_BOUNDS_CHECK + if (i >= size) { + stop("subscript out of bounds (index %s >= vector size %s)", i, size); + } +#endif + } } ; // regular types for INTSXP, REALSXP, ... diff --git a/inst/tinytest/cpp/Vector.cpp b/inst/tinytest/cpp/Vector.cpp index 495796958..9ac4526ae 100644 --- a/inst/tinytest/cpp/Vector.cpp +++ b/inst/tinytest/cpp/Vector.cpp @@ -886,3 +886,15 @@ bool CharacterVector_test_equality_crosspolicy(CharacterVector x, Vector Date: Tue, 11 Jun 2024 16:14:41 -0700 Subject: [PATCH 05/15] finish NEWS --- inst/NEWS.Rd | 5 ++++- inst/include/Rcpp/vector/traits.h | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index bafb9da6d..11fe09b52 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -13,7 +13,10 @@ \item Count variables were switches to \code{size_t} to avoid warnings about conversion-narrowing (Dirk in \ghpr{1307}) \item Rcpp now avoids the usage of the (non-API) DATAPTR function when - accessing the contents of Rcpp Vector objects where possible. + accessing the contents of Rcpp Vector objects where possible. (Kevin in + \ghpr{1310}) + \item Rcpp now throws an R error on out-of-bounds Vector accesses. (Kevin + in \ghpr{1310}) } \item Changes in Rcpp Deployment: \itemize{ diff --git a/inst/include/Rcpp/vector/traits.h b/inst/include/Rcpp/vector/traits.h index de8cb9fbb..ff27ef86a 100644 --- a/inst/include/Rcpp/vector/traits.h +++ b/inst/include/Rcpp/vector/traits.h @@ -93,8 +93,8 @@ namespace traits{ void check_index(R_xlen_t i) const { #ifndef RCPP_NO_BOUNDS_CHECK - if (i >= size) { - stop("subscript out of bounds (index %s >= vector size %s)", i, size); + if (i >= p->size()) { + stop("subscript out of bounds (index %s >= vector size %s)", i, p->size()); } #endif } From c8c3a5c65d870e4e7bdf5153bb87e595e0748844 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:24:41 -0700 Subject: [PATCH 06/15] don't check index when constructing iterators --- inst/include/Rcpp/vector/traits.h | 4 ++-- tests/tinytest.R | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/inst/include/Rcpp/vector/traits.h b/inst/include/Rcpp/vector/traits.h index ff27ef86a..b63732abe 100644 --- a/inst/include/Rcpp/vector/traits.h +++ b/inst/include/Rcpp/vector/traits.h @@ -79,8 +79,8 @@ namespace traits{ void update( const VECTOR& v ){ p = const_cast(&v) ; } - inline iterator get() const { check_index(0); return iterator( proxy(*p, 0 ) ) ;} - inline const_iterator get_const() const { check_index(0); return const_iterator( const_proxy(*p, 0) ) ; } + inline iterator get() const { return iterator( proxy(*p, 0 ) ) ;} + inline const_iterator get_const() const { return const_iterator( const_proxy(*p, 0) ) ; } inline proxy ref() { check_index(0); return proxy(*p,0) ; } inline proxy ref(R_xlen_t i) { check_index(i); return proxy(*p,i);} diff --git a/tests/tinytest.R b/tests/tinytest.R index f2480ee11..1540f9c8b 100644 --- a/tests/tinytest.R +++ b/tests/tinytest.R @@ -43,5 +43,5 @@ if (requireNamespace("tinytest", quietly=TRUE)) { ## there are several more granular ways to test files in a tinytest directory, ## see its package vignette; tests can also run once the package is installed ## using the same command `test_package(pkgName)`, or by director or file - tinytest::test_package("Rcpp", ncpu=getOption("Ncpus", 1)) + tinytest::test_package("Rcpp", ncpu=getOption("Ncpus")) } From 1d7ce1b6f52543b3b942a1c567ac81a2f8492460 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:32:34 -0700 Subject: [PATCH 07/15] avoid invoking wrong 'get' --- inst/tinytest/test_rcpp_package_skeleton.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/tinytest/test_rcpp_package_skeleton.R b/inst/tinytest/test_rcpp_package_skeleton.R index 23ec2fbd9..b1107c315 100644 --- a/inst/tinytest/test_rcpp_package_skeleton.R +++ b/inst/tinytest/test_rcpp_package_skeleton.R @@ -69,7 +69,7 @@ for (file in grep("RcppExports.R", R_files, invert=TRUE, value=TRUE)) { code <- readLines(file) fn <- eval(parse(text=paste(code, collapse="\n"))) fn_name <- gsub(".*/(.*)\\.R$", "\\1", file) - checkIdentical(fn, get(fn_name), + checkIdentical(fn, base::get(fn_name), sprintf("we parsed the function '%s' correctly", fn_name) ) } From 4c8df0c2e1fcb6592eb2083490024fe8a57c2698 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:40:40 -0700 Subject: [PATCH 08/15] don't pass 'ncpus' --- tests/tinytest.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tinytest.R b/tests/tinytest.R index 1540f9c8b..29e82d1be 100644 --- a/tests/tinytest.R +++ b/tests/tinytest.R @@ -43,5 +43,5 @@ if (requireNamespace("tinytest", quietly=TRUE)) { ## there are several more granular ways to test files in a tinytest directory, ## see its package vignette; tests can also run once the package is installed ## using the same command `test_package(pkgName)`, or by director or file - tinytest::test_package("Rcpp", ncpu=getOption("Ncpus")) + tinytest::test_package("Rcpp") } From 2520e51fd115b4ad381ccdd0e3d2fc4fbe472557 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:43:59 -0700 Subject: [PATCH 09/15] finish NEWS --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 18557b78f..321ec0aa9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,9 @@ avoid DATAPTR usage * inst/include/Rcpp/vector/traits.h: Implement bounds checks in r_vector_cache access + * inst/tinytest/cpp/Vector.cpp: Add unit tests + * inst/tinytest/test_vector.R: Add unit tests + * tests/tinytest.R: Test in serial by default 2024-06-02 Dirk Eddelbuettel From 528f453910da900d9a9c37a2b5cb41b0d405cd13 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 11 Jun 2024 16:55:19 -0700 Subject: [PATCH 10/15] test tweaks --- inst/tinytest/cpp/Vector.cpp | 10 ++++------ inst/tinytest/test_vector.R | 7 +++++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/inst/tinytest/cpp/Vector.cpp b/inst/tinytest/cpp/Vector.cpp index 9ac4526ae..4fc26b7e8 100644 --- a/inst/tinytest/cpp/Vector.cpp +++ b/inst/tinytest/cpp/Vector.cpp @@ -888,13 +888,11 @@ bool CharacterVector_test_equality_crosspolicy(CharacterVector x, Vector Date: Wed, 12 Jun 2024 08:09:11 -0500 Subject: [PATCH 11/15] Small robustification for package version check during dev cycle --- inst/tinytest/test_packageversion.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/tinytest/test_packageversion.R b/inst/tinytest/test_packageversion.R index 6df612c79..871510d5e 100644 --- a/inst/tinytest/test_packageversion.R +++ b/inst/tinytest/test_packageversion.R @@ -1,5 +1,5 @@ -## Copyright (C) 2019 - 2022 Dirk Eddelbuettel +## Copyright (C) 2019 - 2024 Dirk Eddelbuettel ## ## This file is part of Rcpp. ## @@ -30,7 +30,7 @@ v <- as.integer(unlist(strsplit(pvstr, "\\."))) relstr <- as.character(as.package_version(paste(v[1:3], collapse="."))) ## call C++ function returning list of six values, three each for 'release' and 'dev' version -res <- checkVersion(v) +res <- checkVersion(v[1:min(4, length(v))]) ## basic check: is the #defined version equal to the computed version (issue #1014) From bc529e061bdaf8f2dc81786486bcf8c804569aba Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 18 Jun 2024 09:37:46 -0700 Subject: [PATCH 12/15] use warning instead of stop --- inst/include/Rcpp/vector/traits.h | 4 ++-- inst/tinytest/test_vector.R | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/inst/include/Rcpp/vector/traits.h b/inst/include/Rcpp/vector/traits.h index b63732abe..c6d76d694 100644 --- a/inst/include/Rcpp/vector/traits.h +++ b/inst/include/Rcpp/vector/traits.h @@ -56,7 +56,7 @@ namespace traits{ void check_index(R_xlen_t i) const { #ifndef RCPP_NO_BOUNDS_CHECK if (i >= size) { - stop("subscript out of bounds (index %s >= vector size %s)", i, size); + warning("subscript out of bounds (index %s >= vector size %s)", i, size); } #endif } @@ -94,7 +94,7 @@ namespace traits{ void check_index(R_xlen_t i) const { #ifndef RCPP_NO_BOUNDS_CHECK if (i >= p->size()) { - stop("subscript out of bounds (index %s >= vector size %s)", i, p->size()); + warning("subscript out of bounds (index %s >= vector size %s)", i, p->size()); } #endif } diff --git a/inst/tinytest/test_vector.R b/inst/tinytest/test_vector.R index ba287395c..e8138e24e 100644 --- a/inst/tinytest/test_vector.R +++ b/inst/tinytest/test_vector.R @@ -696,8 +696,9 @@ expect_true( !CharacterVector_test_equality("foo", "bar") ) expect_true( !CharacterVector_test_equality_crosspolicy("foo", "bar") ) # https://github.com/RcppCore/Rcpp/issues/1308 -expect_error(NumericVector_test_out_of_bounds_read(numeric(0), 0)) -expect_error(NumericVector_test_out_of_bounds_read(numeric(1), 1)) -expect_error(CharacterVector_test_out_of_bounds_read(character(0), 0)) -expect_error(CharacterVector_test_out_of_bounds_read(character(1), 1)) +# tests disabled since these could trigger UBSAN warnings / crashes +#expect_warning(NumericVector_test_out_of_bounds_read(numeric(0), 0)) +#expect_warning(NumericVector_test_out_of_bounds_read(numeric(1), 1)) +#expect_warning(CharacterVector_test_out_of_bounds_read(character(0), 0)) +#expect_warning(CharacterVector_test_out_of_bounds_read(character(1), 1)) From d412e224fe1c9392ce4e7552657f4b96b29abdd1 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 18 Jun 2024 09:38:48 -0700 Subject: [PATCH 13/15] update NEWS --- inst/NEWS.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 11fe09b52..d0b8adb2d 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -15,7 +15,7 @@ \item Rcpp now avoids the usage of the (non-API) DATAPTR function when accessing the contents of Rcpp Vector objects where possible. (Kevin in \ghpr{1310}) - \item Rcpp now throws an R error on out-of-bounds Vector accesses. (Kevin + \item Rcpp now emits an R warning on out-of-bounds Vector accesses. (Kevin in \ghpr{1310}) } \item Changes in Rcpp Deployment: From 3f4d5df173efdb6b04c5dea3e11da580a28cab49 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 18 Jun 2024 09:39:13 -0700 Subject: [PATCH 14/15] NEWS once more --- inst/NEWS.Rd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index d0b8adb2d..1fbef846d 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -15,8 +15,8 @@ \item Rcpp now avoids the usage of the (non-API) DATAPTR function when accessing the contents of Rcpp Vector objects where possible. (Kevin in \ghpr{1310}) - \item Rcpp now emits an R warning on out-of-bounds Vector accesses. (Kevin - in \ghpr{1310}) + \item Rcpp now emits an R warning on out-of-bounds Vector accesses. This + may become an error in a future Rcpp release. (Kevin in \ghpr{1310}) } \item Changes in Rcpp Deployment: \itemize{ From c1ca0bbba55681e8db07433f48669002f688dc31 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 18 Jun 2024 11:05:48 -0700 Subject: [PATCH 15/15] fixup for check_indices in subsetter --- inst/include/Rcpp/vector/Subsetter.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/inst/include/Rcpp/vector/Subsetter.h b/inst/include/Rcpp/vector/Subsetter.h index 0d8b32a6a..339d2000d 100644 --- a/inst/include/Rcpp/vector/Subsetter.h +++ b/inst/include/Rcpp/vector/Subsetter.h @@ -133,9 +133,9 @@ class SubsetProxy { private: - #ifndef RCPP_NO_BOUNDS_CHECK template void check_indices(IDX* x, R_xlen_t n, R_xlen_t size) { +#ifndef RCPP_NO_BOUNDS_CHECK for (IDX i=0; i < n; ++i) { if (x[i] < 0 or x[i] >= size) { if(std::numeric_limits::is_integer && size > std::numeric_limits::max()) { @@ -144,11 +144,8 @@ class SubsetProxy { stop("index error"); } } +#endif } - #else - template - void check_indices(IDX* x, IDX n, IDX size) {} - #endif void get_indices( traits::identity< traits::int2type > t ) { indices.reserve(rhs_n);