Skip to content

Auto generation Warnings & Invalid C++ Identifiers (Closes #526 and #387) #528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2016-08-02 James J Balamuta <balamut2@illinois.edu>

* R/Rcpp.package.skeleton.R: Added autogeneration warning
* src/attributes.cpp: Fixed invalid C++ Identifiers and modified
export header to warn against hand edits
* vignettes/Rcpp-package.Rnw: Updated code generation snippets
* man/Rcpp.package.skeleton.Rd: Add warning on hand edits to the
autogenerated RcppExports files.
* man/compileAttributes.Rd: Idem

2016-08-01 Nathan Russell <russell.nr2012@gmail.com>

* inst/include/Rcpp/vector/Vector.h: Added decreasing option for Vector
Expand Down
2 changes: 2 additions & 0 deletions R/Rcpp.package.skeleton.R
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ Rcpp.package.skeleton <- function(name = "anRpackage", list = character(),
message(" >> added example src file using Rcpp attributes")
compileAttributes(root)
message(" >> compiled Rcpp attributes")
message(" >> do NOT modify by hand either RcppExports.cpp or ",
"RcppExports.R")
} else {
header <- readLines(file.path(skeleton, "rcpp_hello_world.h"))
header <- gsub("@PKG@", name, header, fixed = TRUE)
Expand Down
6 changes: 5 additions & 1 deletion inst/NEWS.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
\item The \code{NORET} macro is now defined if it was not already defined
by R (Kevin fixing issue \ghit{512}).
\item Environment functions get() & find() now accept a Symbol
(James Joseph Balamuta in \ghpr{513} addressing issue \ghit{326}).
(James Balamuta in \ghpr{513} addressing issue \ghit{326}).
\item Several uses of \code{Rf_eval} were replaced by the preferred
\code{Rcpp::Rcpp_eval} (Qiang in PR \ghpr{523} closing \ghit{498}).
\item Improved Autogeneration Warning for RcppExports
(James Balamuta in \ghpr{528} addressing issue \ghit{526}).
\item Fixed invalid C++ prefix identifiers in auto-generated code
(James Balamuta in \ghpr{528} addressing issue \ghit{387}).
}
\item Changes in Rcpp unit tests
\itemize{
Expand Down
7 changes: 5 additions & 2 deletions man/Rcpp.package.skeleton.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,11 @@ Rcpp.package.skeleton(name = "anRpackage", list = character(),
If the \code{attributes} argument is \code{TRUE}, then rather than generate
the example files as described above, a single \samp{rcpp_hello_world.cpp}
file is created in the \samp{src} directory and it's attributes are
compiled using the \code{\link{compileAttributes}} function, so files
\samp{RcppExports.R} and \samp{RcppExports.cpp} are generated as well.
compiled using the \code{\link{compileAttributes}} function. This leads to
the files \samp{RcppExports.R} and \samp{RcppExports.cpp} being generated.
They are automatically regenerated from \emph{scratch} each time
\code{\link{compileAttributes}} is called. Therefore, one should
\strong{not} modify by hand either of the \samp{RcppExports} files.

If the \code{module} argument is \code{TRUE}, a sample Rcpp module will
be generated as well.
Expand Down
2 changes: 1 addition & 1 deletion man/compileAttributes.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ compileAttributes(pkgdir = ".", verbose = getOption("verbose"))
\details{
The source files in the package directory given by \code{pkgdir} are scanned for attributes and code is generated as required based on the attributes.

For C++ functions adorned with the \code{Rcpp::export} attribute, the C++ and R source code required to bind to the function from R is generated and added (respectively) to \code{src/RcppExports.cpp} or \code{R/RcppExports.R}.
For C++ functions adorned with the \code{Rcpp::export} attribute, the C++ and R source code required to bind to the function from R is generated and added (respectively) to \code{src/RcppExports.cpp} or \code{R/RcppExports.R}. Both of these files are automatically generated from \emph{scratch} each time \code{compiledAttributes} is run.

In order to access the declarations for custom \code{Rcpp::as} and \code{Rcpp::wrap} handlers the \code{compileAttributes} function will also call any \link[inline:plugins]{inline plugins} available for packages listed in the \code{LinkingTo} field of the \code{DESCRIPTION} file.
}
Expand Down
51 changes: 26 additions & 25 deletions src/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1772,8 +1772,9 @@ namespace attributes {

// write header/preamble
std::ostringstream headerStream;
headerStream << commentPrefix_ << " This file was generated by "
<< "Rcpp::compileAttributes" << std::endl;
headerStream << commentPrefix_ << " Generated by using "
<< "Rcpp::compileAttributes()"
<< " -> do not edit by hand" << std::endl;
headerStream << commentPrefix_ << " Generator token: "
<< generatorToken() << std::endl << std::endl;
if (!preamble.empty())
Expand Down Expand Up @@ -2045,11 +2046,11 @@ namespace attributes {
<< getCCallable(packageCpp() + "_" + function.name()) << ";"
<< std::endl;
ostr() << " }" << std::endl;
ostr() << " RObject __result;" << std::endl;
ostr() << " RObject rcpp_result_gen;" << std::endl;
ostr() << " {" << std::endl;
if (it->rng())
ostr() << " RNGScope __rngScope;" << std::endl;
ostr() << " __result = " << ptrName << "(";
ostr() << " RNGScope RCPP_rngScope_gen;" << std::endl;
ostr() << " rcpp_result_gen = " << ptrName << "(";

const std::vector<Argument>& args = function.arguments();
for (std::size_t i = 0; i<args.size(); i++) {
Expand All @@ -2061,18 +2062,18 @@ namespace attributes {
ostr() << ");" << std::endl;
ostr() << " }" << std::endl;

ostr() << " if (__result.inherits(\"interrupted-error\"))"
ostr() << " if (rcpp_result_gen.inherits(\"interrupted-error\"))"
<< std::endl
<< " throw Rcpp::internal::InterruptedException();"
<< std::endl;
ostr() << " if (__result.inherits(\"try-error\"))"
ostr() << " if (rcpp_result_gen.inherits(\"try-error\"))"
<< std::endl
<< " throw Rcpp::exception(as<std::string>("
<< "__result).c_str());"
<< "rcpp_result_gen).c_str());"
<< std::endl;
if (!function.type().isVoid()) {
ostr() << " return Rcpp::as<" << function.type() << " >"
<< "(__result);" << std::endl;
<< "(rcpp_result_gen);" << std::endl;
}

ostr() << " }" << std::endl << std::endl;
Expand Down Expand Up @@ -2148,7 +2149,7 @@ namespace attributes {
}

std::string CppExportsIncludeGenerator::getHeaderGuard() const {
return "__" + packageCpp() + "_RcppExports_h__";
return "_RCPP_" + packageCpp() + "_RCPPEXPORTS_H_GEN_";
}

CppPackageIncludeGenerator::CppPackageIncludeGenerator(
Expand Down Expand Up @@ -2196,7 +2197,7 @@ namespace attributes {
}

std::string CppPackageIncludeGenerator::getHeaderGuard() const {
return "__" + packageCpp() + "_h__";
return "_RCPP_" + packageCpp() + "_H_GEN_";
}

RExportsGenerator::RExportsGenerator(const std::string& packageDir,
Expand Down Expand Up @@ -2582,9 +2583,9 @@ namespace attributes {
ostr << args << ") {" << std::endl;
ostr << "BEGIN_RCPP" << std::endl;
if (!function.type().isVoid())
ostr << " Rcpp::RObject __result;" << std::endl;
ostr << " Rcpp::RObject rcpp_result_gen;" << std::endl;
if (!cppInterface && attribute.rng())
ostr << " Rcpp::RNGScope __rngScope;" << std::endl;
ostr << " Rcpp::RNGScope rcpp_rngScope_gen;" << std::endl;
for (size_t i = 0; i<arguments.size(); i++) {
const Argument& argument = arguments[i];

Expand All @@ -2595,7 +2596,7 @@ namespace attributes {

ostr << " ";
if (!function.type().isVoid())
ostr << "__result = Rcpp::wrap(";
ostr << "rcpp_result_gen = Rcpp::wrap(";
ostr << function.name() << "(";
for (size_t i = 0; i<arguments.size(); i++) {
const Argument& argument = arguments[i];
Expand All @@ -2609,7 +2610,7 @@ namespace attributes {

if (!function.type().isVoid())
{
ostr << " return __result;" << std::endl;
ostr << " return rcpp_result_gen;" << std::endl;
}
else
{
Expand All @@ -2623,11 +2624,11 @@ namespace attributes {
if (cppInterface) {
ostr << "RcppExport SEXP " << funcName << "(" << args << ") {"
<< std::endl;
ostr << " SEXP __result;" << std::endl;
ostr << " SEXP rcpp_result_gen;" << std::endl;
ostr << " {" << std::endl;
if (attribute.rng())
ostr << " Rcpp::RNGScope __rngScope;" << std::endl;
ostr << " __result = PROTECT(" << funcName
ostr << " Rcpp::RNGScope rcpp_rngScope_gen;" << std::endl;
ostr << " rcpp_result_gen = PROTECT(" << funcName
<< kTrySuffix << "(";
for (size_t i = 0; i<arguments.size(); i++) {
const Argument& argument = arguments[i];
Expand All @@ -2637,21 +2638,21 @@ namespace attributes {
}
ostr << "));" << std::endl;
ostr << " }" << std::endl;
ostr << " Rboolean __isInterrupt = Rf_inherits(__result, \"interrupted-error\");"
ostr << " Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, \"interrupted-error\");"
<< std::endl
<< " if (__isInterrupt) {" << std::endl
<< " if (rcpp_isError_gen) {" << std::endl
<< " UNPROTECT(1);" << std::endl
<< " Rf_onintr();" << std::endl
<< " }" << std::endl
<< " Rboolean __isError = Rf_inherits(__result, \"try-error\");"
<< " Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, \"try-error\");"
<< std::endl
<< " if (__isError) {" << std::endl
<< " SEXP __msgSEXP = Rf_asChar(__result);" << std::endl
<< " if (rcpp_isError_gen) {" << std::endl
<< " SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);" << std::endl
<< " UNPROTECT(1);" << std::endl
<< " Rf_error(CHAR(__msgSEXP));" << std::endl
<< " Rf_error(CHAR(rcpp_msgSEXP_gen));" << std::endl
<< " }" << std::endl
<< " UNPROTECT(1);" << std::endl
<< " return __result;" << std::endl
<< " return rcpp_result_gen;" << std::endl
<< "}" << std::endl;
}
}
Expand Down
12 changes: 6 additions & 6 deletions vignettes/Rcpp-package.Rnw
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ e.g. handle the \texttt{List} class.
on the package, which generates the \texttt{RcppExports.cpp} file:

<<lang=cpp>>=
// This file was generated by Rcpp::compileAttributes
// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

#include <Rcpp.h>
Expand All @@ -184,10 +184,10 @@ using namespace Rcpp;
List rcpp_hello_world();
RcppExport SEXP mypackage_rcpp_hello_world() {
BEGIN_RCPP
Rcpp::RObject __result;
Rcpp::RNGScope __rngScope;
__result = Rcpp::wrap(rcpp_hello_world());
return __result;
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
rcpp_result_gen = Rcpp::wrap(rcpp_hello_world());
return rcpp_result_gen;
END_RCPP
}
@
Expand All @@ -205,7 +205,7 @@ The \rdoc{Rcpp}{compileAttributes} also generates \proglang{R} code
that uses the \proglang{C++} function.

<<lang=cpp>>=
# This file was generated by Rcpp::compileAttributes
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

rcpp_hello_world <- function() {
Expand Down