Skip to content

Commit 414001b

Browse files
committed
Lay the ground for Rf_error masking (#1402)
* Add a message at compilation time * Protect the valid Rf_error calls generated by Rcpp
1 parent dcd33d7 commit 414001b

File tree

6 files changed

+53
-6
lines changed

6 files changed

+53
-6
lines changed

ChangeLog

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
2025-11-12 Iñaki Ucar <[email protected]>
2+
3+
* inst/include/Rcpp/macros/mask.h: Lay the ground for Rf_error masking,
4+
unless RCPP_NO_MASK_RF_ERROR is defined; the new define just generates a
5+
compilation note, which will become a warning + masking in a future release
6+
* inst/include/RcppCommon.h: Include the previous file in the last place
7+
* src/attributes.cpp: Use parentheses to protect call to Rf_error
8+
* inst/tinytest/cpp/stack.cpp: Idem
9+
* inst/tinytest/testRcppInterfaceExporter/src/RcppExports.cpp: Idem
10+
111
2025-11-04 Dirk Eddelbuettel <[email protected]>
212

313
* .github/workflows/macos.yaml (jobs): Roll macos-13 to macos-14
@@ -10,7 +20,7 @@
1020

1121
2025-10-21 Iñaki Ucar <[email protected]>
1222

13-
* inst/include/Rcpp/exceptions_impl.h: use __has_include to simplify checks
23+
* inst/include/Rcpp/exceptions_impl.h: Use __has_include to simplify checks
1424
to enable demangling, making them robust for more platforms
1525

1626
2025-10-13 Dirk Eddelbuettel <[email protected]>

inst/include/Rcpp/macros/mask.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// mask.h: Rcpp R/C++ interface class library -- masking macros
2+
//
3+
// Copyright (C) 2025 Iñaki Ucar
4+
//
5+
// This file is part of Rcpp.
6+
//
7+
// Rcpp is free software: you can redistribute it and/or modify it
8+
// under the terms of the GNU General Public License as published by
9+
// the Free Software Foundation, either version 2 of the License, or
10+
// (at your option) any later version.
11+
//
12+
// Rcpp is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
// GNU General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License
18+
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
19+
20+
#ifndef Rcpp_macros_mask_h
21+
#define Rcpp_macros_mask_h
22+
23+
#ifndef RCPP_NO_MASK_RF_ERROR
24+
#define Rf_error(...) \
25+
_Pragma("message \"Use of Rf_error() instead of Rcpp::stop(). Calls \
26+
to Rf_error() in C++ contexts are unsafe: consider using Rcpp::stop() instead, \
27+
or define RCPP_NO_MASK_RF_ERROR if this is a false positive. More info:\n\
28+
- https://github.com/RcppCore/Rcpp/issues/1247\n\
29+
- https://github.com/RcppCore/Rcpp/pull/1402\"") \
30+
Rf_error(__VA_ARGS__)
31+
#endif
32+
33+
#endif

inst/include/RcppCommon.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// Copyright (C) 2008 - 2009 Dirk Eddelbuettel
66
// Copyright (C) 2009 - 2020 Dirk Eddelbuettel and Romain Francois
7-
// Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar
7+
// Copyright (C) 2021 - 2025 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar
88
//
99
// This file is part of Rcpp.
1010
//
@@ -191,4 +191,6 @@ namespace Rcpp {
191191

192192
#include <Rcpp/internal/wrap.h>
193193

194+
#include <Rcpp/macros/mask.h>
195+
194196
#endif

inst/tinytest/cpp/stack.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//
33
// misc.cpp: Rcpp R/C++ interface class library -- misc unit tests
44
//
5-
// Copyright (C) 2013 - 2022 Dirk Eddelbuettel and Romain Francois
5+
// Copyright (C) 2013 - 2024 Dirk Eddelbuettel and Romain Francois
6+
// Copyright (C) 2025 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar
67
//
78
// This file is part of Rcpp.
89
//
@@ -55,7 +56,7 @@ SEXP testSendInterrupt() {
5556
SEXP maybeThrow(void* data) {
5657
bool* fail = (bool*) data;
5758
if (*fail)
58-
Rf_error("throw!");
59+
(Rf_error)("throw!"); // prevent masking
5960
else
6061
return NumericVector::create(42);
6162
}

inst/tinytest/testRcppInterfaceExporter/src/RcppExports.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ RcppExport SEXP _testRcppInterfaceExporter_test_cpp_interface(SEXP xSEXP, SEXP f
4343
if (rcpp_isError_gen) {
4444
SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);
4545
UNPROTECT(1);
46-
Rf_error("%s", CHAR(rcpp_msgSEXP_gen));
46+
(Rf_error)("%s", CHAR(rcpp_msgSEXP_gen));
4747
}
4848
UNPROTECT(1);
4949
return rcpp_result_gen;

src/attributes.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2953,7 +2953,8 @@ namespace attributes {
29532953
<< " if (rcpp_isError_gen) {" << std::endl
29542954
<< " SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);" << std::endl
29552955
<< " UNPROTECT(1);" << std::endl
2956-
<< " Rf_error(\"%s\", CHAR(rcpp_msgSEXP_gen));" << std::endl
2956+
// Parentheses to prevent masking
2957+
<< " (Rf_error)(\"%s\", CHAR(rcpp_msgSEXP_gen));" << std::endl
29572958
<< " }" << std::endl
29582959
<< " UNPROTECT(1);" << std::endl
29592960
<< " return rcpp_result_gen;" << std::endl

0 commit comments

Comments
 (0)