Skip to content

Commit 78db387

Browse files
committed
Merge upstream stable (dlang/dmd@6825ed6a88)
1 parent 38e3014 commit 78db387

File tree

5 files changed

+64
-20
lines changed

5 files changed

+64
-20
lines changed

dmd/chkformat.d

+59-15
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ module dmd.chkformat;
1313
//import core.stdc.stdio : printf, scanf;
1414
import core.stdc.ctype : isdigit;
1515

16+
import dmd.cond;
1617
import dmd.errors;
1718
import dmd.expression;
1819
import dmd.globals;
20+
import dmd.identifier;
1921
import dmd.mtype;
2022
import dmd.target;
2123

@@ -59,7 +61,7 @@ import dmd.target;
5961
bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expression[] args, bool isVa_list)
6062
{
6163
//printf("checkPrintFormat('%.*s')\n", cast(int)format.length, format.ptr);
62-
size_t n = 0;
64+
size_t n, gnu_m_count; // index in args / number of Format.GNU_m
6365
for (size_t i = 0; i < format.length;)
6466
{
6567
if (format[i] != '%')
@@ -85,11 +87,17 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
8587
continue;
8688
}
8789

88-
Expression getNextArg()
90+
if (fmt == Format.GNU_m)
91+
++gnu_m_count;
92+
93+
Expression getNextArg(ref bool skip)
8994
{
9095
if (n == args.length)
9196
{
92-
deprecation(loc, "more format specifiers than %d arguments", cast(int)n);
97+
if (args.length < (n + 1) - gnu_m_count)
98+
deprecation(loc, "more format specifiers than %zd arguments", n);
99+
else
100+
skip = true;
93101
return null;
94102
}
95103
return args[n++];
@@ -103,7 +111,10 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
103111

104112
if (widthStar)
105113
{
106-
auto e = getNextArg();
114+
bool skip;
115+
auto e = getNextArg(skip);
116+
if (skip)
117+
continue;
107118
if (!e)
108119
return true;
109120
auto t = e.type.toBasetype();
@@ -113,15 +124,21 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
113124

114125
if (precisionStar)
115126
{
116-
auto e = getNextArg();
127+
bool skip;
128+
auto e = getNextArg(skip);
129+
if (skip)
130+
continue;
117131
if (!e)
118132
return true;
119133
auto t = e.type.toBasetype();
120134
if (t.ty != Tint32 && t.ty != Tuns32)
121135
errorMsg("precision ", slice, e, "int", t);
122136
}
123137

124-
auto e = getNextArg();
138+
bool skip;
139+
auto e = getNextArg(skip);
140+
if (skip)
141+
continue;
125142
if (!e)
126143
return true;
127144
auto t = e.type.toBasetype();
@@ -179,6 +196,7 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
179196
errorMsg(null, slice, e, "ptrdiff_t", t);
180197
break;
181198

199+
case Format.GNU_a: // Format.GNU_a is only for scanf
182200
case Format.lg:
183201
case Format.g: // double
184202
if (t.ty != Tfloat64 && t.ty != Timaginary64)
@@ -260,6 +278,9 @@ bool checkPrintfFormat(ref const Loc loc, scope const char[] format, scope Expre
260278
deprecation(loc, "format specifier `\"%.*s\"` is invalid", cast(int)slice.length, slice.ptr);
261279
break;
262280

281+
case Format.GNU_m:
282+
break; // not assert(0) because it may go through it if there are extra arguments
283+
263284
case Format.percent:
264285
assert(0);
265286
}
@@ -439,15 +460,19 @@ bool checkScanfFormat(ref const Loc loc, scope const char[] format, scope Expres
439460
if (!(t.ty == Tpointer && tnext.ty == Tfloat32))
440461
errorMsg(null, slice, e, "float*", t);
441462
break;
463+
442464
case Format.lg: // pointer to double
443465
if (!(t.ty == Tpointer && tnext.ty == Tfloat64))
444466
errorMsg(null, slice, e, "double*", t);
445467
break;
468+
446469
case Format.Lg: // pointer to long double
447470
if (!(t.ty == Tpointer && tnext.ty == Tfloat80))
448471
errorMsg(null, slice, e, "real*", t);
449472
break;
450473

474+
case Format.GNU_a:
475+
case Format.GNU_m:
451476
case Format.c:
452477
case Format.s: // pointer to char string
453478
if (!(t.ty == Tpointer && (tnext.ty == Tchar || tnext.ty == Tint8 || tnext.ty == Tuns8)))
@@ -493,9 +518,8 @@ private:
493518
* Returns:
494519
* Format
495520
*/
496-
pure nothrow @safe
497521
Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
498-
out bool asterisk)
522+
out bool asterisk) nothrow pure @safe
499523
{
500524
auto i = idx;
501525
assert(format[i] == '%');
@@ -583,9 +607,8 @@ Format parseScanfFormatSpecifier(scope const char[] format, ref size_t idx,
583607
* Returns:
584608
* Format
585609
*/
586-
pure nothrow @safe
587610
Format parsePrintfFormatSpecifier(scope const char[] format, ref size_t idx,
588-
out bool widthStar, out bool precisionStar)
611+
out bool widthStar, out bool precisionStar) nothrow pure @safe
589612
{
590613
auto i = idx;
591614
assert(format[i] == '%');
@@ -767,6 +790,8 @@ enum Format
767790
jn, // pointer to intmax_t
768791
zn, // pointer to size_t
769792
tn, // pointer to ptrdiff_t
793+
GNU_a, // GNU ext. : address to a string with no maximum size (scanf)
794+
GNU_m, // GNU ext. : string corresponding to the error code in errno (printf) / length modifier (scanf)
770795
percent, // %% (i.e. no argument)
771796
error, // invalid format specification
772797
}
@@ -785,9 +810,9 @@ enum Format
785810
* Returns:
786811
* Format
787812
*/
788-
pure @safe nothrow
789813
Format parseGenericFormatSpecifier(scope const char[] format,
790-
ref size_t idx, out char genSpecifier)
814+
ref size_t idx, out char genSpecifier, bool useGNUExts =
815+
findCondition(global.versionids, Identifier.idPool("CRuntime_Glibc"))) nothrow pure @trusted
791816
{
792817
const length = format.length;
793818

@@ -859,13 +884,21 @@ Format parseGenericFormatSpecifier(scope const char[] format,
859884
Format.u;
860885
break;
861886

887+
case 'a':
888+
if (useGNUExts)
889+
{
890+
// https://www.gnu.org/software/libc/manual/html_node/Dynamic-String-Input.html
891+
specifier = Format.GNU_a;
892+
break;
893+
}
894+
goto case;
895+
862896
case 'f':
863897
case 'F':
864898
case 'e':
865899
case 'E':
866900
case 'g':
867901
case 'G':
868-
case 'a':
869902
case 'A':
870903
if (lm == 'L')
871904
specifier = Format.Lg;
@@ -910,6 +943,15 @@ Format parseGenericFormatSpecifier(scope const char[] format,
910943
Format.n;
911944
break;
912945

946+
case 'm':
947+
if (useGNUExts)
948+
{
949+
// http://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
950+
specifier = Format.GNU_m;
951+
break;
952+
}
953+
goto default;
954+
913955
default:
914956
specifier = Format.error;
915957
break;
@@ -1075,7 +1117,8 @@ unittest
10751117
assert(idx == 2);
10761118

10771119
idx = 0;
1078-
assert(parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar) == Format.g);
1120+
Format g = parsePrintfFormatSpecifier("%a", idx, widthStar, precisionStar);
1121+
assert(g == Format.g || g == Format.GNU_a);
10791122
assert(idx == 2);
10801123

10811124
idx = 0;
@@ -1245,7 +1288,8 @@ unittest
12451288
assert(idx == 2);
12461289

12471290
idx = 0;
1248-
assert(parseScanfFormatSpecifier("%a", idx, asterisk) == Format.g);
1291+
g = parseScanfFormatSpecifier("%a", idx, asterisk);
1292+
assert(g == Format.g || g == Format.GNU_a);
12491293
assert(idx == 2);
12501294

12511295
idx = 0;

dmd/cond.d

+1-1
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ extern (C++) final class StaticIfCondition : Condition
961961
* Returns:
962962
* true if found
963963
*/
964-
bool findCondition(Identifiers* ids, Identifier ident)
964+
bool findCondition(Identifiers* ids, Identifier ident) @safe nothrow pure
965965
{
966966
if (ids)
967967
{

dmd/scope.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ struct Scope
124124
AA *anchorCounts; // lookup duplicate anchor name count
125125
Identifier *prevAnchor; // qualified symbol name of last doc anchor
126126

127-
AliasDeclaration *aliasAsg; /// if set, then aliasAsg is being assigned a new value,
128-
/// do not set wasRead for it
127+
AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value,
128+
// do not set wasRead for it
129129
Scope();
130130

131131
Scope *copy();

runtime/druntime

tests/d2/dmd-testsuite

0 commit comments

Comments
 (0)