Skip to content

Commit

Permalink
introduced enum for C/C++ standards and added functions to get them f…
Browse files Browse the repository at this point in the history
…rom strings (#366)
  • Loading branch information
firewave authored Sep 9, 2024
1 parent 76368ec commit 7b88c13
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 33 deletions.
115 changes: 82 additions & 33 deletions simplecpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3786,56 +3786,105 @@ void simplecpp::cleanup(std::map<std::string, TokenList*> &filedata)
filedata.clear();
}

std::string simplecpp::getCStdString(const std::string &std)
simplecpp::cstd_t simplecpp::getCStd(const std::string &std)
{
if (std == "c90" || std == "c89" || std == "iso9899:1990" || std == "iso9899:199409" || std == "gnu90" || std == "gnu89") {
// __STDC_VERSION__ is not set for C90 although the macro was added in the 1994 amendments
return "";
}
if (std == "c90" || std == "c89" || std == "iso9899:1990" || std == "iso9899:199409" || std == "gnu90" || std == "gnu89")
return C89;
if (std == "c99" || std == "c9x" || std == "iso9899:1999" || std == "iso9899:199x" || std == "gnu99"|| std == "gnu9x")
return "199901L";
return C99;
if (std == "c11" || std == "c1x" || std == "iso9899:2011" || std == "gnu11" || std == "gnu1x")
return "201112L";
return C11;
if (std == "c17" || std == "c18" || std == "iso9899:2017" || std == "iso9899:2018" || std == "gnu17"|| std == "gnu18")
return "201710L";
if (std == "c23" || std == "gnu23" || std == "c2x" || std == "gnu2x") {
// supported by GCC 9+ and Clang 9+
// Clang 9, 10, 11, 12, 13 return "201710L"
// Clang 14, 15, 16, 17 return "202000L"
// Clang 9, 10, 11, 12, 13, 14, 15, 16, 17 do not support "c23" and "gnu23"
return "202311L";
return C17;
if (std == "c23" || std == "gnu23" || std == "c2x" || std == "gnu2x")
return C23;
return CUnknown;
}

std::string simplecpp::getCStdString(cstd_t std)
{
switch (std)
{
case C89:
// __STDC_VERSION__ is not set for C90 although the macro was added in the 1994 amendments
return "";
case C99:
return "199901L";
case C11:
return "201112L";
case C17:
return "201710L";
case C23:
// supported by GCC 9+ and Clang 9+
// Clang 9, 10, 11, 12, 13 return "201710L"
// Clang 14, 15, 16, 17 return "202000L"
// Clang 9, 10, 11, 12, 13, 14, 15, 16, 17 do not support "c23" and "gnu23"
return "202311L";
case CUnknown:
return "";
}
return "";
}

std::string simplecpp::getCppStdString(const std::string &std)
std::string simplecpp::getCStdString(const std::string &std)
{
return getCStdString(getCStd(std));
}

simplecpp::cppstd_t simplecpp::getCppStd(const std::string &std)
{
if (std == "c++98" || std == "c++03" || std == "gnu++98" || std == "gnu++03")
return "199711L";
return CPP03;
if (std == "c++11" || std == "gnu++11" || std == "c++0x" || std == "gnu++0x")
return "201103L";
return CPP11;
if (std == "c++14" || std == "c++1y" || std == "gnu++14" || std == "gnu++1y")
return "201402L";
return CPP14;
if (std == "c++17" || std == "c++1z" || std == "gnu++17" || std == "gnu++1z")
return "201703L";
if (std == "c++20" || std == "c++2a" || std == "gnu++20" || std == "gnu++2a") {
// GCC 10 returns "201703L" - correct in 11+
return "202002L";
}
if (std == "c++23" || std == "c++2b" || std == "gnu++23" || std == "gnu++2b") {
// supported by GCC 11+ and Clang 12+
// GCC 11, 12, 13 return "202100L"
// Clang 12, 13, 14, 15, 16 do not support "c++23" and "gnu++23" and return "202101L"
// Clang 17, 18 return "202302L"
return "202302L";
}
if (std == "c++26" || std == "c++2c" || std == "gnu++26" || std == "gnu++2c") {
// supported by Clang 17+
return "202400L";
return CPP17;
if (std == "c++20" || std == "c++2a" || std == "gnu++20" || std == "gnu++2a")
return CPP20;
if (std == "c++23" || std == "c++2b" || std == "gnu++23" || std == "gnu++2b")
return CPP23;
if (std == "c++26" || std == "c++2c" || std == "gnu++26" || std == "gnu++2c")
return CPP26;
return CPPUnknown;
}

std::string simplecpp::getCppStdString(cppstd_t std)
{
switch (std)
{
case CPP03:
return "199711L";
case CPP11:
return "201103L";
case CPP14:
return "201402L";
case CPP17:
return "201703L";
case CPP20:
// GCC 10 returns "201703L" - correct in 11+
return "202002L";
case CPP23:
// supported by GCC 11+ and Clang 12+
// GCC 11, 12, 13 return "202100L"
// Clang 12, 13, 14, 15, 16 do not support "c++23" and "gnu++23" and return "202101L"
// Clang 17, 18 return "202302L"
return "202302L";
case CPP26:
// supported by Clang 17+
return "202400L";
case CPPUnknown:
return "";
}
return "";
}

std::string simplecpp::getCppStdString(const std::string &std)
{
return getCppStdString(getCppStd(std));
}

#if (__cplusplus < 201103L) && !defined(__APPLE__)
#undef nullptr
#endif
13 changes: 13 additions & 0 deletions simplecpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
#endif

namespace simplecpp {
/** C code standard */
enum cstd_t { CUnknown=-1, C89, C99, C11, C17, C23 };

/** C++ code standard */
enum cppstd_t { CPPUnknown=-1, CPP03, CPP11, CPP14, CPP17, CPP20, CPP23, CPP26 };

typedef std::string TokenString;
class Macro;
Expand Down Expand Up @@ -368,11 +373,19 @@ namespace simplecpp {
/** Convert Cygwin path to Windows path */
SIMPLECPP_LIB std::string convertCygwinToWindowsPath(const std::string &cygwinPath);

/** Returns the C version a given standard */
SIMPLECPP_LIB cstd_t getCStd(const std::string &std);

/** Returns the C++ version a given standard */
SIMPLECPP_LIB cppstd_t getCppStd(const std::string &std);

/** Returns the __STDC_VERSION__ value for a given standard */
SIMPLECPP_LIB std::string getCStdString(const std::string &std);
SIMPLECPP_LIB std::string getCStdString(cstd_t std);

/** Returns the __cplusplus value for a given standard */
SIMPLECPP_LIB std::string getCppStdString(const std::string &std);
SIMPLECPP_LIB std::string getCppStdString(cppstd_t std);
}

#if defined(_MSC_VER)
Expand Down
18 changes: 18 additions & 0 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2701,6 +2701,23 @@ static void invalidStd()
outputList.clear();
}

static void stdEnum()
{
ASSERT_EQUALS(simplecpp::cstd_t::C89, simplecpp::getCStd("c89"));
ASSERT_EQUALS(simplecpp::cstd_t::C89, simplecpp::getCStd("c90"));
ASSERT_EQUALS(simplecpp::cstd_t::C11, simplecpp::getCStd("iso9899:2011"));
ASSERT_EQUALS(simplecpp::cstd_t::C23, simplecpp::getCStd("gnu23"));
ASSERT_EQUALS(simplecpp::cstd_t::CUnknown, simplecpp::getCStd("gnu77"));
ASSERT_EQUALS(simplecpp::cstd_t::CUnknown, simplecpp::getCStd("c++11"));

ASSERT_EQUALS(simplecpp::cppstd_t::CPP03, simplecpp::getCppStd("c++03"));
ASSERT_EQUALS(simplecpp::cppstd_t::CPP03, simplecpp::getCppStd("c++98"));
ASSERT_EQUALS(simplecpp::cppstd_t::CPP17, simplecpp::getCppStd("c++1z"));
ASSERT_EQUALS(simplecpp::cppstd_t::CPP26, simplecpp::getCppStd("gnu++26"));
ASSERT_EQUALS(simplecpp::cppstd_t::CPPUnknown, simplecpp::getCppStd("gnu++77"));
ASSERT_EQUALS(simplecpp::cppstd_t::CPPUnknown, simplecpp::getCppStd("c11"));
}

static void assertToken(const std::string& s, bool name, bool number, bool comment, char op, int line)
{
const std::vector<std::string> f;
Expand Down Expand Up @@ -3030,6 +3047,7 @@ int main(int argc, char **argv)
TEST_CASE(stdcVersionDefine);
TEST_CASE(cpluscplusDefine);
TEST_CASE(invalidStd);
TEST_CASE(stdEnum);

TEST_CASE(token);

Expand Down

0 comments on commit 7b88c13

Please sign in to comment.