Fix #101: sanitize names of namespaces/methods/signals/properties/arguments (#102)

- add a list of c++ keywords and common defines
- sanitize names so that there are no functions/args with names that are reserved in c++

Co-authored-by: Christian Schneider <cschneider@radiodata.biz>
This commit is contained in:
ChristianS99
2020-05-16 22:57:37 +02:00
committed by GitHub
parent 9af20af001
commit fb0a70a831
6 changed files with 135 additions and 13 deletions

View File

@ -164,6 +164,7 @@ std::tuple<std::string, std::string> AdaptorGenerator::processMethods(const Node
for (const auto& method : methods) for (const auto& method : methods)
{ {
auto methodName = method->get("name"); auto methodName = method->get("name");
auto methodNameSafe = mangle_name(methodName);
auto annotations = getAnnotations(*method); auto annotations = getAnnotations(*method);
bool async{false}; bool async{false};
@ -219,7 +220,7 @@ std::tuple<std::string, std::string> AdaptorGenerator::processMethods(const Node
<< "[this](" << "[this]("
<< (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "") << (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "")
<< argTypeStr << argTypeStr
<< "){ " << (async ? "" : "return ") << "this->" << methodName << "(" << "){ " << (async ? "" : "return ") << "this->" << methodNameSafe << "("
<< (async ? "std::move(result)"s + (argTypeStr.empty() ? "" : ", ") : "") << (async ? "std::move(result)"s + (argTypeStr.empty() ? "" : ", ") : "")
<< argStr << "); })" << argStr << "); })"
<< annotationRegistration << ";" << endl; << annotationRegistration << ";" << endl;
@ -227,7 +228,7 @@ std::tuple<std::string, std::string> AdaptorGenerator::processMethods(const Node
declarationSS << tab declarationSS << tab
<< "virtual " << "virtual "
<< (async ? "void" : outArgsToType(outArgs)) << (async ? "void" : outArgsToType(outArgs))
<< " " << methodName << " " << methodNameSafe
<< "(" << "("
<< (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "") << (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "")
<< argTypeStr << argTypeStr
@ -279,6 +280,7 @@ std::tuple<std::string, std::string> AdaptorGenerator::processSignals(const Node
auto nameWithCapFirstLetter = name; auto nameWithCapFirstLetter = name;
nameWithCapFirstLetter[0] = std::toupper(nameWithCapFirstLetter[0]); nameWithCapFirstLetter[0] = std::toupper(nameWithCapFirstLetter[0]);
nameWithCapFirstLetter = mangle_name(nameWithCapFirstLetter);
signalMethodSS << tab << "void emit" << nameWithCapFirstLetter << "(" << argTypeStr << ")" << endl signalMethodSS << tab << "void emit" << nameWithCapFirstLetter << "(" << argTypeStr << ")" << endl
<< tab << "{" << endl << tab << "{" << endl
@ -305,6 +307,7 @@ std::tuple<std::string, std::string> AdaptorGenerator::processProperties(const N
for (const auto& property : properties) for (const auto& property : properties)
{ {
auto propertyName = property->get("name"); auto propertyName = property->get("name");
auto propertyNameSafe = mangle_name(propertyName);
auto propertyAccess = property->get("access"); auto propertyAccess = property->get("access");
auto propertySignature = property->get("type"); auto propertySignature = property->get("type");
@ -336,23 +339,23 @@ std::tuple<std::string, std::string> AdaptorGenerator::processProperties(const N
if (propertyAccess == "read" || propertyAccess == "readwrite") if (propertyAccess == "read" || propertyAccess == "readwrite")
{ {
registrationSS << ".withGetter([this](){ return this->" << propertyName << "(); })"; registrationSS << ".withGetter([this](){ return this->" << propertyNameSafe << "(); })";
} }
if (propertyAccess == "readwrite" || propertyAccess == "write") if (propertyAccess == "readwrite" || propertyAccess == "write")
{ {
registrationSS registrationSS
<< ".withSetter([this](" << propertyTypeArg << ")" << ".withSetter([this](" << propertyTypeArg << ")"
"{ this->" << propertyName << "(" << propertyArg << "); })"; "{ this->" << propertyNameSafe << "(" << propertyArg << "); })";
} }
registrationSS << annotationRegistration; registrationSS << annotationRegistration;
registrationSS << ";" << endl; registrationSS << ";" << endl;
if (propertyAccess == "read" || propertyAccess == "readwrite") if (propertyAccess == "read" || propertyAccess == "readwrite")
declarationSS << tab << "virtual " << propertyType << " " << propertyName << "() = 0;" << endl; declarationSS << tab << "virtual " << propertyType << " " << propertyNameSafe << "() = 0;" << endl;
if (propertyAccess == "readwrite" || propertyAccess == "write") if (propertyAccess == "readwrite" || propertyAccess == "write")
declarationSS << tab << "virtual void " << propertyName << "(" << propertyTypeArg << ") = 0;" << endl; declarationSS << tab << "virtual void " << propertyNameSafe << "(" << propertyTypeArg << ") = 0;" << endl;
} }
return std::make_tuple(registrationSS.str(), declarationSS.str()); return std::make_tuple(registrationSS.str(), declarationSS.str());

View File

@ -96,6 +96,7 @@ std::tuple<unsigned, std::string> BaseGenerator::generateNamespaces(const std::s
{ {
std::string nspace; std::string nspace;
getline(ss, nspace, '.'); getline(ss, nspace, '.');
nspace = mangle_name(nspace);
body << "namespace " << nspace << " {" << endl; body << "namespace " << nspace << " {" << endl;
++count; ++count;
} }
@ -125,17 +126,18 @@ std::tuple<std::string, std::string, std::string, std::string> BaseGenerator::ar
{ {
argName = "arg" + std::to_string(i); argName = "arg" + std::to_string(i);
} }
auto argNameSafe = mangle_name(argName);
auto type = signature_to_type(arg->get("type")); auto type = signature_to_type(arg->get("type"));
argStringsSS << "\"" << argName << "\""; argStringsSS << "\"" << argName << "\"";
if (!async) if (!async)
{ {
argSS << argName; argSS << argNameSafe;
argTypeSS << "const " << type << "& " << argName; argTypeSS << "const " << type << "& " << argNameSafe;
} }
else else
{ {
argSS << "std::move(" << argName << ")"; argSS << "std::move(" << argNameSafe << ")";
argTypeSS << type << " " << argName; argTypeSS << type << " " << argNameSafe;
} }
typeSS << type; typeSS << type;
} }

View File

@ -135,6 +135,7 @@ std::tuple<std::string, std::string> ProxyGenerator::processMethods(const Nodes&
for (const auto& method : methods) for (const auto& method : methods)
{ {
auto name = method->get("name"); auto name = method->get("name");
auto nameSafe = mangle_name(name);
Nodes args = (*method)["arg"]; Nodes args = (*method)["arg"];
Nodes inArgs = args.select("direction" , "in"); Nodes inArgs = args.select("direction" , "in");
Nodes outArgs = args.select("direction" , "out"); Nodes outArgs = args.select("direction" , "out");
@ -174,7 +175,7 @@ std::tuple<std::string, std::string> ProxyGenerator::processMethods(const Nodes&
std::tie(outArgStr, outArgTypeStr, std::ignore, std::ignore) = argsToNamesAndTypes(outArgs); std::tie(outArgStr, outArgTypeStr, std::ignore, std::ignore) = argsToNamesAndTypes(outArgs);
const std::string realRetType = (async && !dontExpectReply ? "sdbus::PendingAsyncCall" : async ? "void" : retType); const std::string realRetType = (async && !dontExpectReply ? "sdbus::PendingAsyncCall" : async ? "void" : retType);
definitionSS << tab << realRetType << " " << name << "(" << inArgTypeStr << ")" << endl definitionSS << tab << realRetType << " " << nameSafe << "(" << inArgTypeStr << ")" << endl
<< tab << "{" << endl; << tab << "{" << endl;
if (!timeoutValue.empty()) if (!timeoutValue.empty())
@ -260,6 +261,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const
for (const auto& property : properties) for (const auto& property : properties)
{ {
auto propertyName = property->get("name"); auto propertyName = property->get("name");
auto propertyNameSafe = mangle_name(propertyName);
auto propertyAccess = property->get("access"); auto propertyAccess = property->get("access");
auto propertySignature = property->get("type"); auto propertySignature = property->get("type");
@ -269,7 +271,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const
if (propertyAccess == "read" || propertyAccess == "readwrite") if (propertyAccess == "read" || propertyAccess == "readwrite")
{ {
propertySS << tab << propertyType << " " << propertyName << "()" << endl propertySS << tab << propertyType << " " << propertyNameSafe << "()" << endl
<< tab << "{" << endl; << tab << "{" << endl;
propertySS << tab << tab << "return proxy_.getProperty(\"" << propertyName << "\")" propertySS << tab << tab << "return proxy_.getProperty(\"" << propertyName << "\")"
".onInterface(INTERFACE_NAME)"; ".onInterface(INTERFACE_NAME)";
@ -278,7 +280,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const
if (propertyAccess == "readwrite" || propertyAccess == "write") if (propertyAccess == "readwrite" || propertyAccess == "write")
{ {
propertySS << tab << "void " << propertyName << "(" << propertyTypeArg << ")" << endl propertySS << tab << "void " << propertyNameSafe << "(" << propertyTypeArg << ")" << endl
<< tab << "{" << endl; << tab << "{" << endl;
propertySS << tab << tab << "proxy_.setProperty(\"" << propertyName << "\")" propertySS << tab << tab << "proxy_.setProperty(\"" << propertyName << "\")"
".onInterface(INTERFACE_NAME)" ".onInterface(INTERFACE_NAME)"

View File

@ -7,6 +7,7 @@
#include <map> #include <map>
#include "generator_utils.h" #include "generator_utils.h"
#include "reserved_names.h"
std::string underscorize(const std::string& str) std::string underscorize(const std::string& str)
@ -142,3 +143,11 @@ std::string signature_to_type(const std::string& signature)
_parse_signature(signature, type, i); _parse_signature(signature, type, i);
return type; return type;
} }
std::string mangle_name(const std::string& name)
{
if (reserved_names.find(name) != reserved_names.end())
return name + "_";
else
return name;
}

View File

@ -19,4 +19,6 @@ std::string underscorize(const std::string& str);
constexpr const char* getHeaderComment() noexcept { return "\n/*\n * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!\n */\n\n"; } constexpr const char* getHeaderComment() noexcept { return "\n/*\n * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!\n */\n\n"; }
std::string mangle_name (const std::string& name);
#endif //__SDBUSCPP_TOOLS_GENERATOR_UTILS_H #endif //__SDBUSCPP_TOOLS_GENERATOR_UTILS_H

View File

@ -0,0 +1,104 @@
#include <set>
static const std::set<std::string> reserved_names = {
// c++ keywords taken from https://en.cppreference.com/w/cpp/keyword
"alignas",
"alignof",
"and",
"and_eq",
"asm",
"atomic_cancel",
"atomic_commit",
"atomic_noexcept",
"auto",
"bitand",
"bitor",
"bool",
"break",
"case",
"catch",
"char",
"char8_t",
"char16_t",
"char32_t",
"class",
"compl",
"concept",
"const",
"consteval",
"constexpr",
"constinit",
"const_cast",
"continue",
"co_await",
"co_return",
"co_yield",
"decltype",
"default",
"delete",
"do",
"double",
"dynamic_cast",
"else",
"enum",
"explicit",
"export",
"extern",
"false",
"float",
"for",
"friend",
"goto",
"if",
"inline",
"int",
"long",
"mutable",
"namespace",
"new",
"noexcept",
"not",
"not_eq",
"nullptr",
"operator",
"or",
"or_eq",
"private",
"protected",
"public",
"reflexpr",
"register",
"reinterpret_cast",
"requires",
"return",
"short",
"signed",
"sizeof",
"static",
"static_assert",
"static_cast",
"struct",
"switch",
"synchronized",
"template",
"this",
"thread_local",
"throw",
"true",
"try",
"typedef",
"typeid",
"typename",
"union",
"unsigned",
"using",
"virtual",
"void",
"volatile",
"wchar_t",
"while",
"xor",
"xor_eq",
// common defines
"NULL"
};