1# Executing Actions. -*- Autotest -*- 2 3# Copyright (C) 2002, 2004-2005, 2007, 2009-2015, 2018-2021 Free 4# Software Foundation, Inc. 5 6# This program is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <https://www.gnu.org/licenses/>. 18 19AT_BANNER([[Sync Lines.]]) 20 21 22# _AT_SYNCLINES_COMPILE(FILE) 23# --------------------------- 24# Compile FILE expecting an error, and save in the file stdout the 25# normalized output. Ignore the exit status, since some compilers 26# (e.g. c89 on IRIX 6.5) trigger warnings on '#error', instead of 27# errors. 28m4_define([_AT_SYNCLINES_COMPILE], 29[AT_CHECK([$CC $CFLAGS $CPPFLAGS -c $1], [ignore], [], [stderr]) 30 31# Transform the file 'stderr' into something like this: 32# 33# input.y:4: #error "4" 34# 35# In case GCC displays column information, strip it down. 36# 37# input.y:4:2: #error "4" or 38# input.y:4.2: #error "4" or 39# input.y:4:2: error: #error "4" 40# => 41# input.y:4: #error "4" 42# 43# It may also issue more context information: 44# 45# input.y: In function 'yyparse': 46# input.y:8: #error "8" 47# => 48# input.y:4: #error "8" 49# 50# The message may include a caret-error (indented by GCC 4.8, 51# not by clang 3.2): 52# 53# input.y:1:2: error: #error "1" 54# #error "1" 55# ^ 56# 57# Possibly distcc adds its bits. 58# 59# distcc[33187] ERROR: compile (null) on localhost failed 60# syncline.c:1:2: error: #error "1" 61# distcc[33185] ERROR: compile syncline.c on localhost failed 62# 63# or even 64# 65# distcc[35882] (dcc_connect_by_name) ERROR: failed to look up host "chrisimac": Unknown host 66# distcc[35882] Warning: failed to distribute input.c to chrisimac/4, running locally instead 67# 68# The compiler might end by the number of messages issued (Clang 3.2): 69# 70# syncline.c:1:2: error: "1" 71# #error "1" 72# ^ 73# 1 error generated. 74# 75# When c++ is used to compiler C, we might have more messages (Clang 3.2): 76# 77# clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated 78# 79# 80# xlc reports things like: 81# 82# "input.yy", line 80.21: 1540-0218 (S) The call does not match any parameter list for "operator<<". 83# "/usr/vacpp/include/iosfwd", line 32.6: 1506-205 (S) #error This file to be used only with IBM VisualAge C++ v4 and later compilers 84# 85# Newer GCCs go further and if the function is declared static, complain 86# that it's not used. 87# 88# GCC 7 also underlines the error. 89# 90# syncline.c:4:2: error: #error "4" 91# #error "4" 92# ^~~~~ 93# 94# GCC 9 displays a left-hand margin with the line number: 95# 96# syncline.c: In function 'foo': 97# syncline.c:4:2: error: #error "4" 98# 4 | #error "4" 99# | ^~~~~ 100AT_CHECK([["$PERL" -p -0777 - stderr <<\EOF || exit 77 101 # Remove left-hand margin. 102 s/^[\d ]{6}\| //gm; 103 104 # 1. Remove useless lines. 105 106 # distcc clutter. 107 s/^distcc\[\d+\] .*\n//gm; 108 # c vs. c++. 109 s/^clang: warning: treating 'c' input as 'c\+\+'.*\n//gm; 110 # Function context. 111 s/^[^:]*: In function '[^']+':\n//gm; 112 # Caret error (with possible '~' to underline). 113 s/^ *#error.*\n *\^~*\n//gm; 114 # Number of errors. 115 s/^1 error generated\.\n//gm; 116 117 # 2. Normalize the lines we kept. 118 119 # xlc messages. Remove also error identifier (e.g., "1540-0218 (S)"). 120 s/^"(.*?)", line ([\w.]*): \d+-\d+ \(.\) /$][1:$][2: /gm; 121 # Remove column. 122 s/^([^:]+:\d+)[.:][^:]+:(.+)$/$][1:$][2/gm; 123 # Map all combinations of "error: " and "#error: " to "#error ". 124 s/^([^:]+:\d+):( |#error|error|:)+/$][1: #error /gm; 125EOF 126]], 127 0, [stdout]) 128]) 129 130 131 132# AT_SYNCLINES_COMPILE(FILE) 133# -------------------------- 134# Compile FILE expecting an error, and save in the file 'stdout' the 135# normalized output. If we can't get a trustable location 136# from the compiler, just skip the test. 137# 138# It seems impossible to find a generic scheme to check the location 139# of an error. Even requiring GCC is not sufficient, since for instance 140# the version modified by Apple: 141# 142# | Reading specs from /usr/libexec/gcc/darwin/ppc/2.95.2/specs 143# | Apple Computer, Inc. version gcc-934.3, based on gcc version 2.95.2 144# | 19991024 (release) configure:2124: $? = 0 145# 146# instead of: 147# 148# | input.y:2: #error "2" 149# 150# it reports: 151# 152# | input.y:2: "2" 153# | cpp-precomp: warning: errors during smart preprocessing, retrying in basic mode 154m4_define([AT_SYNCLINES_COMPILE], 155[# Check if we can trust location translation. 156AT_DATA([syncline.c], 157[[void foo (void); 158void foo (void) 159{ 160#error "4" 161} 162]]) 163 164_AT_SYNCLINES_COMPILE([syncline.c]) 165AT_REQUIRE([[test "`cat stdout`" = 'syncline.c:4: @%:@error "4"']]) 166 167# Then work for real. 168_AT_SYNCLINES_COMPILE([$1]) 169]) 170 171 172# AT_TEST(TITLE, INPUT, ERROR-MSG) 173# -------------------------------- 174# Check that compiling the parser produced from INPUT cause GCC 175# to issue ERROR-MSG. 176m4_pushdef([AT_TEST], 177[AT_SETUP([$1]) 178AT_BISON_OPTION_PUSHDEFS 179 180AT_DATA([[input.y]], [$2]) 181AT_BISON_CHECK([-o input.c input.y]) 182AT_SYNCLINES_COMPILE([input.c]) 183AT_CHECK([cat stdout], 0, [$3]) 184AT_BISON_OPTION_POPDEFS 185AT_CLEANUP 186]) 187 188 189## ------------------- ## 190## Prologue syncline. ## 191## ------------------- ## 192 193 194AT_TEST([Prologue syncline], 195[[%{ 196#error "2" 197%} 198%code { 199 ]AT_YYERROR_DECLARE_EXTERN[ 200 ]AT_YYLEX_DECLARE_EXTERN[ 201} 202%% 203exp: '0'; 204%% 205]], 206[input.y:2: #error "2" 207]) 208 209 210## ----------------- ## 211## %union syncline. ## 212## ----------------- ## 213 214AT_TEST([%union syncline], 215[[%union { 216#error "2" 217 char dummy; 218} 219%code { 220 ]AT_YYERROR_DECLARE_EXTERN[ 221 ]AT_YYLEX_DECLARE_EXTERN[ 222} 223%% 224exp: '0'; 225%% 226]], 227[input.y:2: #error "2" 228]) 229 230 231## ---------------------- ## 232## %union name syncline. ## 233## ---------------------- ## 234 235# Check that invalid union names are properly reported in the 236# source file. 237AT_SETUP([%union name syncline]) 238AT_BISON_OPTION_PUSHDEFS 239AT_DATA([[input.y]], 240[[%union break 241{ 242 char dummy; 243} 244%code { 245 ]AT_YYERROR_DECLARE_EXTERN[ 246 ]AT_YYLEX_DECLARE_EXTERN[ 247%} 248%% 249exp: '0'; 250%% 251]]) 252 253AT_BISON_CHECK([-o input.c input.y]) 254AT_SYNCLINES_COMPILE([input.c]) 255AT_CHECK([[grep '^input.y:1' stdout]], 0, [ignore]) 256AT_BISON_OPTION_POPDEFS 257AT_CLEANUP 258 259 260## ----------------------- ## 261## Postprologue syncline. ## 262## ----------------------- ## 263 264AT_TEST([Postprologue syncline], 265[[%code { 266 ]AT_YYERROR_DECLARE_EXTERN[ 267 ]AT_YYLEX_DECLARE_EXTERN[ 268} 269%{ 270 /* Preprologue. */ 271%} 272%union 273{ 274 int ival; 275} 276%{ 277#error "13" 278%} 279%% 280exp: '0'; 281%% 282]], 283[input.y:13: #error "13" 284]) 285 286 287## ----------------- ## 288## Action syncline. ## 289## ----------------- ## 290 291AT_TEST([Action syncline], 292[[%code { 293 ]AT_YYERROR_DECLARE_EXTERN[ 294 ]AT_YYLEX_DECLARE_EXTERN[ 295} 296%% 297exp: 298{ 299#error "8" 300}; 301]], 302[input.y:8: #error "8" 303]) 304 305 306## ------------------- ## 307## Epilogue syncline. ## 308## ------------------- ## 309 310AT_TEST([Epilogue syncline], 311[[%code { 312 ]AT_YYERROR_DECLARE_EXTERN[ 313 ]AT_YYLEX_DECLARE_EXTERN[ 314} 315%% 316exp: '0'; 317%% 318#error "8" 319]], 320[input.y:8: #error "8" 321]) 322 323## -------------------- ## 324## %code top syncline. ## 325## -------------------- ## 326 327AT_TEST([%code top syncline], 328[[%code top { 329#error "2" 330} 331%code { 332 ]AT_YYERROR_DECLARE_EXTERN[ 333 ]AT_YYLEX_DECLARE_EXTERN[ 334} 335%% 336exp: '0'; 337%% 338]], 339[input.y:2: #error "2" 340]) 341 342## ---------------------- ## 343## %destructor syncline. ## 344## ---------------------- ## 345 346AT_TEST([%destructor syncline], 347[[%destructor { 348#error "2" 349} <ival> 350%{ 351]AT_YYERROR_DECLARE_EXTERN[ 352]AT_YYLEX_DECLARE_EXTERN[ 353%} 354%union { 355 int ival; 356} 357%type <ival> exp 358%% 359exp: '0' { $$ = 0; }; 360%% 361]], 362[input.y:2: #error "2" 363]) 364 365 366## ------------------- ## 367## %printer syncline. ## 368## ------------------- ## 369 370AT_TEST([%printer syncline], 371[[%printer { 372#error "2" 373} <ival> 374%debug 375%code { 376 ]AT_YYERROR_DECLARE_EXTERN[ 377 ]AT_YYLEX_DECLARE_EXTERN[ 378} 379%union { 380 int ival; 381} 382%type <ival> exp 383%% 384exp: '0' { $$ = 0; }; 385%% 386]], 387[input.y:2: #error "2" 388]) 389 390m4_popdef([AT_TEST]) 391 392 393 394## ------------------ ## 395## syncline escapes. ## 396## ------------------ ## 397 398# AT_TEST([SKELETON]) 399# ------------------- 400m4_pushdef([AT_TEST], 401[AT_SETUP([syncline escapes: $1]) 402 403AT_BISON_OPTION_PUSHDEFS([%skeleton "$1"]) 404 405# ICC is unable to handle these file names: it fails to pass them 406# properly to the linker, and is unable to save a file named this way. 407# Don't try with such compilers. 408AT_DATA([\"\\\"\".AT_LANG_EXT], 409[[int main (void) { return 0; } 410]]) 411 412AT_REQUIRE([AT_CXX_IF([$CXX $CXXFLAGS], [$CC $CFLAGS]) $CPPFLAGS \"\\\"\".]AT_LANG_EXT[ -o \"\\\"\"], 413 [0], [ignore], [ignore]) 414 415AT_DATA_GRAMMAR([\"\\\"\".y], 416[[%skeleton "$1" 417%code { 418 ]AT_YYERROR_DECLARE[ 419 ]AT_YYLEX_DECLARE[ 420} 421%destructor {} <> 422%printer {} <> 423%% 424exp: '0' 425%% 426]AT_YYERROR_DEFINE[ 427]AT_YYLEX_DEFINE[ 428]AT_MAIN_DEFINE[ 429]]) 430 431# Maybe we tried to create a file name that the file system does not 432# support. 433AT_SKIP_IF([[test ! -f \"\\\"\".y]]) 434AT_FULL_COMPILE([\"\\\"\"]) 435AT_BISON_OPTION_POPDEFS 436 437AT_CLEANUP 438]) 439 440m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc]) 441 442m4_popdef([AT_TEST]) 443 444 445 446## ----------- ## 447## %no-lines. ## 448## ----------- ## 449 450# AT_TEST([SKELETON]) 451# ------------------- 452m4_pushdef([AT_TEST], 453[AT_SETUP([%no-lines: $1]) 454 455AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %defines]) 456AT_DATA_GRAMMAR([input.y], 457[[%skeleton "$1" %defines 458%{ 459]AT_YYERROR_DECLARE_EXTERN[ 460]AT_YYLEX_DECLARE_EXTERN[ 461%} 462%union { 463 int ival; 464} 465%% 466exp: '0' 467]]) 468 469# Generate without.* without the #line. Don't use -o without.c which 470# would change the content (e.g., CPP guard depend on the output file 471# name). 472AT_BISON_CHECK([--no-lines -o input.AT_LANG_EXT -d input.y]) 473AT_CHECK([mv input.]AT_LANG_EXT[ without.]AT_LANG_EXT[]) 474AT_CHECK([mv input.]AT_LANG_HDR[ without.]AT_LANG_HDR[]) 475# There is no #line at all. 476AT_CHECK([grep '#line' *.]AT_LANG_EXT[ *.]AT_LANG_HDR[], 1) 477 478# Generate with.* without the #line. 479AT_BISON_CHECK([-o input.AT_LANG_EXT -d input.y]) 480AT_CHECK([mv input.]AT_LANG_EXT[ with.]AT_LANG_EXT[]) 481AT_CHECK([mv input.]AT_LANG_HDR[ with.]AT_LANG_HDR[]) 482 483# The implementation file with --no-line is exactly the 484# original one with #lines removed. 485AT_CHECK([grep -v '#line' with.]AT_LANG_EXT[ >expout]) 486AT_CHECK([cat without.AT_LANG_EXT], 0, [expout]) 487 488# Likewise for the header. 489AT_CHECK([grep -v '#line' with.]AT_LANG_HDR[ >expout]) 490AT_CHECK([cat without.AT_LANG_HDR], 0, [expout]) 491 492AT_BISON_OPTION_POPDEFS 493 494AT_CLEANUP 495]) 496 497m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc]) 498 499m4_popdef([AT_TEST]) 500 501 502 503## ---------------- ## 504## Output columns. ## 505## ---------------- ## 506 507AT_SETUP([Output columns]) 508 509# This test is fragile: its point is to check the compiler's error 510# message, but it seems too hard to do portability (even between 511# version of GCC). So instead, let's just check the generated code 512# itself. 513 514AT_BISON_OPTION_PUSHDEFS 515AT_DATA([input.y], 516[[%{ 517]AT_YYERROR_DECLARE_EXTERN[ 518]AT_YYLEX_DECLARE_EXTERN[ 519%} 520%define api.value.type union 521%type <int> '0' exp 522%destructor { /* --BEGIN */ 523 destructor 524 /* --END */ } <*> 525%printer { /* --BEGIN */ 526 printer 527 /* --END */ } <*> 528 529 530 531%left '+' 532%% 533exp: exp '+' exp { /* --BEGIN */ 534 $$ = $1 + $3; 535 @$ = @1 + @3; 536 /* --END */ } 537 | '0' 538]]) 539 540AT_BISON_CHECK([-o input.c input.y]) 541AT_CHECK([[sed -ne '/--BEGIN/,/--END/{' \ 542 -e '/input.c/s/ [0-9]* / LINE /;' \ 543 -e 'p;}' \ 544 input.c]], 0, 545[[ { /* --BEGIN */ 546 printer 547 /* --END */ } 548 { /* --BEGIN */ 549 printer 550 /* --END */ } 551 { /* --BEGIN */ 552 destructor 553 /* --END */ } 554 { /* --BEGIN */ 555 destructor 556 /* --END */ } 557 { /* --BEGIN */ 558 (yyval.exp) = (yyvsp[-2].exp) + (yyvsp[0].exp); 559 (yyloc) = (yylsp[-2]) + (yylsp[0]); 560 /* --END */ } 561]]) 562 563AT_BISON_OPTION_POPDEFS 564AT_CLEANUP 565