Skip to content

Commit 036b59d

Browse files
committed
Add range, support type, and standard in error messages
1 parent d4f1c1f commit 036b59d

3 files changed

Lines changed: 139 additions & 24 deletions

File tree

simplecpp.cpp

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -666,15 +666,15 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
666666

667667
const Token *oldLastToken = nullptr;
668668

669+
const cstd_t cstd = getCStd(dui.std);
670+
const bool std_is_c = cstd != CUnknown;
671+
const cppstd_t cppstd = getCppStd(dui.std, std_is_c ? CPPUnknown : CPP26); // use C++26 by default
672+
669673
unsigned long maxline;
670-
{
671-
const cstd_t cstd = getCStd(dui.std);
672-
const cppstd_t cppstd = getCppStd(dui.std);
673-
if ((cstd != CUnknown && cstd < C99) || (cppstd != CPPUnknown && cppstd < CPP11))
674-
maxline = 32767;
675-
else
676-
maxline = 2147483647;
677-
}
674+
if ((cstd != CUnknown && cstd < C99) || (cppstd != CPPUnknown && cppstd < CPP11))
675+
maxline = 32767;
676+
else
677+
maxline = 2147483647;
678678

679679
Location location(fileIndex(filename), 1, 1);
680680
while (stream.good()) {
@@ -744,15 +744,22 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
744744
try {
745745
line = std::stoul(ppTok->str());
746746
} catch (...) {
747-
line = 0;
747+
line = std::numeric_limits<unsigned long>::max();
748748
}
749749

750750
if (line == 0 || line > maxline) {
751751
if (outputList) {
752+
std::string msg = "Line number out of range: " + ppTok->str() + ". ";
753+
if (line == 0) {
754+
msg += "Line number zero is undefined behavior.";
755+
} else {
756+
const char *support_type = cppstd == CPP26 ? "conditionally supported" : "undefined behavior";
757+
std::string std_name = std_is_c ? getCStdName(cstd) : getCppStdName(cppstd);
758+
msg += "Line numbers above " + std::to_string(maxline) + " are " + support_type + " in " + std_name + ".";
759+
}
752760
simplecpp::Output err{
753761
simplecpp::Output::PORTABILITY_LINE_DIRECTIVE,
754-
location,
755-
"Line number out of range: " + ppTok->str() + "."
762+
location, msg
756763
};
757764
outputList->emplace_back(std::move(err));
758765
}
@@ -3997,7 +4004,7 @@ void simplecpp::cleanup(FileDataCache &cache)
39974004
cache.clear();
39984005
}
39994006

4000-
simplecpp::cstd_t simplecpp::getCStd(const std::string &std)
4007+
simplecpp::cstd_t simplecpp::getCStd(const std::string &std, cstd_t dflt)
40014008
{
40024009
if (std == "c90" || std == "c89" || std == "iso9899:1990" || std == "iso9899:199409" || std == "gnu90" || std == "gnu89")
40034010
return C89;
@@ -4011,7 +4018,19 @@ simplecpp::cstd_t simplecpp::getCStd(const std::string &std)
40114018
return C23;
40124019
if (std == "c2y" || std == "gnu2y")
40134020
return C2Y;
4014-
return CUnknown;
4021+
return dflt;
4022+
}
4023+
4024+
const char *simplecpp::getCStdName(cstd_t std)
4025+
{
4026+
switch (std) {
4027+
case CUnknown: return "C";
4028+
case C89: return "C89";
4029+
case C99: return "C99";
4030+
case C11: return "C17";
4031+
case C23: return "C23";
4032+
case C2Y: return "C2Y";
4033+
}
40154034
}
40164035

40174036
std::string simplecpp::getCStdString(cstd_t std)
@@ -4047,7 +4066,7 @@ std::string simplecpp::getCStdString(const std::string &std)
40474066
return getCStdString(getCStd(std));
40484067
}
40494068

4050-
simplecpp::cppstd_t simplecpp::getCppStd(const std::string &std)
4069+
simplecpp::cppstd_t simplecpp::getCppStd(const std::string &std, cppstd_t dflt)
40514070
{
40524071
if (std == "c++98" || std == "c++03" || std == "gnu++98" || std == "gnu++03")
40534072
return CPP03;
@@ -4063,7 +4082,21 @@ simplecpp::cppstd_t simplecpp::getCppStd(const std::string &std)
40634082
return CPP23;
40644083
if (std == "c++26" || std == "c++2c" || std == "gnu++26" || std == "gnu++2c")
40654084
return CPP26;
4066-
return CPPUnknown;
4085+
return dflt;
4086+
}
4087+
4088+
const char *simplecpp::getCppStdName(cppstd_t std)
4089+
{
4090+
switch (std) {
4091+
case CPPUnknown: return "C++";
4092+
case CPP03: return "C++03";
4093+
case CPP11: return "C++11";
4094+
case CPP14: return "C++14";
4095+
case CPP17: return "C++17";
4096+
case CPP20: return "C++20";
4097+
case CPP23: return "C++23";
4098+
case CPP26: return "C++26";
4099+
}
40674100
}
40684101

40694102
std::string simplecpp::getCppStdString(cppstd_t std)

simplecpp.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,10 +588,16 @@ namespace simplecpp {
588588
SIMPLECPP_LIB std::string convertCygwinToWindowsPath(const std::string &cygwinPath);
589589

590590
/** Returns the C version a given standard */
591-
SIMPLECPP_LIB cstd_t getCStd(const std::string &std);
591+
SIMPLECPP_LIB cstd_t getCStd(const std::string &std, cstd_t dflt = CUnknown);
592+
593+
/** Returns the name of a C standard */
594+
SIMPLECPP_LIB const char *getCStdName(cstd_t std);
592595

593596
/** Returns the C++ version a given standard */
594-
SIMPLECPP_LIB cppstd_t getCppStd(const std::string &std);
597+
SIMPLECPP_LIB cppstd_t getCppStd(const std::string &std, cppstd_t dflt = CPPUnknown);
598+
599+
/** Returns the name of a C++ standard */
600+
SIMPLECPP_LIB const char *getCppStdName(cppstd_t std);
595601

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

test.cpp

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,6 +2860,12 @@ static void nullDirective3()
28602860
static void lineDirective()
28612861
{
28622862
for (const std::string std : {"c89", "c90", "c++03"}) {
2863+
std::string std_name;
2864+
if (simplecpp::getCStd(std) != simplecpp::CUnknown)
2865+
std_name = simplecpp::getCStdName(simplecpp::getCStd(std));
2866+
else
2867+
std_name = simplecpp::getCppStdName(simplecpp::getCppStd(std));
2868+
28632869
simplecpp::DUI dui;
28642870
dui.std = std;
28652871

@@ -2869,7 +2875,7 @@ static void lineDirective()
28692875
";\n";
28702876
simplecpp::OutputList outputList;
28712877
makeTokenList(code, dui, &outputList);
2872-
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 0.\n",
2878+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 0. Line number zero is undefined behavior.\n",
28732879
toString(outputList));
28742880
}
28752881

@@ -2888,7 +2894,7 @@ static void lineDirective()
28882894
";\n";
28892895
simplecpp::OutputList outputList;
28902896
makeTokenList(code, dui, &outputList);
2891-
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 32768.\n",
2897+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 32768. Line numbers above 32767 are undefined behavior in " + std_name + ".\n",
28922898
toString(outputList));
28932899
}
28942900

@@ -2898,12 +2904,18 @@ static void lineDirective()
28982904
";\n";
28992905
simplecpp::OutputList outputList;
29002906
makeTokenList(code, dui, &outputList);
2901-
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 18446744073709551617.\n",
2907+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 18446744073709551617. Line numbers above 32767 are undefined behavior in " + std_name + ".\n",
29022908
toString(outputList));
29032909
}
29042910
}
29052911

2906-
for (const std::string std : {"c99", "c++11"}) {
2912+
for (const std::string std : {"c99", "c++11", "c++14", "c++17", "c++20", "c++23"}) {
2913+
std::string std_name;
2914+
if (simplecpp::getCStd(std) != simplecpp::CUnknown)
2915+
std_name = simplecpp::getCStdName(simplecpp::getCStd(std));
2916+
else
2917+
std_name = simplecpp::getCppStdName(simplecpp::getCppStd(std));
2918+
29072919
simplecpp::DUI dui;
29082920
dui.std = std;
29092921

@@ -2913,7 +2925,71 @@ static void lineDirective()
29132925
";\n";
29142926
simplecpp::OutputList outputList;
29152927
makeTokenList(code, dui, &outputList);
2916-
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 0.\n",
2928+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 0. Line number zero is undefined behavior.\n",
2929+
toString(outputList));
2930+
}
2931+
2932+
{
2933+
const char code[] =
2934+
"#line 32767\n"
2935+
";\n";
2936+
simplecpp::OutputList outputList;
2937+
makeTokenList(code, dui, &outputList);
2938+
ASSERT_EQUALS("", toString(outputList));
2939+
}
2940+
2941+
{
2942+
const char code[] =
2943+
"#line 32768\n"
2944+
";\n";
2945+
simplecpp::OutputList outputList;
2946+
makeTokenList(code, dui, &outputList);
2947+
ASSERT_EQUALS("", toString(outputList));
2948+
}
2949+
2950+
{
2951+
const char code[] =
2952+
"#line 2147483647\n"
2953+
";\n";
2954+
simplecpp::OutputList outputList;
2955+
makeTokenList(code, dui, &outputList);
2956+
ASSERT_EQUALS("", toString(outputList));
2957+
}
2958+
2959+
{
2960+
const char code[] =
2961+
"#line 2147483648\n"
2962+
";\n";
2963+
simplecpp::OutputList outputList;
2964+
makeTokenList(code, dui, &outputList);
2965+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 2147483648. Line numbers above 2147483647 are undefined behavior in " + std_name + ".\n",
2966+
toString(outputList));
2967+
}
2968+
2969+
{
2970+
const char code[] =
2971+
"#line 18446744073709551617\n" // 2^64 + 1
2972+
";\n";
2973+
simplecpp::OutputList outputList;
2974+
makeTokenList(code, dui, &outputList);
2975+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 18446744073709551617. Line numbers above 2147483647 are undefined behavior in " + std_name + ".\n",
2976+
toString(outputList));
2977+
}
2978+
}
2979+
2980+
{
2981+
std::string std_name = "C++26";
2982+
2983+
simplecpp::DUI dui;
2984+
dui.std = "c++26";
2985+
2986+
{
2987+
const char code[] =
2988+
"#line 0\n"
2989+
";\n";
2990+
simplecpp::OutputList outputList;
2991+
makeTokenList(code, dui, &outputList);
2992+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 0. Line number zero is undefined behavior.\n",
29172993
toString(outputList));
29182994
}
29192995

@@ -2950,7 +3026,7 @@ static void lineDirective()
29503026
";\n";
29513027
simplecpp::OutputList outputList;
29523028
makeTokenList(code, dui, &outputList);
2953-
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 2147483648.\n",
3029+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 2147483648. Line numbers above 2147483647 are conditionally supported in " + std_name + ".\n",
29543030
toString(outputList));
29553031
}
29563032

@@ -2960,7 +3036,7 @@ static void lineDirective()
29603036
";\n";
29613037
simplecpp::OutputList outputList;
29623038
makeTokenList(code, dui, &outputList);
2963-
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 18446744073709551617.\n",
3039+
ASSERT_EQUALS("file0,2,portability_line_directive,Line number out of range: 18446744073709551617. Line numbers above 2147483647 are conditionally supported in " + std_name + ".\n",
29643040
toString(outputList));
29653041
}
29663042
}

0 commit comments

Comments
 (0)