Skip to content

Instantly share code, notes, and snippets.

@rprichard
Created September 1, 2022 23:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rprichard/3dad0e334cef31e2ec284666fe975cd9 to your computer and use it in GitHub Desktop.
Save rprichard/3dad0e334cef31e2ec284666fe975cd9 to your computer and use it in GitHub Desktop.
Current API19 (and 23) libc++ bug feature detection
# Android added %a printf starting with Android L (API 21).
Feature(name='android-no-printf-a',
when=lambda cfg: _isAndroid(cfg) and not _isAndroidApiAtLeast(cfg, 21) and
not programSucceeds(cfg, """
#include <stdio.h>
#include <string.h>
int main(int, char**) {
char buf[100];
snprintf(buf, sizeof(buf), "%a", 0.0);
return strcmp(buf, "0x0p+0");
}
""")),
# Android added hex-float strto{f,d,ld} starting with Android L (API 21).
Feature(name='android-no-strtof-hex-flt',
when=lambda cfg: _isAndroid(cfg) and not _isAndroidApiAtLeast(cfg, 21) and
not programSucceeds(cfg, """
#include <stdlib.h>
int main(int, char**) {
return !(strtof("0x1p+4", NULL) == 16 &&
strtod("0x1p+4", NULL) == 16 &&
strtold("0x1p+4", NULL) == 16);
}
"""),
actions=[AddCompileFlag('-D_LIBCPP_TESTING_ANDROID_NO_STRTOF_HEX_FLT')]),
# Android added %F printf starting with Android L (API 21).
Feature(name='android-no-printf-F',
when=lambda cfg: _isAndroid(cfg) and not _isAndroidApiAtLeast(cfg, 21) and
not programSucceeds(cfg, """
#include <stdio.h>
#include <string.h>
int main(int, char**) {
char buf[100];
snprintf(buf, sizeof(buf), "%1.1F", 0.0);
return strcmp(buf, "0.0");
}
"""),
actions=[AddCompileFlag('-D_LIBCPP_TESTING_ANDROID_NO_PRINTF_CAPITAL_F')]),
# Android %f prints negative 0 like positive 0 prior to Android L (API 21).
Feature(name='android-broken-printf-neg0',
when=lambda cfg: _isAndroid(cfg) and not _isAndroidApiAtLeast(cfg, 21) and
not programSucceeds(cfg, """
#include <stdio.h>
#include <string.h>
int main(int, char**) {
char buf[100];
snprintf(buf, sizeof(buf), "%1.1f", -0.0);
return strcmp(buf, "-0.0");
}
"""),
actions=[AddCompileFlag('-D_LIBCPP_TESTING_ANDROID_BROKEN_NEG0')]),
# Prior to Android L (API 21), INFINITY and NAN are formatted as "Inf" and
# "NaN". Android L and up use inf/INF and nan/NAN depending on format letter
# case.
Feature(name='android-printf-nan-inf-mixed-case',
when=lambda cfg: _isAndroid(cfg) and not _isAndroidApiAtLeast(cfg, 21) and
not programSucceeds(cfg, """
#include <math.h>
#include <stdio.h>
#include <string.h>
int main(int, char**) {
char buf[100];
snprintf(buf, sizeof(buf), "%f %f", INFINITY, NAN);
return strcmp(buf, "inf nan");
}
"""),
actions=[AddCompileFlag('-D_LIBCPP_TESTING_ANDROID_PRINTF_NAN_INF_MIXED_CASE')]),
# Considering NAN and -NAN:
# - Android K (API 19): "%f" prints "NaN", "%+f" prints "+NaN" (even for
# -NAN, the sign bit is ignored).
# - Android L (API 21): "%f" and "%+f" print "nan".
# - Android M (API 23) and up: "%f" prints "nan" or "-nan", "%+f" prints
# "+nan" or "-nan".
# Set this feature for L, where the sign is never printed. Otherwise, "%+f"
# for non-negative NAN prints the '+' sign.
Feature(name='android-printf-nan-no-sign',
when=lambda cfg: _isAndroid(cfg) and not _isAndroidApiAtLeast(cfg, 23) and
not programSucceeds(cfg, """
#include <math.h>
#include <stdio.h>
int main(int, char**) {
char buf[100];
snprintf(buf, sizeof(buf), "%+f", NAN);
return buf[0] != '+';
}
"""),
actions=[AddCompileFlag('-D_LIBCPP_TESTING_ANDROID_PRINTF_NAN_NO_SIGN')]),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment