From 36f9d995c218cbd4e4754e0dcc7e4f964f1305ba Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 25 Jan 2024 11:15:53 +0000 Subject: [PATCH] C/C++ front-end: accept all floating-point extensions that GCC and Clang support Testing with Compiler Explorer showed that Clang supports a subset of GCC's extensions, and GCC also supports some more extensions that what we previously covered. --- regression/ansi-c/float_constant1/main.c | 12 ++++++++++++ src/ansi-c/literals/parse_float.cpp | 17 +++++++---------- src/ansi-c/scanner.l | 17 ++++++++++++++++- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/regression/ansi-c/float_constant1/main.c b/regression/ansi-c/float_constant1/main.c index 93fc5e4b4c44..086bfefa82ff 100644 --- a/regression/ansi-c/float_constant1/main.c +++ b/regression/ansi-c/float_constant1/main.c @@ -21,9 +21,21 @@ STATIC_ASSERT(__builtin_types_compatible_p(_Float64, __typeof(1.0f64))); STATIC_ASSERT(__builtin_types_compatible_p(_Float128, __typeof(1.0f128))); STATIC_ASSERT(__builtin_types_compatible_p(_Float32x, __typeof(1.0f32x))); STATIC_ASSERT(__builtin_types_compatible_p(_Float64x, __typeof(1.0f64x))); +// f128x should be supported by GCC >= 7 (and for C++ in GCC >=13), but there +// are not current GCC ports that actually support such types STATIC_ASSERT(__builtin_types_compatible_p(_Float128x, __typeof(1.0f128x))); #endif +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 13 +STATIC_ASSERT(__builtin_types_compatible_p(_Float16, __typeof(1.0f16))); +STATIC_ASSERT(__builtin_types_compatible_p(__bf16, __typeof(1.0bf16))); +STATIC_ASSERT(__builtin_types_compatible_p(__bf16, __typeof(1.BF16))); +#endif + +#if defined(__clang__) && __clang_major__ >= 6 +STATIC_ASSERT(__builtin_types_compatible_p(_Float16, __typeof(1.0f16))); +#endif + #ifdef __GNUC__ _Complex c; #endif diff --git a/src/ansi-c/literals/parse_float.cpp b/src/ansi-c/literals/parse_float.cpp index b56f9e44f937..bd0fc35d144a 100644 --- a/src/ansi-c/literals/parse_float.cpp +++ b/src/ansi-c/literals/parse_float.cpp @@ -77,8 +77,8 @@ parse_floatt::parse_floatt(const std::string &src) p++; // get exponent - while(*p!=0 && *p!='f' && *p!='l' && - *p!='w' && *p!='q' && *p!='d') + while(*p != 0 && *p != 'f' && *p != 'l' && *p != 'w' && *p != 'q' && + *p != 'd' && *p != 'b') { str_exponent+=*p; p++; @@ -121,10 +121,8 @@ parse_floatt::parse_floatt(const std::string &src) p++; // get fraction part - while(*p!=0 && *p!='e' && - *p!='f' && *p!='l' && - *p!='w' && *p!='q' && *p!='d' && - *p!='i' && *p!='j') + while(*p != 0 && *p != 'e' && *p != 'f' && *p != 'l' && *p != 'w' && + *p != 'q' && *p != 'd' && *p != 'i' && *p != 'j' && *p != 'b') { str_fraction_part+=*p; p++; @@ -139,9 +137,8 @@ parse_floatt::parse_floatt(const std::string &src) p++; // get exponent - while(*p!=0 && *p!='f' && *p!='l' && - *p!='w' && *p!='q' && *p!='d' && - *p!='i' && *p!='j') + while(*p != 0 && *p != 'f' && *p != 'l' && *p != 'w' && *p != 'q' && + *p != 'd' && *p != 'i' && *p != 'j' && *p != 'b') { str_exponent+=*p; p++; @@ -173,7 +170,7 @@ parse_floatt::parse_floatt(const std::string &src) is_float80=false; is_float128=is_float128x=false; - if(strcmp(p, "f16")==0) + if(strcmp(p, "f16") == 0 || strcmp(p, "bf16") == 0) is_float16=true; else if(strcmp(p, "f32")==0) is_float32=true; diff --git a/src/ansi-c/scanner.l b/src/ansi-c/scanner.l index a55fc3b1fc0b..60114f189686 100644 --- a/src/ansi-c/scanner.l +++ b/src/ansi-c/scanner.l @@ -217,10 +217,13 @@ hexfloat1 "0"[xX]{hexdigit}*"."{hexdigit}+[pP][+-]?{integer} hexfloat2 "0"[xX]{hexdigit}*"."[pP][+-]?{integer} hexfloat3 "0"[xX]{hexdigit}*[pP][+-]?{integer} float_suffix [fFlLiIjJ]* -gcc_ext_float_suffix [wWqQ]|[dD][fFdDlL]?|"f16"|"f32"|"f64"|"f128"|"f32x"|"f64x"|"f128x" +clang_ext_float_suffix [qQ]|"f16"|"F16" +gcc_ext_float_width (("bf"|"BF")"16")|([fF]("32"|"64"|"128"|"32x"|"64x"|"128x")) +gcc_ext_float_suffix {clang_ext_float_suffix}|[wW]|[dD][fFdDlL]?|{gcc_ext_float_width} float {float1}|{float2}|{float3}|{hexfloat1}|{hexfloat2}|{hexfloat3} float_s {float}{float_suffix}|{integer}[fF] gcc_ext_float_s {float}{gcc_ext_float_suffix} +clang_ext_float_s {float}{clang_ext_float_suffix} cppstart {ws}"#"{ws} cpplineno {cppstart}"line"*{ws}{integer}{ws}.*{newline} cppdirective {cppstart}({newline}|[^p].*|"p"[^r].*|"pr"[^a].*|"pra"[^g].*|"prag"[^m].*|"pragm"[^a].*) @@ -1561,6 +1564,18 @@ __decltype { if(PARSER.cpp98 && return TOK_INTEGER; } +{clang_ext_float_s} { if(PARSER.mode!=configt::ansi_ct::flavourt::GCC && + PARSER.mode != configt::ansi_ct::flavourt::CLANG) + { + yyansi_cerror("Preprocessor directive found"); + return TOK_SCANNER_ERROR; + } + newstack(yyansi_clval); + parser_stack(yyansi_clval)=convert_float_literal(yytext); + PARSER.set_source_location(parser_stack(yyansi_clval)); + return TOK_FLOATING; + } + {gcc_ext_float_s} { if(PARSER.mode!=configt::ansi_ct::flavourt::GCC) { yyansi_cerror("Preprocessor directive found");