12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576 |
- /* Main parser.
- Copyright (C) 2000-2015 Free Software Foundation, Inc.
- Contributed by Andy Vaught
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include <setjmp.h>
- #include "coretypes.h"
- #include "flags.h"
- #include "gfortran.h"
- #include "match.h"
- #include "parse.h"
- #include "debug.h"
- /* Current statement label. Zero means no statement label. Because new_st
- can get wiped during statement matching, we have to keep it separate. */
- gfc_st_label *gfc_statement_label;
- static locus label_locus;
- static jmp_buf eof_buf;
- gfc_state_data *gfc_state_stack;
- static bool last_was_use_stmt = false;
- /* TODO: Re-order functions to kill these forward decls. */
- static void check_statement_label (gfc_statement);
- static void undo_new_statement (void);
- static void reject_statement (void);
- /* A sort of half-matching function. We try to match the word on the
- input with the passed string. If this succeeds, we call the
- keyword-dependent matching function that will match the rest of the
- statement. For single keywords, the matching subroutine is
- gfc_match_eos(). */
- static match
- match_word (const char *str, match (*subr) (void), locus *old_locus)
- {
- match m;
- if (str != NULL)
- {
- m = gfc_match (str);
- if (m != MATCH_YES)
- return m;
- }
- m = (*subr) ();
- if (m != MATCH_YES)
- {
- gfc_current_locus = *old_locus;
- reject_statement ();
- }
- return m;
- }
- /* Like match_word, but if str is matched, set a flag that it
- was matched. */
- static match
- match_word_omp_simd (const char *str, match (*subr) (void), locus *old_locus,
- bool *simd_matched)
- {
- match m;
- if (str != NULL)
- {
- m = gfc_match (str);
- if (m != MATCH_YES)
- return m;
- *simd_matched = true;
- }
- m = (*subr) ();
- if (m != MATCH_YES)
- {
- gfc_current_locus = *old_locus;
- reject_statement ();
- }
- return m;
- }
- /* Load symbols from all USE statements encountered in this scoping unit. */
- static void
- use_modules (void)
- {
- gfc_error_buf old_error_1;
- output_buffer old_error;
- gfc_push_error (&old_error, &old_error_1);
- gfc_buffer_error (false);
- gfc_use_modules ();
- gfc_buffer_error (true);
- gfc_pop_error (&old_error, &old_error_1);
- gfc_commit_symbols ();
- gfc_warning_check ();
- gfc_current_ns->old_cl_list = gfc_current_ns->cl_list;
- gfc_current_ns->old_equiv = gfc_current_ns->equiv;
- gfc_current_ns->old_data = gfc_current_ns->data;
- last_was_use_stmt = false;
- }
- /* Figure out what the next statement is, (mostly) regardless of
- proper ordering. The do...while(0) is there to prevent if/else
- ambiguity. */
- #define match(keyword, subr, st) \
- do { \
- if (match_word (keyword, subr, &old_locus) == MATCH_YES) \
- return st; \
- else \
- undo_new_statement (); \
- } while (0);
- /* This is a specialist version of decode_statement that is used
- for the specification statements in a function, whose
- characteristics are deferred into the specification statements.
- eg.: INTEGER (king = mykind) foo ()
- USE mymodule, ONLY mykind.....
- The KIND parameter needs a return after USE or IMPORT, whereas
- derived type declarations can occur anywhere, up the executable
- block. ST_GET_FCN_CHARACTERISTICS is returned when we have run
- out of the correct kind of specification statements. */
- static gfc_statement
- decode_specification_statement (void)
- {
- gfc_statement st;
- locus old_locus;
- char c;
- if (gfc_match_eos () == MATCH_YES)
- return ST_NONE;
- old_locus = gfc_current_locus;
- if (match_word ("use", gfc_match_use, &old_locus) == MATCH_YES)
- {
- last_was_use_stmt = true;
- return ST_USE;
- }
- else
- {
- undo_new_statement ();
- if (last_was_use_stmt)
- use_modules ();
- }
- match ("import", gfc_match_import, ST_IMPORT);
- if (gfc_current_block ()->result->ts.type != BT_DERIVED)
- goto end_of_block;
- match (NULL, gfc_match_st_function, ST_STATEMENT_FUNCTION);
- match (NULL, gfc_match_data_decl, ST_DATA_DECL);
- match (NULL, gfc_match_enumerator_def, ST_ENUMERATOR);
- /* General statement matching: Instead of testing every possible
- statement, we eliminate most possibilities by peeking at the
- first character. */
- c = gfc_peek_ascii_char ();
- switch (c)
- {
- case 'a':
- match ("abstract% interface", gfc_match_abstract_interface,
- ST_INTERFACE);
- match ("allocatable", gfc_match_allocatable, ST_ATTR_DECL);
- match ("asynchronous", gfc_match_asynchronous, ST_ATTR_DECL);
- break;
- case 'b':
- match (NULL, gfc_match_bind_c_stmt, ST_ATTR_DECL);
- break;
- case 'c':
- match ("codimension", gfc_match_codimension, ST_ATTR_DECL);
- match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
- break;
- case 'd':
- match ("data", gfc_match_data, ST_DATA);
- match ("dimension", gfc_match_dimension, ST_ATTR_DECL);
- break;
- case 'e':
- match ("enum , bind ( c )", gfc_match_enum, ST_ENUM);
- match ("entry% ", gfc_match_entry, ST_ENTRY);
- match ("equivalence", gfc_match_equivalence, ST_EQUIVALENCE);
- match ("external", gfc_match_external, ST_ATTR_DECL);
- break;
- case 'f':
- match ("format", gfc_match_format, ST_FORMAT);
- break;
- case 'g':
- break;
- case 'i':
- match ("implicit", gfc_match_implicit, ST_IMPLICIT);
- match ("implicit% none", gfc_match_implicit_none, ST_IMPLICIT_NONE);
- match ("interface", gfc_match_interface, ST_INTERFACE);
- match ("intent", gfc_match_intent, ST_ATTR_DECL);
- match ("intrinsic", gfc_match_intrinsic, ST_ATTR_DECL);
- break;
- case 'm':
- break;
- case 'n':
- match ("namelist", gfc_match_namelist, ST_NAMELIST);
- break;
- case 'o':
- match ("optional", gfc_match_optional, ST_ATTR_DECL);
- break;
- case 'p':
- match ("parameter", gfc_match_parameter, ST_PARAMETER);
- match ("pointer", gfc_match_pointer, ST_ATTR_DECL);
- if (gfc_match_private (&st) == MATCH_YES)
- return st;
- match ("procedure", gfc_match_procedure, ST_PROCEDURE);
- if (gfc_match_public (&st) == MATCH_YES)
- return st;
- match ("protected", gfc_match_protected, ST_ATTR_DECL);
- break;
- case 'r':
- break;
- case 's':
- match ("save", gfc_match_save, ST_ATTR_DECL);
- break;
- case 't':
- match ("target", gfc_match_target, ST_ATTR_DECL);
- match ("type", gfc_match_derived_decl, ST_DERIVED_DECL);
- break;
- case 'u':
- break;
- case 'v':
- match ("value", gfc_match_value, ST_ATTR_DECL);
- match ("volatile", gfc_match_volatile, ST_ATTR_DECL);
- break;
- case 'w':
- break;
- }
- /* This is not a specification statement. See if any of the matchers
- has stored an error message of some sort. */
- end_of_block:
- gfc_clear_error ();
- gfc_buffer_error (false);
- gfc_current_locus = old_locus;
- return ST_GET_FCN_CHARACTERISTICS;
- }
- /* This is the primary 'decode_statement'. */
- static gfc_statement
- decode_statement (void)
- {
- gfc_namespace *ns;
- gfc_statement st;
- locus old_locus;
- match m;
- char c;
- gfc_enforce_clean_symbol_state ();
- gfc_clear_error (); /* Clear any pending errors. */
- gfc_clear_warning (); /* Clear any pending warnings. */
- gfc_matching_function = false;
- if (gfc_match_eos () == MATCH_YES)
- return ST_NONE;
- if (gfc_current_state () == COMP_FUNCTION
- && gfc_current_block ()->result->ts.kind == -1)
- return decode_specification_statement ();
- old_locus = gfc_current_locus;
- c = gfc_peek_ascii_char ();
- if (c == 'u')
- {
- if (match_word ("use", gfc_match_use, &old_locus) == MATCH_YES)
- {
- last_was_use_stmt = true;
- return ST_USE;
- }
- else
- undo_new_statement ();
- }
- if (last_was_use_stmt)
- use_modules ();
- /* Try matching a data declaration or function declaration. The
- input "REALFUNCTIONA(N)" can mean several things in different
- contexts, so it (and its relatives) get special treatment. */
- if (gfc_current_state () == COMP_NONE
- || gfc_current_state () == COMP_INTERFACE
- || gfc_current_state () == COMP_CONTAINS)
- {
- gfc_matching_function = true;
- m = gfc_match_function_decl ();
- if (m == MATCH_YES)
- return ST_FUNCTION;
- else if (m == MATCH_ERROR)
- reject_statement ();
- else
- gfc_undo_symbols ();
- gfc_current_locus = old_locus;
- }
- gfc_matching_function = false;
- /* Match statements whose error messages are meant to be overwritten
- by something better. */
- match (NULL, gfc_match_assignment, ST_ASSIGNMENT);
- match (NULL, gfc_match_pointer_assignment, ST_POINTER_ASSIGNMENT);
- match (NULL, gfc_match_st_function, ST_STATEMENT_FUNCTION);
- match (NULL, gfc_match_data_decl, ST_DATA_DECL);
- match (NULL, gfc_match_enumerator_def, ST_ENUMERATOR);
- /* Try to match a subroutine statement, which has the same optional
- prefixes that functions can have. */
- if (gfc_match_subroutine () == MATCH_YES)
- return ST_SUBROUTINE;
- gfc_undo_symbols ();
- gfc_current_locus = old_locus;
- /* Check for the IF, DO, SELECT, WHERE, FORALL, CRITICAL, BLOCK and ASSOCIATE
- statements, which might begin with a block label. The match functions for
- these statements are unusual in that their keyword is not seen before
- the matcher is called. */
- if (gfc_match_if (&st) == MATCH_YES)
- return st;
- gfc_undo_symbols ();
- gfc_current_locus = old_locus;
- if (gfc_match_where (&st) == MATCH_YES)
- return st;
- gfc_undo_symbols ();
- gfc_current_locus = old_locus;
- if (gfc_match_forall (&st) == MATCH_YES)
- return st;
- gfc_undo_symbols ();
- gfc_current_locus = old_locus;
- match (NULL, gfc_match_do, ST_DO);
- match (NULL, gfc_match_block, ST_BLOCK);
- match (NULL, gfc_match_associate, ST_ASSOCIATE);
- match (NULL, gfc_match_critical, ST_CRITICAL);
- match (NULL, gfc_match_select, ST_SELECT_CASE);
- gfc_current_ns = gfc_build_block_ns (gfc_current_ns);
- match (NULL, gfc_match_select_type, ST_SELECT_TYPE);
- ns = gfc_current_ns;
- gfc_current_ns = gfc_current_ns->parent;
- gfc_free_namespace (ns);
- /* General statement matching: Instead of testing every possible
- statement, we eliminate most possibilities by peeking at the
- first character. */
- switch (c)
- {
- case 'a':
- match ("abstract% interface", gfc_match_abstract_interface,
- ST_INTERFACE);
- match ("allocate", gfc_match_allocate, ST_ALLOCATE);
- match ("allocatable", gfc_match_allocatable, ST_ATTR_DECL);
- match ("assign", gfc_match_assign, ST_LABEL_ASSIGNMENT);
- match ("asynchronous", gfc_match_asynchronous, ST_ATTR_DECL);
- break;
- case 'b':
- match ("backspace", gfc_match_backspace, ST_BACKSPACE);
- match ("block data", gfc_match_block_data, ST_BLOCK_DATA);
- match (NULL, gfc_match_bind_c_stmt, ST_ATTR_DECL);
- break;
- case 'c':
- match ("call", gfc_match_call, ST_CALL);
- match ("close", gfc_match_close, ST_CLOSE);
- match ("continue", gfc_match_continue, ST_CONTINUE);
- match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
- match ("cycle", gfc_match_cycle, ST_CYCLE);
- match ("case", gfc_match_case, ST_CASE);
- match ("common", gfc_match_common, ST_COMMON);
- match ("contains", gfc_match_eos, ST_CONTAINS);
- match ("class", gfc_match_class_is, ST_CLASS_IS);
- match ("codimension", gfc_match_codimension, ST_ATTR_DECL);
- break;
- case 'd':
- match ("deallocate", gfc_match_deallocate, ST_DEALLOCATE);
- match ("data", gfc_match_data, ST_DATA);
- match ("dimension", gfc_match_dimension, ST_ATTR_DECL);
- break;
- case 'e':
- match ("end file", gfc_match_endfile, ST_END_FILE);
- match ("exit", gfc_match_exit, ST_EXIT);
- match ("else", gfc_match_else, ST_ELSE);
- match ("else where", gfc_match_elsewhere, ST_ELSEWHERE);
- match ("else if", gfc_match_elseif, ST_ELSEIF);
- match ("error stop", gfc_match_error_stop, ST_ERROR_STOP);
- match ("enum , bind ( c )", gfc_match_enum, ST_ENUM);
- if (gfc_match_end (&st) == MATCH_YES)
- return st;
- match ("entry% ", gfc_match_entry, ST_ENTRY);
- match ("equivalence", gfc_match_equivalence, ST_EQUIVALENCE);
- match ("external", gfc_match_external, ST_ATTR_DECL);
- break;
- case 'f':
- match ("final", gfc_match_final_decl, ST_FINAL);
- match ("flush", gfc_match_flush, ST_FLUSH);
- match ("format", gfc_match_format, ST_FORMAT);
- break;
- case 'g':
- match ("generic", gfc_match_generic, ST_GENERIC);
- match ("go to", gfc_match_goto, ST_GOTO);
- break;
- case 'i':
- match ("inquire", gfc_match_inquire, ST_INQUIRE);
- match ("implicit", gfc_match_implicit, ST_IMPLICIT);
- match ("implicit% none", gfc_match_implicit_none, ST_IMPLICIT_NONE);
- match ("import", gfc_match_import, ST_IMPORT);
- match ("interface", gfc_match_interface, ST_INTERFACE);
- match ("intent", gfc_match_intent, ST_ATTR_DECL);
- match ("intrinsic", gfc_match_intrinsic, ST_ATTR_DECL);
- break;
- case 'l':
- match ("lock", gfc_match_lock, ST_LOCK);
- break;
- case 'm':
- match ("module% procedure", gfc_match_modproc, ST_MODULE_PROC);
- match ("module", gfc_match_module, ST_MODULE);
- break;
- case 'n':
- match ("nullify", gfc_match_nullify, ST_NULLIFY);
- match ("namelist", gfc_match_namelist, ST_NAMELIST);
- break;
- case 'o':
- match ("open", gfc_match_open, ST_OPEN);
- match ("optional", gfc_match_optional, ST_ATTR_DECL);
- break;
- case 'p':
- match ("print", gfc_match_print, ST_WRITE);
- match ("parameter", gfc_match_parameter, ST_PARAMETER);
- match ("pause", gfc_match_pause, ST_PAUSE);
- match ("pointer", gfc_match_pointer, ST_ATTR_DECL);
- if (gfc_match_private (&st) == MATCH_YES)
- return st;
- match ("procedure", gfc_match_procedure, ST_PROCEDURE);
- match ("program", gfc_match_program, ST_PROGRAM);
- if (gfc_match_public (&st) == MATCH_YES)
- return st;
- match ("protected", gfc_match_protected, ST_ATTR_DECL);
- break;
- case 'r':
- match ("read", gfc_match_read, ST_READ);
- match ("return", gfc_match_return, ST_RETURN);
- match ("rewind", gfc_match_rewind, ST_REWIND);
- break;
- case 's':
- match ("sequence", gfc_match_eos, ST_SEQUENCE);
- match ("stop", gfc_match_stop, ST_STOP);
- match ("save", gfc_match_save, ST_ATTR_DECL);
- match ("sync all", gfc_match_sync_all, ST_SYNC_ALL);
- match ("sync images", gfc_match_sync_images, ST_SYNC_IMAGES);
- match ("sync memory", gfc_match_sync_memory, ST_SYNC_MEMORY);
- break;
- case 't':
- match ("target", gfc_match_target, ST_ATTR_DECL);
- match ("type", gfc_match_derived_decl, ST_DERIVED_DECL);
- match ("type is", gfc_match_type_is, ST_TYPE_IS);
- break;
- case 'u':
- match ("unlock", gfc_match_unlock, ST_UNLOCK);
- break;
- case 'v':
- match ("value", gfc_match_value, ST_ATTR_DECL);
- match ("volatile", gfc_match_volatile, ST_ATTR_DECL);
- break;
- case 'w':
- match ("wait", gfc_match_wait, ST_WAIT);
- match ("write", gfc_match_write, ST_WRITE);
- break;
- }
- /* All else has failed, so give up. See if any of the matchers has
- stored an error message of some sort. */
- if (!gfc_error_check ())
- gfc_error_now ("Unclassifiable statement at %C");
- reject_statement ();
- gfc_error_recovery ();
- return ST_NONE;
- }
- /* Like match, but set a flag simd_matched if keyword matched. */
- #define matchs(keyword, subr, st) \
- do { \
- if (match_word_omp_simd (keyword, subr, &old_locus, \
- &simd_matched) == MATCH_YES) \
- return st; \
- else \
- undo_new_statement (); \
- } while (0);
- /* Like match, but don't match anything if not -fopenmp. */
- #define matcho(keyword, subr, st) \
- do { \
- if (!flag_openmp) \
- ; \
- else if (match_word (keyword, subr, &old_locus) \
- == MATCH_YES) \
- return st; \
- else \
- undo_new_statement (); \
- } while (0);
- static gfc_statement
- decode_oacc_directive (void)
- {
- locus old_locus;
- char c;
- gfc_enforce_clean_symbol_state ();
- gfc_clear_error (); /* Clear any pending errors. */
- gfc_clear_warning (); /* Clear any pending warnings. */
- if (gfc_pure (NULL))
- {
- gfc_error_now ("OpenACC directives at %C may not appear in PURE "
- "procedures");
- gfc_error_recovery ();
- return ST_NONE;
- }
- gfc_unset_implicit_pure (NULL);
- old_locus = gfc_current_locus;
- /* General OpenACC directive matching: Instead of testing every possible
- statement, we eliminate most possibilities by peeking at the
- first character. */
- c = gfc_peek_ascii_char ();
- switch (c)
- {
- case 'c':
- match ("cache", gfc_match_oacc_cache, ST_OACC_CACHE);
- break;
- case 'd':
- match ("data", gfc_match_oacc_data, ST_OACC_DATA);
- match ("declare", gfc_match_oacc_declare, ST_OACC_DECLARE);
- break;
- case 'e':
- match ("end data", gfc_match_omp_eos, ST_OACC_END_DATA);
- match ("end host_data", gfc_match_omp_eos, ST_OACC_END_HOST_DATA);
- match ("end kernels loop", gfc_match_omp_eos, ST_OACC_END_KERNELS_LOOP);
- match ("end kernels", gfc_match_omp_eos, ST_OACC_END_KERNELS);
- match ("end loop", gfc_match_omp_eos, ST_OACC_END_LOOP);
- match ("end parallel loop", gfc_match_omp_eos, ST_OACC_END_PARALLEL_LOOP);
- match ("end parallel", gfc_match_omp_eos, ST_OACC_END_PARALLEL);
- match ("enter data", gfc_match_oacc_enter_data, ST_OACC_ENTER_DATA);
- match ("exit data", gfc_match_oacc_exit_data, ST_OACC_EXIT_DATA);
- break;
- case 'h':
- match ("host_data", gfc_match_oacc_host_data, ST_OACC_HOST_DATA);
- break;
- case 'p':
- match ("parallel loop", gfc_match_oacc_parallel_loop, ST_OACC_PARALLEL_LOOP);
- match ("parallel", gfc_match_oacc_parallel, ST_OACC_PARALLEL);
- break;
- case 'k':
- match ("kernels loop", gfc_match_oacc_kernels_loop, ST_OACC_KERNELS_LOOP);
- match ("kernels", gfc_match_oacc_kernels, ST_OACC_KERNELS);
- break;
- case 'l':
- match ("loop", gfc_match_oacc_loop, ST_OACC_LOOP);
- break;
- case 'r':
- match ("routine", gfc_match_oacc_routine, ST_OACC_ROUTINE);
- break;
- case 'u':
- match ("update", gfc_match_oacc_update, ST_OACC_UPDATE);
- break;
- case 'w':
- match ("wait", gfc_match_oacc_wait, ST_OACC_WAIT);
- break;
- }
- /* Directive not found or stored an error message.
- Check and give up. */
- if (gfc_error_check () == 0)
- gfc_error_now ("Unclassifiable OpenACC directive at %C");
- reject_statement ();
- gfc_error_recovery ();
- return ST_NONE;
- }
- static gfc_statement
- decode_omp_directive (void)
- {
- locus old_locus;
- char c;
- bool simd_matched = false;
- gfc_enforce_clean_symbol_state ();
- gfc_clear_error (); /* Clear any pending errors. */
- gfc_clear_warning (); /* Clear any pending warnings. */
- if (gfc_pure (NULL))
- {
- gfc_error_now ("OpenMP directives at %C may not appear in PURE "
- "or ELEMENTAL procedures");
- gfc_error_recovery ();
- return ST_NONE;
- }
- gfc_unset_implicit_pure (NULL);
- old_locus = gfc_current_locus;
- /* General OpenMP directive matching: Instead of testing every possible
- statement, we eliminate most possibilities by peeking at the
- first character. */
- c = gfc_peek_ascii_char ();
- /* match is for directives that should be recognized only if
- -fopenmp, matchs for directives that should be recognized
- if either -fopenmp or -fopenmp-simd. */
- switch (c)
- {
- case 'a':
- matcho ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC);
- break;
- case 'b':
- matcho ("barrier", gfc_match_omp_barrier, ST_OMP_BARRIER);
- break;
- case 'c':
- matcho ("cancellation% point", gfc_match_omp_cancellation_point,
- ST_OMP_CANCELLATION_POINT);
- matcho ("cancel", gfc_match_omp_cancel, ST_OMP_CANCEL);
- matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
- break;
- case 'd':
- matchs ("declare reduction", gfc_match_omp_declare_reduction,
- ST_OMP_DECLARE_REDUCTION);
- matchs ("declare simd", gfc_match_omp_declare_simd,
- ST_OMP_DECLARE_SIMD);
- matcho ("declare target", gfc_match_omp_declare_target,
- ST_OMP_DECLARE_TARGET);
- matchs ("distribute parallel do simd",
- gfc_match_omp_distribute_parallel_do_simd,
- ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD);
- matcho ("distribute parallel do", gfc_match_omp_distribute_parallel_do,
- ST_OMP_DISTRIBUTE_PARALLEL_DO);
- matchs ("distribute simd", gfc_match_omp_distribute_simd,
- ST_OMP_DISTRIBUTE_SIMD);
- matcho ("distribute", gfc_match_omp_distribute, ST_OMP_DISTRIBUTE);
- matchs ("do simd", gfc_match_omp_do_simd, ST_OMP_DO_SIMD);
- matcho ("do", gfc_match_omp_do, ST_OMP_DO);
- break;
- case 'e':
- matcho ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC);
- matcho ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL);
- matchs ("end distribute parallel do simd", gfc_match_omp_eos,
- ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD);
- matcho ("end distribute parallel do", gfc_match_omp_eos,
- ST_OMP_END_DISTRIBUTE_PARALLEL_DO);
- matchs ("end distribute simd", gfc_match_omp_eos,
- ST_OMP_END_DISTRIBUTE_SIMD);
- matcho ("end distribute", gfc_match_omp_eos, ST_OMP_END_DISTRIBUTE);
- matchs ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD);
- matcho ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
- matchs ("end simd", gfc_match_omp_eos, ST_OMP_END_SIMD);
- matcho ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER);
- matcho ("end ordered", gfc_match_omp_eos, ST_OMP_END_ORDERED);
- matchs ("end parallel do simd", gfc_match_omp_eos,
- ST_OMP_END_PARALLEL_DO_SIMD);
- matcho ("end parallel do", gfc_match_omp_eos, ST_OMP_END_PARALLEL_DO);
- matcho ("end parallel sections", gfc_match_omp_eos,
- ST_OMP_END_PARALLEL_SECTIONS);
- matcho ("end parallel workshare", gfc_match_omp_eos,
- ST_OMP_END_PARALLEL_WORKSHARE);
- matcho ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL);
- matcho ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS);
- matcho ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE);
- matcho ("end target data", gfc_match_omp_eos, ST_OMP_END_TARGET_DATA);
- matchs ("end target teams distribute parallel do simd",
- gfc_match_omp_eos,
- ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
- matcho ("end target teams distribute parallel do", gfc_match_omp_eos,
- ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO);
- matchs ("end target teams distribute simd", gfc_match_omp_eos,
- ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD);
- matcho ("end target teams distribute", gfc_match_omp_eos,
- ST_OMP_END_TARGET_TEAMS_DISTRIBUTE);
- matcho ("end target teams", gfc_match_omp_eos, ST_OMP_END_TARGET_TEAMS);
- matcho ("end target", gfc_match_omp_eos, ST_OMP_END_TARGET);
- matcho ("end taskgroup", gfc_match_omp_eos, ST_OMP_END_TASKGROUP);
- matcho ("end task", gfc_match_omp_eos, ST_OMP_END_TASK);
- matchs ("end teams distribute parallel do simd", gfc_match_omp_eos,
- ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
- matcho ("end teams distribute parallel do", gfc_match_omp_eos,
- ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO);
- matchs ("end teams distribute simd", gfc_match_omp_eos,
- ST_OMP_END_TEAMS_DISTRIBUTE_SIMD);
- matcho ("end teams distribute", gfc_match_omp_eos,
- ST_OMP_END_TEAMS_DISTRIBUTE);
- matcho ("end teams", gfc_match_omp_eos, ST_OMP_END_TEAMS);
- matcho ("end workshare", gfc_match_omp_end_nowait,
- ST_OMP_END_WORKSHARE);
- break;
- case 'f':
- matcho ("flush", gfc_match_omp_flush, ST_OMP_FLUSH);
- break;
- case 'm':
- matcho ("master", gfc_match_omp_master, ST_OMP_MASTER);
- break;
- case 'o':
- matcho ("ordered", gfc_match_omp_ordered, ST_OMP_ORDERED);
- break;
- case 'p':
- matchs ("parallel do simd", gfc_match_omp_parallel_do_simd,
- ST_OMP_PARALLEL_DO_SIMD);
- matcho ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO);
- matcho ("parallel sections", gfc_match_omp_parallel_sections,
- ST_OMP_PARALLEL_SECTIONS);
- matcho ("parallel workshare", gfc_match_omp_parallel_workshare,
- ST_OMP_PARALLEL_WORKSHARE);
- matcho ("parallel", gfc_match_omp_parallel, ST_OMP_PARALLEL);
- break;
- case 's':
- matcho ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS);
- matcho ("section", gfc_match_omp_eos, ST_OMP_SECTION);
- matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
- matcho ("single", gfc_match_omp_single, ST_OMP_SINGLE);
- break;
- case 't':
- matcho ("target data", gfc_match_omp_target_data, ST_OMP_TARGET_DATA);
- matchs ("target teams distribute parallel do simd",
- gfc_match_omp_target_teams_distribute_parallel_do_simd,
- ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
- matcho ("target teams distribute parallel do",
- gfc_match_omp_target_teams_distribute_parallel_do,
- ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO);
- matchs ("target teams distribute simd",
- gfc_match_omp_target_teams_distribute_simd,
- ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD);
- matcho ("target teams distribute", gfc_match_omp_target_teams_distribute,
- ST_OMP_TARGET_TEAMS_DISTRIBUTE);
- matcho ("target teams", gfc_match_omp_target_teams, ST_OMP_TARGET_TEAMS);
- matcho ("target update", gfc_match_omp_target_update,
- ST_OMP_TARGET_UPDATE);
- matcho ("target", gfc_match_omp_target, ST_OMP_TARGET);
- matcho ("taskgroup", gfc_match_omp_taskgroup, ST_OMP_TASKGROUP);
- matcho ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
- matcho ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
- matcho ("task", gfc_match_omp_task, ST_OMP_TASK);
- matchs ("teams distribute parallel do simd",
- gfc_match_omp_teams_distribute_parallel_do_simd,
- ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
- matcho ("teams distribute parallel do",
- gfc_match_omp_teams_distribute_parallel_do,
- ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO);
- matchs ("teams distribute simd", gfc_match_omp_teams_distribute_simd,
- ST_OMP_TEAMS_DISTRIBUTE_SIMD);
- matcho ("teams distribute", gfc_match_omp_teams_distribute,
- ST_OMP_TEAMS_DISTRIBUTE);
- matcho ("teams", gfc_match_omp_teams, ST_OMP_TEAMS);
- matcho ("threadprivate", gfc_match_omp_threadprivate,
- ST_OMP_THREADPRIVATE);
- break;
- case 'w':
- matcho ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE);
- break;
- }
- /* All else has failed, so give up. See if any of the matchers has
- stored an error message of some sort. Don't error out if
- not -fopenmp and simd_matched is false, i.e. if a directive other
- than one marked with match has been seen. */
- if (flag_openmp || simd_matched)
- {
- if (!gfc_error_check ())
- gfc_error_now ("Unclassifiable OpenMP directive at %C");
- }
- reject_statement ();
- gfc_error_recovery ();
- return ST_NONE;
- }
- static gfc_statement
- decode_gcc_attribute (void)
- {
- locus old_locus;
- gfc_enforce_clean_symbol_state ();
- gfc_clear_error (); /* Clear any pending errors. */
- gfc_clear_warning (); /* Clear any pending warnings. */
- old_locus = gfc_current_locus;
- match ("attributes", gfc_match_gcc_attributes, ST_ATTR_DECL);
- /* All else has failed, so give up. See if any of the matchers has
- stored an error message of some sort. */
- if (!gfc_error_check ())
- gfc_error_now ("Unclassifiable GCC directive at %C");
- reject_statement ();
- gfc_error_recovery ();
- return ST_NONE;
- }
- #undef match
- /* Assert next length characters to be equal to token in free form. */
- static void
- verify_token_free (const char* token, int length, bool last_was_use_stmt)
- {
- int i;
- char c;
- c = gfc_next_ascii_char ();
- for (i = 0; i < length; i++, c = gfc_next_ascii_char ())
- gcc_assert (c == token[i]);
- gcc_assert (gfc_is_whitespace(c));
- gfc_gobble_whitespace ();
- if (last_was_use_stmt)
- use_modules ();
- }
- /* Get the next statement in free form source. */
- static gfc_statement
- next_free (void)
- {
- match m;
- int i, cnt, at_bol;
- char c;
- at_bol = gfc_at_bol ();
- gfc_gobble_whitespace ();
- c = gfc_peek_ascii_char ();
- if (ISDIGIT (c))
- {
- char d;
- /* Found a statement label? */
- m = gfc_match_st_label (&gfc_statement_label);
- d = gfc_peek_ascii_char ();
- if (m != MATCH_YES || !gfc_is_whitespace (d))
- {
- gfc_match_small_literal_int (&i, &cnt);
- if (cnt > 5)
- gfc_error_now ("Too many digits in statement label at %C");
- if (i == 0)
- gfc_error_now ("Zero is not a valid statement label at %C");
- do
- c = gfc_next_ascii_char ();
- while (ISDIGIT(c));
- if (!gfc_is_whitespace (c))
- gfc_error_now ("Non-numeric character in statement label at %C");
- return ST_NONE;
- }
- else
- {
- label_locus = gfc_current_locus;
- gfc_gobble_whitespace ();
- if (at_bol && gfc_peek_ascii_char () == ';')
- {
- gfc_error_now ("Semicolon at %C needs to be preceded by "
- "statement");
- gfc_next_ascii_char (); /* Eat up the semicolon. */
- return ST_NONE;
- }
- if (gfc_match_eos () == MATCH_YES)
- {
- gfc_warning_now (0, "Ignoring statement label in empty statement "
- "at %L", &label_locus);
- gfc_free_st_label (gfc_statement_label);
- gfc_statement_label = NULL;
- return ST_NONE;
- }
- }
- }
- else if (c == '!')
- {
- /* Comments have already been skipped by the time we get here,
- except for GCC attributes and OpenMP/OpenACC directives. */
- gfc_next_ascii_char (); /* Eat up the exclamation sign. */
- c = gfc_peek_ascii_char ();
- if (c == 'g')
- {
- int i;
- c = gfc_next_ascii_char ();
- for (i = 0; i < 4; i++, c = gfc_next_ascii_char ())
- gcc_assert (c == "gcc$"[i]);
- gfc_gobble_whitespace ();
- return decode_gcc_attribute ();
- }
- else if (c == '$')
- {
- /* Since both OpenMP and OpenACC directives starts with
- !$ character sequence, we must check all flags combinations */
- if ((flag_openmp || flag_openmp_simd)
- && !flag_openacc)
- {
- verify_token_free ("$omp", 4, last_was_use_stmt);
- return decode_omp_directive ();
- }
- else if ((flag_openmp || flag_openmp_simd)
- && flag_openacc)
- {
- gfc_next_ascii_char (); /* Eat up dollar character */
- c = gfc_peek_ascii_char ();
- if (c == 'o')
- {
- verify_token_free ("omp", 3, last_was_use_stmt);
- return decode_omp_directive ();
- }
- else if (c == 'a')
- {
- verify_token_free ("acc", 3, last_was_use_stmt);
- return decode_oacc_directive ();
- }
- }
- else if (flag_openacc)
- {
- verify_token_free ("$acc", 4, last_was_use_stmt);
- return decode_oacc_directive ();
- }
- }
- gcc_unreachable ();
- }
-
- if (at_bol && c == ';')
- {
- if (!(gfc_option.allow_std & GFC_STD_F2008))
- gfc_error_now ("Fortran 2008: Semicolon at %C without preceding "
- "statement");
- gfc_next_ascii_char (); /* Eat up the semicolon. */
- return ST_NONE;
- }
- return decode_statement ();
- }
- /* Assert next length characters to be equal to token in fixed form. */
- static bool
- verify_token_fixed (const char *token, int length, bool last_was_use_stmt)
- {
- int i;
- char c = gfc_next_char_literal (NONSTRING);
- for (i = 0; i < length; i++, c = gfc_next_char_literal (NONSTRING))
- gcc_assert ((char) gfc_wide_tolower (c) == token[i]);
- if (c != ' ' && c != '0')
- {
- gfc_buffer_error (false);
- gfc_error ("Bad continuation line at %C");
- return false;
- }
- if (last_was_use_stmt)
- use_modules ();
- return true;
- }
- /* Get the next statement in fixed-form source. */
- static gfc_statement
- next_fixed (void)
- {
- int label, digit_flag, i;
- locus loc;
- gfc_char_t c;
- if (!gfc_at_bol ())
- return decode_statement ();
- /* Skip past the current label field, parsing a statement label if
- one is there. This is a weird number parser, since the number is
- contained within five columns and can have any kind of embedded
- spaces. We also check for characters that make the rest of the
- line a comment. */
- label = 0;
- digit_flag = 0;
- for (i = 0; i < 5; i++)
- {
- c = gfc_next_char_literal (NONSTRING);
- switch (c)
- {
- case ' ':
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- label = label * 10 + ((unsigned char) c - '0');
- label_locus = gfc_current_locus;
- digit_flag = 1;
- break;
- /* Comments have already been skipped by the time we get
- here, except for GCC attributes and OpenMP directives. */
- case '*':
- c = gfc_next_char_literal (NONSTRING);
-
- if (TOLOWER (c) == 'g')
- {
- for (i = 0; i < 4; i++, c = gfc_next_char_literal (NONSTRING))
- gcc_assert (TOLOWER (c) == "gcc$"[i]);
- return decode_gcc_attribute ();
- }
- else if (c == '$')
- {
- if ((flag_openmp || flag_openmp_simd)
- && !flag_openacc)
- {
- if (!verify_token_fixed ("omp", 3, last_was_use_stmt))
- return ST_NONE;
- return decode_omp_directive ();
- }
- else if ((flag_openmp || flag_openmp_simd)
- && flag_openacc)
- {
- c = gfc_next_char_literal(NONSTRING);
- if (c == 'o' || c == 'O')
- {
- if (!verify_token_fixed ("mp", 2, last_was_use_stmt))
- return ST_NONE;
- return decode_omp_directive ();
- }
- else if (c == 'a' || c == 'A')
- {
- if (!verify_token_fixed ("cc", 2, last_was_use_stmt))
- return ST_NONE;
- return decode_oacc_directive ();
- }
- }
- else if (flag_openacc)
- {
- if (!verify_token_fixed ("acc", 3, last_was_use_stmt))
- return ST_NONE;
- return decode_oacc_directive ();
- }
- }
- /* FALLTHROUGH */
- /* Comments have already been skipped by the time we get
- here so don't bother checking for them. */
- default:
- gfc_buffer_error (false);
- gfc_error ("Non-numeric character in statement label at %C");
- return ST_NONE;
- }
- }
- if (digit_flag)
- {
- if (label == 0)
- gfc_warning_now (0, "Zero is not a valid statement label at %C");
- else
- {
- /* We've found a valid statement label. */
- gfc_statement_label = gfc_get_st_label (label);
- }
- }
- /* Since this line starts a statement, it cannot be a continuation
- of a previous statement. If we see something here besides a
- space or zero, it must be a bad continuation line. */
- c = gfc_next_char_literal (NONSTRING);
- if (c == '\n')
- goto blank_line;
- if (c != ' ' && c != '0')
- {
- gfc_buffer_error (false);
- gfc_error ("Bad continuation line at %C");
- return ST_NONE;
- }
- /* Now that we've taken care of the statement label columns, we have
- to make sure that the first nonblank character is not a '!'. If
- it is, the rest of the line is a comment. */
- do
- {
- loc = gfc_current_locus;
- c = gfc_next_char_literal (NONSTRING);
- }
- while (gfc_is_whitespace (c));
- if (c == '!')
- goto blank_line;
- gfc_current_locus = loc;
- if (c == ';')
- {
- if (digit_flag)
- gfc_error_now ("Semicolon at %C needs to be preceded by statement");
- else if (!(gfc_option.allow_std & GFC_STD_F2008))
- gfc_error_now ("Fortran 2008: Semicolon at %C without preceding "
- "statement");
- return ST_NONE;
- }
- if (gfc_match_eos () == MATCH_YES)
- goto blank_line;
- /* At this point, we've got a nonblank statement to parse. */
- return decode_statement ();
- blank_line:
- if (digit_flag)
- gfc_warning_now (0, "Ignoring statement label in empty statement at %L",
- &label_locus);
-
- gfc_current_locus.lb->truncated = 0;
- gfc_advance_line ();
- return ST_NONE;
- }
- /* Return the next non-ST_NONE statement to the caller. We also worry
- about including files and the ends of include files at this stage. */
- static gfc_statement
- next_statement (void)
- {
- gfc_statement st;
- locus old_locus;
- gfc_enforce_clean_symbol_state ();
- gfc_new_block = NULL;
- gfc_current_ns->old_cl_list = gfc_current_ns->cl_list;
- gfc_current_ns->old_equiv = gfc_current_ns->equiv;
- gfc_current_ns->old_data = gfc_current_ns->data;
- for (;;)
- {
- gfc_statement_label = NULL;
- gfc_buffer_error (true);
- if (gfc_at_eol ())
- gfc_advance_line ();
- gfc_skip_comments ();
- if (gfc_at_end ())
- {
- st = ST_NONE;
- break;
- }
- if (gfc_define_undef_line ())
- continue;
- old_locus = gfc_current_locus;
- st = (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free ();
- if (st != ST_NONE)
- break;
- }
- gfc_buffer_error (false);
- if (st == ST_GET_FCN_CHARACTERISTICS && gfc_statement_label != NULL)
- {
- gfc_free_st_label (gfc_statement_label);
- gfc_statement_label = NULL;
- gfc_current_locus = old_locus;
- }
- if (st != ST_NONE)
- check_statement_label (st);
- return st;
- }
- /****************************** Parser ***********************************/
- /* The parser subroutines are of type 'try' that fail if the file ends
- unexpectedly. */
- /* Macros that expand to case-labels for various classes of
- statements. Start with executable statements that directly do
- things. */
- #define case_executable case ST_ALLOCATE: case ST_BACKSPACE: case ST_CALL: \
- case ST_CLOSE: case ST_CONTINUE: case ST_DEALLOCATE: case ST_END_FILE: \
- case ST_GOTO: case ST_INQUIRE: case ST_NULLIFY: case ST_OPEN: \
- case ST_READ: case ST_RETURN: case ST_REWIND: case ST_SIMPLE_IF: \
- case ST_PAUSE: case ST_STOP: case ST_WAIT: case ST_WRITE: \
- case ST_POINTER_ASSIGNMENT: case ST_EXIT: case ST_CYCLE: \
- case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
- case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
- case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_OMP_TASKYIELD: \
- case ST_OMP_CANCEL: case ST_OMP_CANCELLATION_POINT: \
- case ST_OMP_TARGET_UPDATE: case ST_ERROR_STOP: case ST_SYNC_ALL: \
- case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK: \
- case ST_OACC_UPDATE: case ST_OACC_WAIT: case ST_OACC_CACHE: \
- case ST_OACC_ENTER_DATA: case ST_OACC_EXIT_DATA
- /* Statements that mark other executable statements. */
- #define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \
- case ST_IF_BLOCK: case ST_BLOCK: case ST_ASSOCIATE: \
- case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_SELECT_TYPE: \
- case ST_OMP_PARALLEL: \
- case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \
- case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_SINGLE: \
- case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \
- case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: \
- case ST_OMP_TASK: case ST_OMP_TASKGROUP: case ST_OMP_SIMD: \
- case ST_OMP_DO_SIMD: case ST_OMP_PARALLEL_DO_SIMD: case ST_OMP_TARGET: \
- case ST_OMP_TARGET_DATA: case ST_OMP_TARGET_TEAMS: \
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE: \
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: \
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: \
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: \
- case ST_OMP_TEAMS: case ST_OMP_TEAMS_DISTRIBUTE: \
- case ST_OMP_TEAMS_DISTRIBUTE_SIMD: \
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: \
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case ST_OMP_DISTRIBUTE: \
- case ST_OMP_DISTRIBUTE_SIMD: case ST_OMP_DISTRIBUTE_PARALLEL_DO: \
- case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: \
- case ST_CRITICAL: \
- case ST_OACC_PARALLEL_LOOP: case ST_OACC_PARALLEL: case ST_OACC_KERNELS: \
- case ST_OACC_DATA: case ST_OACC_HOST_DATA: case ST_OACC_LOOP: case ST_OACC_KERNELS_LOOP
- /* Declaration statements */
- #define case_decl case ST_ATTR_DECL: case ST_COMMON: case ST_DATA_DECL: \
- case ST_EQUIVALENCE: case ST_NAMELIST: case ST_STATEMENT_FUNCTION: \
- case ST_TYPE: case ST_INTERFACE: case ST_OMP_THREADPRIVATE: \
- case ST_PROCEDURE: case ST_OMP_DECLARE_SIMD: case ST_OMP_DECLARE_REDUCTION: \
- case ST_OMP_DECLARE_TARGET: case ST_OACC_ROUTINE
- /* Block end statements. Errors associated with interchanging these
- are detected in gfc_match_end(). */
- #define case_end case ST_END_BLOCK_DATA: case ST_END_FUNCTION: \
- case ST_END_PROGRAM: case ST_END_SUBROUTINE: \
- case ST_END_BLOCK: case ST_END_ASSOCIATE
- /* Push a new state onto the stack. */
- static void
- push_state (gfc_state_data *p, gfc_compile_state new_state, gfc_symbol *sym)
- {
- p->state = new_state;
- p->previous = gfc_state_stack;
- p->sym = sym;
- p->head = p->tail = NULL;
- p->do_variable = NULL;
- if (p->state != COMP_DO && p->state != COMP_DO_CONCURRENT)
- p->ext.oacc_declare_clauses = NULL;
- /* If this the state of a construct like BLOCK, DO or IF, the corresponding
- construct statement was accepted right before pushing the state. Thus,
- the construct's gfc_code is available as tail of the parent state. */
- gcc_assert (gfc_state_stack);
- p->construct = gfc_state_stack->tail;
- gfc_state_stack = p;
- }
- /* Pop the current state. */
- static void
- pop_state (void)
- {
- gfc_state_stack = gfc_state_stack->previous;
- }
- /* Try to find the given state in the state stack. */
- bool
- gfc_find_state (gfc_compile_state state)
- {
- gfc_state_data *p;
- for (p = gfc_state_stack; p; p = p->previous)
- if (p->state == state)
- break;
- return (p == NULL) ? false : true;
- }
- /* Starts a new level in the statement list. */
- static gfc_code *
- new_level (gfc_code *q)
- {
- gfc_code *p;
- p = q->block = gfc_get_code (EXEC_NOP);
- gfc_state_stack->head = gfc_state_stack->tail = p;
- return p;
- }
- /* Add the current new_st code structure and adds it to the current
- program unit. As a side-effect, it zeroes the new_st. */
- static gfc_code *
- add_statement (void)
- {
- gfc_code *p;
- p = XCNEW (gfc_code);
- *p = new_st;
- p->loc = gfc_current_locus;
- if (gfc_state_stack->head == NULL)
- gfc_state_stack->head = p;
- else
- gfc_state_stack->tail->next = p;
- while (p->next != NULL)
- p = p->next;
- gfc_state_stack->tail = p;
- gfc_clear_new_st ();
- return p;
- }
- /* Frees everything associated with the current statement. */
- static void
- undo_new_statement (void)
- {
- gfc_free_statements (new_st.block);
- gfc_free_statements (new_st.next);
- gfc_free_statement (&new_st);
- gfc_clear_new_st ();
- }
- /* If the current statement has a statement label, make sure that it
- is allowed to, or should have one. */
- static void
- check_statement_label (gfc_statement st)
- {
- gfc_sl_type type;
- if (gfc_statement_label == NULL)
- {
- if (st == ST_FORMAT)
- gfc_error ("FORMAT statement at %L does not have a statement label",
- &new_st.loc);
- return;
- }
- switch (st)
- {
- case ST_END_PROGRAM:
- case ST_END_FUNCTION:
- case ST_END_SUBROUTINE:
- case ST_ENDDO:
- case ST_ENDIF:
- case ST_END_SELECT:
- case ST_END_CRITICAL:
- case ST_END_BLOCK:
- case ST_END_ASSOCIATE:
- case_executable:
- case_exec_markers:
- if (st == ST_ENDDO || st == ST_CONTINUE)
- type = ST_LABEL_DO_TARGET;
- else
- type = ST_LABEL_TARGET;
- break;
- case ST_FORMAT:
- type = ST_LABEL_FORMAT;
- break;
- /* Statement labels are not restricted from appearing on a
- particular line. However, there are plenty of situations
- where the resulting label can't be referenced. */
- default:
- type = ST_LABEL_BAD_TARGET;
- break;
- }
- gfc_define_st_label (gfc_statement_label, type, &label_locus);
- new_st.here = gfc_statement_label;
- }
- /* Figures out what the enclosing program unit is. This will be a
- function, subroutine, program, block data or module. */
- gfc_state_data *
- gfc_enclosing_unit (gfc_compile_state * result)
- {
- gfc_state_data *p;
- for (p = gfc_state_stack; p; p = p->previous)
- if (p->state == COMP_FUNCTION || p->state == COMP_SUBROUTINE
- || p->state == COMP_MODULE || p->state == COMP_BLOCK_DATA
- || p->state == COMP_PROGRAM)
- {
- if (result != NULL)
- *result = p->state;
- return p;
- }
- if (result != NULL)
- *result = COMP_PROGRAM;
- return NULL;
- }
- /* Translate a statement enum to a string. */
- const char *
- gfc_ascii_statement (gfc_statement st)
- {
- const char *p;
- switch (st)
- {
- case ST_ARITHMETIC_IF:
- p = _("arithmetic IF");
- break;
- case ST_ALLOCATE:
- p = "ALLOCATE";
- break;
- case ST_ASSOCIATE:
- p = "ASSOCIATE";
- break;
- case ST_ATTR_DECL:
- p = _("attribute declaration");
- break;
- case ST_BACKSPACE:
- p = "BACKSPACE";
- break;
- case ST_BLOCK:
- p = "BLOCK";
- break;
- case ST_BLOCK_DATA:
- p = "BLOCK DATA";
- break;
- case ST_CALL:
- p = "CALL";
- break;
- case ST_CASE:
- p = "CASE";
- break;
- case ST_CLOSE:
- p = "CLOSE";
- break;
- case ST_COMMON:
- p = "COMMON";
- break;
- case ST_CONTINUE:
- p = "CONTINUE";
- break;
- case ST_CONTAINS:
- p = "CONTAINS";
- break;
- case ST_CRITICAL:
- p = "CRITICAL";
- break;
- case ST_CYCLE:
- p = "CYCLE";
- break;
- case ST_DATA_DECL:
- p = _("data declaration");
- break;
- case ST_DATA:
- p = "DATA";
- break;
- case ST_DEALLOCATE:
- p = "DEALLOCATE";
- break;
- case ST_DERIVED_DECL:
- p = _("derived type declaration");
- break;
- case ST_DO:
- p = "DO";
- break;
- case ST_ELSE:
- p = "ELSE";
- break;
- case ST_ELSEIF:
- p = "ELSE IF";
- break;
- case ST_ELSEWHERE:
- p = "ELSEWHERE";
- break;
- case ST_END_ASSOCIATE:
- p = "END ASSOCIATE";
- break;
- case ST_END_BLOCK:
- p = "END BLOCK";
- break;
- case ST_END_BLOCK_DATA:
- p = "END BLOCK DATA";
- break;
- case ST_END_CRITICAL:
- p = "END CRITICAL";
- break;
- case ST_ENDDO:
- p = "END DO";
- break;
- case ST_END_FILE:
- p = "END FILE";
- break;
- case ST_END_FORALL:
- p = "END FORALL";
- break;
- case ST_END_FUNCTION:
- p = "END FUNCTION";
- break;
- case ST_ENDIF:
- p = "END IF";
- break;
- case ST_END_INTERFACE:
- p = "END INTERFACE";
- break;
- case ST_END_MODULE:
- p = "END MODULE";
- break;
- case ST_END_PROGRAM:
- p = "END PROGRAM";
- break;
- case ST_END_SELECT:
- p = "END SELECT";
- break;
- case ST_END_SUBROUTINE:
- p = "END SUBROUTINE";
- break;
- case ST_END_WHERE:
- p = "END WHERE";
- break;
- case ST_END_TYPE:
- p = "END TYPE";
- break;
- case ST_ENTRY:
- p = "ENTRY";
- break;
- case ST_EQUIVALENCE:
- p = "EQUIVALENCE";
- break;
- case ST_ERROR_STOP:
- p = "ERROR STOP";
- break;
- case ST_EXIT:
- p = "EXIT";
- break;
- case ST_FLUSH:
- p = "FLUSH";
- break;
- case ST_FORALL_BLOCK: /* Fall through */
- case ST_FORALL:
- p = "FORALL";
- break;
- case ST_FORMAT:
- p = "FORMAT";
- break;
- case ST_FUNCTION:
- p = "FUNCTION";
- break;
- case ST_GENERIC:
- p = "GENERIC";
- break;
- case ST_GOTO:
- p = "GOTO";
- break;
- case ST_IF_BLOCK:
- p = _("block IF");
- break;
- case ST_IMPLICIT:
- p = "IMPLICIT";
- break;
- case ST_IMPLICIT_NONE:
- p = "IMPLICIT NONE";
- break;
- case ST_IMPLIED_ENDDO:
- p = _("implied END DO");
- break;
- case ST_IMPORT:
- p = "IMPORT";
- break;
- case ST_INQUIRE:
- p = "INQUIRE";
- break;
- case ST_INTERFACE:
- p = "INTERFACE";
- break;
- case ST_LOCK:
- p = "LOCK";
- break;
- case ST_PARAMETER:
- p = "PARAMETER";
- break;
- case ST_PRIVATE:
- p = "PRIVATE";
- break;
- case ST_PUBLIC:
- p = "PUBLIC";
- break;
- case ST_MODULE:
- p = "MODULE";
- break;
- case ST_PAUSE:
- p = "PAUSE";
- break;
- case ST_MODULE_PROC:
- p = "MODULE PROCEDURE";
- break;
- case ST_NAMELIST:
- p = "NAMELIST";
- break;
- case ST_NULLIFY:
- p = "NULLIFY";
- break;
- case ST_OPEN:
- p = "OPEN";
- break;
- case ST_PROGRAM:
- p = "PROGRAM";
- break;
- case ST_PROCEDURE:
- p = "PROCEDURE";
- break;
- case ST_READ:
- p = "READ";
- break;
- case ST_RETURN:
- p = "RETURN";
- break;
- case ST_REWIND:
- p = "REWIND";
- break;
- case ST_STOP:
- p = "STOP";
- break;
- case ST_SYNC_ALL:
- p = "SYNC ALL";
- break;
- case ST_SYNC_IMAGES:
- p = "SYNC IMAGES";
- break;
- case ST_SYNC_MEMORY:
- p = "SYNC MEMORY";
- break;
- case ST_SUBROUTINE:
- p = "SUBROUTINE";
- break;
- case ST_TYPE:
- p = "TYPE";
- break;
- case ST_UNLOCK:
- p = "UNLOCK";
- break;
- case ST_USE:
- p = "USE";
- break;
- case ST_WHERE_BLOCK: /* Fall through */
- case ST_WHERE:
- p = "WHERE";
- break;
- case ST_WAIT:
- p = "WAIT";
- break;
- case ST_WRITE:
- p = "WRITE";
- break;
- case ST_ASSIGNMENT:
- p = _("assignment");
- break;
- case ST_POINTER_ASSIGNMENT:
- p = _("pointer assignment");
- break;
- case ST_SELECT_CASE:
- p = "SELECT CASE";
- break;
- case ST_SELECT_TYPE:
- p = "SELECT TYPE";
- break;
- case ST_TYPE_IS:
- p = "TYPE IS";
- break;
- case ST_CLASS_IS:
- p = "CLASS IS";
- break;
- case ST_SEQUENCE:
- p = "SEQUENCE";
- break;
- case ST_SIMPLE_IF:
- p = _("simple IF");
- break;
- case ST_STATEMENT_FUNCTION:
- p = "STATEMENT FUNCTION";
- break;
- case ST_LABEL_ASSIGNMENT:
- p = "LABEL ASSIGNMENT";
- break;
- case ST_ENUM:
- p = "ENUM DEFINITION";
- break;
- case ST_ENUMERATOR:
- p = "ENUMERATOR DEFINITION";
- break;
- case ST_END_ENUM:
- p = "END ENUM";
- break;
- case ST_OACC_PARALLEL_LOOP:
- p = "!$ACC PARALLEL LOOP";
- break;
- case ST_OACC_END_PARALLEL_LOOP:
- p = "!$ACC END PARALLEL LOOP";
- break;
- case ST_OACC_PARALLEL:
- p = "!$ACC PARALLEL";
- break;
- case ST_OACC_END_PARALLEL:
- p = "!$ACC END PARALLEL";
- break;
- case ST_OACC_KERNELS:
- p = "!$ACC KERNELS";
- break;
- case ST_OACC_END_KERNELS:
- p = "!$ACC END KERNELS";
- break;
- case ST_OACC_KERNELS_LOOP:
- p = "!$ACC KERNELS LOOP";
- break;
- case ST_OACC_END_KERNELS_LOOP:
- p = "!$ACC END KERNELS LOOP";
- break;
- case ST_OACC_DATA:
- p = "!$ACC DATA";
- break;
- case ST_OACC_END_DATA:
- p = "!$ACC END DATA";
- break;
- case ST_OACC_HOST_DATA:
- p = "!$ACC HOST_DATA";
- break;
- case ST_OACC_END_HOST_DATA:
- p = "!$ACC END HOST_DATA";
- break;
- case ST_OACC_LOOP:
- p = "!$ACC LOOP";
- break;
- case ST_OACC_END_LOOP:
- p = "!$ACC END LOOP";
- break;
- case ST_OACC_DECLARE:
- p = "!$ACC DECLARE";
- break;
- case ST_OACC_UPDATE:
- p = "!$ACC UPDATE";
- break;
- case ST_OACC_WAIT:
- p = "!$ACC WAIT";
- break;
- case ST_OACC_CACHE:
- p = "!$ACC CACHE";
- break;
- case ST_OACC_ENTER_DATA:
- p = "!$ACC ENTER DATA";
- break;
- case ST_OACC_EXIT_DATA:
- p = "!$ACC EXIT DATA";
- break;
- case ST_OACC_ROUTINE:
- p = "!$ACC ROUTINE";
- break;
- case ST_OMP_ATOMIC:
- p = "!$OMP ATOMIC";
- break;
- case ST_OMP_BARRIER:
- p = "!$OMP BARRIER";
- break;
- case ST_OMP_CANCEL:
- p = "!$OMP CANCEL";
- break;
- case ST_OMP_CANCELLATION_POINT:
- p = "!$OMP CANCELLATION POINT";
- break;
- case ST_OMP_CRITICAL:
- p = "!$OMP CRITICAL";
- break;
- case ST_OMP_DECLARE_REDUCTION:
- p = "!$OMP DECLARE REDUCTION";
- break;
- case ST_OMP_DECLARE_SIMD:
- p = "!$OMP DECLARE SIMD";
- break;
- case ST_OMP_DECLARE_TARGET:
- p = "!$OMP DECLARE TARGET";
- break;
- case ST_OMP_DISTRIBUTE:
- p = "!$OMP DISTRIBUTE";
- break;
- case ST_OMP_DISTRIBUTE_PARALLEL_DO:
- p = "!$OMP DISTRIBUTE PARALLEL DO";
- break;
- case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- p = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
- break;
- case ST_OMP_DISTRIBUTE_SIMD:
- p = "!$OMP DISTRIBUTE SIMD";
- break;
- case ST_OMP_DO:
- p = "!$OMP DO";
- break;
- case ST_OMP_DO_SIMD:
- p = "!$OMP DO SIMD";
- break;
- case ST_OMP_END_ATOMIC:
- p = "!$OMP END ATOMIC";
- break;
- case ST_OMP_END_CRITICAL:
- p = "!$OMP END CRITICAL";
- break;
- case ST_OMP_END_DISTRIBUTE:
- p = "!$OMP END DISTRIBUTE";
- break;
- case ST_OMP_END_DISTRIBUTE_PARALLEL_DO:
- p = "!$OMP END DISTRIBUTE PARALLEL DO";
- break;
- case ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD:
- p = "!$OMP END DISTRIBUTE PARALLEL DO SIMD";
- break;
- case ST_OMP_END_DISTRIBUTE_SIMD:
- p = "!$OMP END DISTRIBUTE SIMD";
- break;
- case ST_OMP_END_DO:
- p = "!$OMP END DO";
- break;
- case ST_OMP_END_DO_SIMD:
- p = "!$OMP END DO SIMD";
- break;
- case ST_OMP_END_SIMD:
- p = "!$OMP END SIMD";
- break;
- case ST_OMP_END_MASTER:
- p = "!$OMP END MASTER";
- break;
- case ST_OMP_END_ORDERED:
- p = "!$OMP END ORDERED";
- break;
- case ST_OMP_END_PARALLEL:
- p = "!$OMP END PARALLEL";
- break;
- case ST_OMP_END_PARALLEL_DO:
- p = "!$OMP END PARALLEL DO";
- break;
- case ST_OMP_END_PARALLEL_DO_SIMD:
- p = "!$OMP END PARALLEL DO SIMD";
- break;
- case ST_OMP_END_PARALLEL_SECTIONS:
- p = "!$OMP END PARALLEL SECTIONS";
- break;
- case ST_OMP_END_PARALLEL_WORKSHARE:
- p = "!$OMP END PARALLEL WORKSHARE";
- break;
- case ST_OMP_END_SECTIONS:
- p = "!$OMP END SECTIONS";
- break;
- case ST_OMP_END_SINGLE:
- p = "!$OMP END SINGLE";
- break;
- case ST_OMP_END_TASK:
- p = "!$OMP END TASK";
- break;
- case ST_OMP_END_TARGET:
- p = "!$OMP END TARGET";
- break;
- case ST_OMP_END_TARGET_DATA:
- p = "!$OMP END TARGET DATA";
- break;
- case ST_OMP_END_TARGET_TEAMS:
- p = "!$OMP END TARGET TEAMS";
- break;
- case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE:
- p = "!$OMP END TARGET TEAMS DISTRIBUTE";
- break;
- case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- p = "!$OMP END TARGET TEAMS DISTRIBUTE PARALLEL DO";
- break;
- case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- p = "!$OMP END TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
- break;
- case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD:
- p = "!$OMP END TARGET TEAMS DISTRIBUTE SIMD";
- break;
- case ST_OMP_END_TASKGROUP:
- p = "!$OMP END TASKGROUP";
- break;
- case ST_OMP_END_TEAMS:
- p = "!$OMP END TEAMS";
- break;
- case ST_OMP_END_TEAMS_DISTRIBUTE:
- p = "!$OMP END TEAMS DISTRIBUTE";
- break;
- case ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO:
- p = "!$OMP END TEAMS DISTRIBUTE PARALLEL DO";
- break;
- case ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- p = "!$OMP END TEAMS DISTRIBUTE PARALLEL DO SIMD";
- break;
- case ST_OMP_END_TEAMS_DISTRIBUTE_SIMD:
- p = "!$OMP END TEAMS DISTRIBUTE SIMD";
- break;
- case ST_OMP_END_WORKSHARE:
- p = "!$OMP END WORKSHARE";
- break;
- case ST_OMP_FLUSH:
- p = "!$OMP FLUSH";
- break;
- case ST_OMP_MASTER:
- p = "!$OMP MASTER";
- break;
- case ST_OMP_ORDERED:
- p = "!$OMP ORDERED";
- break;
- case ST_OMP_PARALLEL:
- p = "!$OMP PARALLEL";
- break;
- case ST_OMP_PARALLEL_DO:
- p = "!$OMP PARALLEL DO";
- break;
- case ST_OMP_PARALLEL_DO_SIMD:
- p = "!$OMP PARALLEL DO SIMD";
- break;
- case ST_OMP_PARALLEL_SECTIONS:
- p = "!$OMP PARALLEL SECTIONS";
- break;
- case ST_OMP_PARALLEL_WORKSHARE:
- p = "!$OMP PARALLEL WORKSHARE";
- break;
- case ST_OMP_SECTIONS:
- p = "!$OMP SECTIONS";
- break;
- case ST_OMP_SECTION:
- p = "!$OMP SECTION";
- break;
- case ST_OMP_SIMD:
- p = "!$OMP SIMD";
- break;
- case ST_OMP_SINGLE:
- p = "!$OMP SINGLE";
- break;
- case ST_OMP_TARGET:
- p = "!$OMP TARGET";
- break;
- case ST_OMP_TARGET_DATA:
- p = "!$OMP TARGET DATA";
- break;
- case ST_OMP_TARGET_TEAMS:
- p = "!$OMP TARGET TEAMS";
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
- p = "!$OMP TARGET TEAMS DISTRIBUTE";
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- p = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- p = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- p = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
- break;
- case ST_OMP_TARGET_UPDATE:
- p = "!$OMP TARGET UPDATE";
- break;
- case ST_OMP_TASK:
- p = "!$OMP TASK";
- break;
- case ST_OMP_TASKGROUP:
- p = "!$OMP TASKGROUP";
- break;
- case ST_OMP_TASKWAIT:
- p = "!$OMP TASKWAIT";
- break;
- case ST_OMP_TASKYIELD:
- p = "!$OMP TASKYIELD";
- break;
- case ST_OMP_TEAMS:
- p = "!$OMP TEAMS";
- break;
- case ST_OMP_TEAMS_DISTRIBUTE:
- p = "!$OMP TEAMS DISTRIBUTE";
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- p = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- p = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
- p = "!$OMP TEAMS DISTRIBUTE SIMD";
- break;
- case ST_OMP_THREADPRIVATE:
- p = "!$OMP THREADPRIVATE";
- break;
- case ST_OMP_WORKSHARE:
- p = "!$OMP WORKSHARE";
- break;
- default:
- gfc_internal_error ("gfc_ascii_statement(): Bad statement code");
- }
- return p;
- }
- /* Create a symbol for the main program and assign it to ns->proc_name. */
-
- static void
- main_program_symbol (gfc_namespace *ns, const char *name)
- {
- gfc_symbol *main_program;
- symbol_attribute attr;
- gfc_get_symbol (name, ns, &main_program);
- gfc_clear_attr (&attr);
- attr.flavor = FL_PROGRAM;
- attr.proc = PROC_UNKNOWN;
- attr.subroutine = 1;
- attr.access = ACCESS_PUBLIC;
- attr.is_main_program = 1;
- main_program->attr = attr;
- main_program->declared_at = gfc_current_locus;
- ns->proc_name = main_program;
- gfc_commit_symbols ();
- }
- /* Do whatever is necessary to accept the last statement. */
- static void
- accept_statement (gfc_statement st)
- {
- switch (st)
- {
- case ST_IMPLICIT_NONE:
- case ST_IMPLICIT:
- break;
- case ST_FUNCTION:
- case ST_SUBROUTINE:
- case ST_MODULE:
- gfc_current_ns->proc_name = gfc_new_block;
- break;
- /* If the statement is the end of a block, lay down a special code
- that allows a branch to the end of the block from within the
- construct. IF and SELECT are treated differently from DO
- (where EXEC_NOP is added inside the loop) for two
- reasons:
- 1. END DO has a meaning in the sense that after a GOTO to
- it, the loop counter must be increased.
- 2. IF blocks and SELECT blocks can consist of multiple
- parallel blocks (IF ... ELSE IF ... ELSE ... END IF).
- Putting the label before the END IF would make the jump
- from, say, the ELSE IF block to the END IF illegal. */
- case ST_ENDIF:
- case ST_END_SELECT:
- case ST_END_CRITICAL:
- if (gfc_statement_label != NULL)
- {
- new_st.op = EXEC_END_NESTED_BLOCK;
- add_statement ();
- }
- break;
- /* In the case of BLOCK and ASSOCIATE blocks, there cannot be more than
- one parallel block. Thus, we add the special code to the nested block
- itself, instead of the parent one. */
- case ST_END_BLOCK:
- case ST_END_ASSOCIATE:
- if (gfc_statement_label != NULL)
- {
- new_st.op = EXEC_END_BLOCK;
- add_statement ();
- }
- break;
- /* The end-of-program unit statements do not get the special
- marker and require a statement of some sort if they are a
- branch target. */
- case ST_END_PROGRAM:
- case ST_END_FUNCTION:
- case ST_END_SUBROUTINE:
- if (gfc_statement_label != NULL)
- {
- new_st.op = EXEC_RETURN;
- add_statement ();
- }
- else
- {
- new_st.op = EXEC_END_PROCEDURE;
- add_statement ();
- }
- break;
- case ST_ENTRY:
- case_executable:
- case_exec_markers:
- add_statement ();
- break;
- default:
- break;
- }
- gfc_commit_symbols ();
- gfc_warning_check ();
- gfc_clear_new_st ();
- }
- /* Undo anything tentative that has been built for the current
- statement. */
- static void
- reject_statement (void)
- {
- /* Revert to the previous charlen chain. */
- gfc_free_charlen (gfc_current_ns->cl_list, gfc_current_ns->old_cl_list);
- gfc_current_ns->cl_list = gfc_current_ns->old_cl_list;
- gfc_free_equiv_until (gfc_current_ns->equiv, gfc_current_ns->old_equiv);
- gfc_current_ns->equiv = gfc_current_ns->old_equiv;
- gfc_reject_data (gfc_current_ns);
- gfc_new_block = NULL;
- gfc_undo_symbols ();
- gfc_clear_warning ();
- undo_new_statement ();
- }
- /* Generic complaint about an out of order statement. We also do
- whatever is necessary to clean up. */
- static void
- unexpected_statement (gfc_statement st)
- {
- gfc_error ("Unexpected %s statement at %C", gfc_ascii_statement (st));
- reject_statement ();
- }
- /* Given the next statement seen by the matcher, make sure that it is
- in proper order with the last. This subroutine is initialized by
- calling it with an argument of ST_NONE. If there is a problem, we
- issue an error and return false. Otherwise we return true.
- Individual parsers need to verify that the statements seen are
- valid before calling here, i.e., ENTRY statements are not allowed in
- INTERFACE blocks. The following diagram is taken from the standard:
- +---------------------------------------+
- | program subroutine function module |
- +---------------------------------------+
- | use |
- +---------------------------------------+
- | import |
- +---------------------------------------+
- | | implicit none |
- | +-----------+------------------+
- | | parameter | implicit |
- | +-----------+------------------+
- | format | | derived type |
- | entry | parameter | interface |
- | | data | specification |
- | | | statement func |
- | +-----------+------------------+
- | | data | executable |
- +--------+-----------+------------------+
- | contains |
- +---------------------------------------+
- | internal module/subprogram |
- +---------------------------------------+
- | end |
- +---------------------------------------+
- */
- enum state_order
- {
- ORDER_START,
- ORDER_USE,
- ORDER_IMPORT,
- ORDER_IMPLICIT_NONE,
- ORDER_IMPLICIT,
- ORDER_SPEC,
- ORDER_EXEC
- };
- typedef struct
- {
- enum state_order state;
- gfc_statement last_statement;
- locus where;
- }
- st_state;
- static bool
- verify_st_order (st_state *p, gfc_statement st, bool silent)
- {
- switch (st)
- {
- case ST_NONE:
- p->state = ORDER_START;
- break;
- case ST_USE:
- if (p->state > ORDER_USE)
- goto order;
- p->state = ORDER_USE;
- break;
- case ST_IMPORT:
- if (p->state > ORDER_IMPORT)
- goto order;
- p->state = ORDER_IMPORT;
- break;
- case ST_IMPLICIT_NONE:
- if (p->state > ORDER_IMPLICIT)
- goto order;
- /* The '>' sign cannot be a '>=', because a FORMAT or ENTRY
- statement disqualifies a USE but not an IMPLICIT NONE.
- Duplicate IMPLICIT NONEs are caught when the implicit types
- are set. */
- p->state = ORDER_IMPLICIT_NONE;
- break;
- case ST_IMPLICIT:
- if (p->state > ORDER_IMPLICIT)
- goto order;
- p->state = ORDER_IMPLICIT;
- break;
- case ST_FORMAT:
- case ST_ENTRY:
- if (p->state < ORDER_IMPLICIT_NONE)
- p->state = ORDER_IMPLICIT_NONE;
- break;
- case ST_PARAMETER:
- if (p->state >= ORDER_EXEC)
- goto order;
- if (p->state < ORDER_IMPLICIT)
- p->state = ORDER_IMPLICIT;
- break;
- case ST_DATA:
- if (p->state < ORDER_SPEC)
- p->state = ORDER_SPEC;
- break;
- case ST_PUBLIC:
- case ST_PRIVATE:
- case ST_DERIVED_DECL:
- case ST_OACC_DECLARE:
- case_decl:
- if (p->state >= ORDER_EXEC)
- goto order;
- if (p->state < ORDER_SPEC)
- p->state = ORDER_SPEC;
- break;
- case_executable:
- case_exec_markers:
- if (p->state < ORDER_EXEC)
- p->state = ORDER_EXEC;
- break;
- default:
- return false;
- }
- /* All is well, record the statement in case we need it next time. */
- p->where = gfc_current_locus;
- p->last_statement = st;
- return true;
- order:
- if (!silent)
- gfc_error_1 ("%s statement at %C cannot follow %s statement at %L",
- gfc_ascii_statement (st),
- gfc_ascii_statement (p->last_statement), &p->where);
- return false;
- }
- /* Handle an unexpected end of file. This is a show-stopper... */
- static void unexpected_eof (void) ATTRIBUTE_NORETURN;
- static void
- unexpected_eof (void)
- {
- gfc_state_data *p;
- gfc_error ("Unexpected end of file in %qs", gfc_source_file);
- /* Memory cleanup. Move to "second to last". */
- for (p = gfc_state_stack; p && p->previous && p->previous->previous;
- p = p->previous);
- gfc_current_ns->code = (p && p->previous) ? p->head : NULL;
- gfc_done_2 ();
- longjmp (eof_buf, 1);
- }
- /* Parse the CONTAINS section of a derived type definition. */
- gfc_access gfc_typebound_default_access;
- static bool
- parse_derived_contains (void)
- {
- gfc_state_data s;
- bool seen_private = false;
- bool seen_comps = false;
- bool error_flag = false;
- bool to_finish;
- gcc_assert (gfc_current_state () == COMP_DERIVED);
- gcc_assert (gfc_current_block ());
- /* Derived-types with SEQUENCE and/or BIND(C) must not have a CONTAINS
- section. */
- if (gfc_current_block ()->attr.sequence)
- gfc_error ("Derived-type %qs with SEQUENCE must not have a CONTAINS"
- " section at %C", gfc_current_block ()->name);
- if (gfc_current_block ()->attr.is_bind_c)
- gfc_error ("Derived-type %qs with BIND(C) must not have a CONTAINS"
- " section at %C", gfc_current_block ()->name);
- accept_statement (ST_CONTAINS);
- push_state (&s, COMP_DERIVED_CONTAINS, NULL);
- gfc_typebound_default_access = ACCESS_PUBLIC;
- to_finish = false;
- while (!to_finish)
- {
- gfc_statement st;
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- break;
- case ST_DATA_DECL:
- gfc_error ("Components in TYPE at %C must precede CONTAINS");
- goto error;
- case ST_PROCEDURE:
- if (!gfc_notify_std (GFC_STD_F2003, "Type-bound procedure at %C"))
- goto error;
- accept_statement (ST_PROCEDURE);
- seen_comps = true;
- break;
- case ST_GENERIC:
- if (!gfc_notify_std (GFC_STD_F2003, "GENERIC binding at %C"))
- goto error;
- accept_statement (ST_GENERIC);
- seen_comps = true;
- break;
- case ST_FINAL:
- if (!gfc_notify_std (GFC_STD_F2003, "FINAL procedure declaration"
- " at %C"))
- goto error;
- accept_statement (ST_FINAL);
- seen_comps = true;
- break;
- case ST_END_TYPE:
- to_finish = true;
- if (!seen_comps
- && (!gfc_notify_std(GFC_STD_F2008, "Derived type definition "
- "at %C with empty CONTAINS section")))
- goto error;
- /* ST_END_TYPE is accepted by parse_derived after return. */
- break;
- case ST_PRIVATE:
- if (!gfc_find_state (COMP_MODULE))
- {
- gfc_error ("PRIVATE statement in TYPE at %C must be inside "
- "a MODULE");
- goto error;
- }
- if (seen_comps)
- {
- gfc_error ("PRIVATE statement at %C must precede procedure"
- " bindings");
- goto error;
- }
- if (seen_private)
- {
- gfc_error ("Duplicate PRIVATE statement at %C");
- goto error;
- }
- accept_statement (ST_PRIVATE);
- gfc_typebound_default_access = ACCESS_PRIVATE;
- seen_private = true;
- break;
- case ST_SEQUENCE:
- gfc_error ("SEQUENCE statement at %C must precede CONTAINS");
- goto error;
- case ST_CONTAINS:
- gfc_error ("Already inside a CONTAINS block at %C");
- goto error;
- default:
- unexpected_statement (st);
- break;
- }
- continue;
- error:
- error_flag = true;
- reject_statement ();
- }
- pop_state ();
- gcc_assert (gfc_current_state () == COMP_DERIVED);
- return error_flag;
- }
- /* Parse a derived type. */
- static void
- parse_derived (void)
- {
- int compiling_type, seen_private, seen_sequence, seen_component;
- gfc_statement st;
- gfc_state_data s;
- gfc_symbol *sym;
- gfc_component *c, *lock_comp = NULL;
- accept_statement (ST_DERIVED_DECL);
- push_state (&s, COMP_DERIVED, gfc_new_block);
- gfc_new_block->component_access = ACCESS_PUBLIC;
- seen_private = 0;
- seen_sequence = 0;
- seen_component = 0;
- compiling_type = 1;
- while (compiling_type)
- {
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_DATA_DECL:
- case ST_PROCEDURE:
- accept_statement (st);
- seen_component = 1;
- break;
- case ST_FINAL:
- gfc_error ("FINAL declaration at %C must be inside CONTAINS");
- break;
- case ST_END_TYPE:
- endType:
- compiling_type = 0;
- if (!seen_component)
- gfc_notify_std (GFC_STD_F2003, "Derived type "
- "definition at %C without components");
- accept_statement (ST_END_TYPE);
- break;
- case ST_PRIVATE:
- if (!gfc_find_state (COMP_MODULE))
- {
- gfc_error ("PRIVATE statement in TYPE at %C must be inside "
- "a MODULE");
- break;
- }
- if (seen_component)
- {
- gfc_error ("PRIVATE statement at %C must precede "
- "structure components");
- break;
- }
- if (seen_private)
- gfc_error ("Duplicate PRIVATE statement at %C");
- s.sym->component_access = ACCESS_PRIVATE;
- accept_statement (ST_PRIVATE);
- seen_private = 1;
- break;
- case ST_SEQUENCE:
- if (seen_component)
- {
- gfc_error ("SEQUENCE statement at %C must precede "
- "structure components");
- break;
- }
- if (gfc_current_block ()->attr.sequence)
- gfc_warning (0, "SEQUENCE attribute at %C already specified in "
- "TYPE statement");
- if (seen_sequence)
- {
- gfc_error ("Duplicate SEQUENCE statement at %C");
- }
- seen_sequence = 1;
- gfc_add_sequence (&gfc_current_block ()->attr,
- gfc_current_block ()->name, NULL);
- break;
- case ST_CONTAINS:
- gfc_notify_std (GFC_STD_F2003,
- "CONTAINS block in derived type"
- " definition at %C");
- accept_statement (ST_CONTAINS);
- parse_derived_contains ();
- goto endType;
- default:
- unexpected_statement (st);
- break;
- }
- }
- /* need to verify that all fields of the derived type are
- * interoperable with C if the type is declared to be bind(c)
- */
- sym = gfc_current_block ();
- for (c = sym->components; c; c = c->next)
- {
- bool coarray, lock_type, allocatable, pointer;
- coarray = lock_type = allocatable = pointer = false;
- /* Look for allocatable components. */
- if (c->attr.allocatable
- || (c->ts.type == BT_CLASS && c->attr.class_ok
- && CLASS_DATA (c)->attr.allocatable)
- || (c->ts.type == BT_DERIVED && !c->attr.pointer
- && c->ts.u.derived->attr.alloc_comp))
- {
- allocatable = true;
- sym->attr.alloc_comp = 1;
- }
- /* Look for pointer components. */
- if (c->attr.pointer
- || (c->ts.type == BT_CLASS && c->attr.class_ok
- && CLASS_DATA (c)->attr.class_pointer)
- || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.pointer_comp))
- {
- pointer = true;
- sym->attr.pointer_comp = 1;
- }
- /* Look for procedure pointer components. */
- if (c->attr.proc_pointer
- || (c->ts.type == BT_DERIVED
- && c->ts.u.derived->attr.proc_pointer_comp))
- sym->attr.proc_pointer_comp = 1;
- /* Looking for coarray components. */
- if (c->attr.codimension
- || (c->ts.type == BT_CLASS && c->attr.class_ok
- && CLASS_DATA (c)->attr.codimension))
- {
- coarray = true;
- sym->attr.coarray_comp = 1;
- }
-
- if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.coarray_comp
- && !c->attr.pointer)
- {
- coarray = true;
- sym->attr.coarray_comp = 1;
- }
- /* Looking for lock_type components. */
- if ((c->ts.type == BT_DERIVED
- && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
- && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
- || (c->ts.type == BT_CLASS && c->attr.class_ok
- && CLASS_DATA (c)->ts.u.derived->from_intmod
- == INTMOD_ISO_FORTRAN_ENV
- && CLASS_DATA (c)->ts.u.derived->intmod_sym_id
- == ISOFORTRAN_LOCK_TYPE)
- || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.lock_comp
- && !allocatable && !pointer))
- {
- lock_type = 1;
- lock_comp = c;
- sym->attr.lock_comp = 1;
- }
- /* Check for F2008, C1302 - and recall that pointers may not be coarrays
- (5.3.14) and that subobjects of coarray are coarray themselves (2.4.7),
- unless there are nondirect [allocatable or pointer] components
- involved (cf. 1.3.33.1 and 1.3.33.3). */
- if (pointer && !coarray && lock_type)
- gfc_error ("Component %s at %L of type LOCK_TYPE must have a "
- "codimension or be a subcomponent of a coarray, "
- "which is not possible as the component has the "
- "pointer attribute", c->name, &c->loc);
- else if (pointer && !coarray && c->ts.type == BT_DERIVED
- && c->ts.u.derived->attr.lock_comp)
- gfc_error ("Pointer component %s at %L has a noncoarray subcomponent "
- "of type LOCK_TYPE, which must have a codimension or be a "
- "subcomponent of a coarray", c->name, &c->loc);
- if (lock_type && allocatable && !coarray)
- gfc_error ("Allocatable component %s at %L of type LOCK_TYPE must have "
- "a codimension", c->name, &c->loc);
- else if (lock_type && allocatable && c->ts.type == BT_DERIVED
- && c->ts.u.derived->attr.lock_comp)
- gfc_error ("Allocatable component %s at %L must have a codimension as "
- "it has a noncoarray subcomponent of type LOCK_TYPE",
- c->name, &c->loc);
- if (sym->attr.coarray_comp && !coarray && lock_type)
- gfc_error ("Noncoarray component %s at %L of type LOCK_TYPE or with "
- "subcomponent of type LOCK_TYPE must have a codimension or "
- "be a subcomponent of a coarray. (Variables of type %s may "
- "not have a codimension as already a coarray "
- "subcomponent exists)", c->name, &c->loc, sym->name);
- if (sym->attr.lock_comp && coarray && !lock_type)
- gfc_error_1 ("Noncoarray component %s at %L of type LOCK_TYPE or with "
- "subcomponent of type LOCK_TYPE must have a codimension or "
- "be a subcomponent of a coarray. (Variables of type %s may "
- "not have a codimension as %s at %L has a codimension or a "
- "coarray subcomponent)", lock_comp->name, &lock_comp->loc,
- sym->name, c->name, &c->loc);
- /* Look for private components. */
- if (sym->component_access == ACCESS_PRIVATE
- || c->attr.access == ACCESS_PRIVATE
- || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.private_comp))
- sym->attr.private_comp = 1;
- }
- if (!seen_component)
- sym->attr.zero_comp = 1;
- pop_state ();
- }
- /* Parse an ENUM. */
-
- static void
- parse_enum (void)
- {
- gfc_statement st;
- int compiling_enum;
- gfc_state_data s;
- int seen_enumerator = 0;
- push_state (&s, COMP_ENUM, gfc_new_block);
- compiling_enum = 1;
- while (compiling_enum)
- {
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- break;
- case ST_ENUMERATOR:
- seen_enumerator = 1;
- accept_statement (st);
- break;
- case ST_END_ENUM:
- compiling_enum = 0;
- if (!seen_enumerator)
- gfc_error ("ENUM declaration at %C has no ENUMERATORS");
- accept_statement (st);
- break;
- default:
- gfc_free_enum_history ();
- unexpected_statement (st);
- break;
- }
- }
- pop_state ();
- }
- /* Parse an interface. We must be able to deal with the possibility
- of recursive interfaces. The parse_spec() subroutine is mutually
- recursive with parse_interface(). */
- static gfc_statement parse_spec (gfc_statement);
- static void
- parse_interface (void)
- {
- gfc_compile_state new_state = COMP_NONE, current_state;
- gfc_symbol *prog_unit, *sym;
- gfc_interface_info save;
- gfc_state_data s1, s2;
- gfc_statement st;
- accept_statement (ST_INTERFACE);
- current_interface.ns = gfc_current_ns;
- save = current_interface;
- sym = (current_interface.type == INTERFACE_GENERIC
- || current_interface.type == INTERFACE_USER_OP)
- ? gfc_new_block : NULL;
- push_state (&s1, COMP_INTERFACE, sym);
- current_state = COMP_NONE;
- loop:
- gfc_current_ns = gfc_get_namespace (current_interface.ns, 0);
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_SUBROUTINE:
- case ST_FUNCTION:
- if (st == ST_SUBROUTINE)
- new_state = COMP_SUBROUTINE;
- else if (st == ST_FUNCTION)
- new_state = COMP_FUNCTION;
- if (gfc_new_block->attr.pointer)
- {
- gfc_new_block->attr.pointer = 0;
- gfc_new_block->attr.proc_pointer = 1;
- }
- if (!gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
- gfc_new_block->formal, NULL))
- {
- reject_statement ();
- gfc_free_namespace (gfc_current_ns);
- goto loop;
- }
- break;
- case ST_PROCEDURE:
- case ST_MODULE_PROC: /* The module procedure matcher makes
- sure the context is correct. */
- accept_statement (st);
- gfc_free_namespace (gfc_current_ns);
- goto loop;
- case ST_END_INTERFACE:
- gfc_free_namespace (gfc_current_ns);
- gfc_current_ns = current_interface.ns;
- goto done;
- default:
- gfc_error ("Unexpected %s statement in INTERFACE block at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- gfc_free_namespace (gfc_current_ns);
- goto loop;
- }
- /* Make sure that the generic name has the right attribute. */
- if (current_interface.type == INTERFACE_GENERIC
- && current_state == COMP_NONE)
- {
- if (new_state == COMP_FUNCTION && sym)
- gfc_add_function (&sym->attr, sym->name, NULL);
- else if (new_state == COMP_SUBROUTINE && sym)
- gfc_add_subroutine (&sym->attr, sym->name, NULL);
- current_state = new_state;
- }
- if (current_interface.type == INTERFACE_ABSTRACT)
- {
- gfc_add_abstract (&gfc_new_block->attr, &gfc_current_locus);
- if (gfc_is_intrinsic_typename (gfc_new_block->name))
- gfc_error ("Name %qs of ABSTRACT INTERFACE at %C "
- "cannot be the same as an intrinsic type",
- gfc_new_block->name);
- }
- push_state (&s2, new_state, gfc_new_block);
- accept_statement (st);
- prog_unit = gfc_new_block;
- prog_unit->formal_ns = gfc_current_ns;
- if (prog_unit == prog_unit->formal_ns->proc_name
- && prog_unit->ns != prog_unit->formal_ns)
- prog_unit->refs++;
- decl:
- /* Read data declaration statements. */
- st = parse_spec (ST_NONE);
- /* Since the interface block does not permit an IMPLICIT statement,
- the default type for the function or the result must be taken
- from the formal namespace. */
- if (new_state == COMP_FUNCTION)
- {
- if (prog_unit->result == prog_unit
- && prog_unit->ts.type == BT_UNKNOWN)
- gfc_set_default_type (prog_unit, 1, prog_unit->formal_ns);
- else if (prog_unit->result != prog_unit
- && prog_unit->result->ts.type == BT_UNKNOWN)
- gfc_set_default_type (prog_unit->result, 1,
- prog_unit->formal_ns);
- }
- if (st != ST_END_SUBROUTINE && st != ST_END_FUNCTION)
- {
- gfc_error ("Unexpected %s statement at %C in INTERFACE body",
- gfc_ascii_statement (st));
- reject_statement ();
- goto decl;
- }
- /* Add EXTERNAL attribute to function or subroutine. */
- if (current_interface.type != INTERFACE_ABSTRACT && !prog_unit->attr.dummy)
- gfc_add_external (&prog_unit->attr, &gfc_current_locus);
- current_interface = save;
- gfc_add_interface (prog_unit);
- pop_state ();
- if (current_interface.ns
- && current_interface.ns->proc_name
- && strcmp (current_interface.ns->proc_name->name,
- prog_unit->name) == 0)
- gfc_error ("INTERFACE procedure %qs at %L has the same name as the "
- "enclosing procedure", prog_unit->name,
- ¤t_interface.ns->proc_name->declared_at);
- goto loop;
- done:
- pop_state ();
- }
- /* Associate function characteristics by going back to the function
- declaration and rematching the prefix. */
- static match
- match_deferred_characteristics (gfc_typespec * ts)
- {
- locus loc;
- match m = MATCH_ERROR;
- char name[GFC_MAX_SYMBOL_LEN + 1];
- loc = gfc_current_locus;
- gfc_current_locus = gfc_current_block ()->declared_at;
- gfc_clear_error ();
- gfc_buffer_error (true);
- m = gfc_match_prefix (ts);
- gfc_buffer_error (false);
- if (ts->type == BT_DERIVED)
- {
- ts->kind = 0;
- if (!ts->u.derived)
- m = MATCH_ERROR;
- }
- /* Only permit one go at the characteristic association. */
- if (ts->kind == -1)
- ts->kind = 0;
- /* Set the function locus correctly. If we have not found the
- function name, there is an error. */
- if (m == MATCH_YES
- && gfc_match ("function% %n", name) == MATCH_YES
- && strcmp (name, gfc_current_block ()->name) == 0)
- {
- gfc_current_block ()->declared_at = gfc_current_locus;
- gfc_commit_symbols ();
- }
- else
- {
- gfc_error_check ();
- gfc_undo_symbols ();
- }
- gfc_current_locus =loc;
- return m;
- }
- /* Check specification-expressions in the function result of the currently
- parsed block and ensure they are typed (give an IMPLICIT type if necessary).
- For return types specified in a FUNCTION prefix, the IMPLICIT rules of the
- scope are not yet parsed so this has to be delayed up to parse_spec. */
- static void
- check_function_result_typed (void)
- {
- gfc_typespec* ts = &gfc_current_ns->proc_name->result->ts;
- gcc_assert (gfc_current_state () == COMP_FUNCTION);
- gcc_assert (ts->type != BT_UNKNOWN);
- /* Check type-parameters, at the moment only CHARACTER lengths possible. */
- /* TODO: Extend when KIND type parameters are implemented. */
- if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length)
- gfc_expr_check_typed (ts->u.cl->length, gfc_current_ns, true);
- }
- /* Parse a set of specification statements. Returns the statement
- that doesn't fit. */
- static gfc_statement
- parse_spec (gfc_statement st)
- {
- st_state ss;
- bool function_result_typed = false;
- bool bad_characteristic = false;
- gfc_typespec *ts;
- verify_st_order (&ss, ST_NONE, false);
- if (st == ST_NONE)
- st = next_statement ();
- /* If we are not inside a function or don't have a result specified so far,
- do nothing special about it. */
- if (gfc_current_state () != COMP_FUNCTION)
- function_result_typed = true;
- else
- {
- gfc_symbol* proc = gfc_current_ns->proc_name;
- gcc_assert (proc);
- if (proc->result->ts.type == BT_UNKNOWN)
- function_result_typed = true;
- }
- loop:
- /* If we're inside a BLOCK construct, some statements are disallowed.
- Check this here. Attribute declaration statements like INTENT, OPTIONAL
- or VALUE are also disallowed, but they don't have a particular ST_*
- key so we have to check for them individually in their matcher routine. */
- if (gfc_current_state () == COMP_BLOCK)
- switch (st)
- {
- case ST_IMPLICIT:
- case ST_IMPLICIT_NONE:
- case ST_NAMELIST:
- case ST_COMMON:
- case ST_EQUIVALENCE:
- case ST_STATEMENT_FUNCTION:
- gfc_error ("%s statement is not allowed inside of BLOCK at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- break;
- default:
- break;
- }
- else if (gfc_current_state () == COMP_BLOCK_DATA)
- /* Fortran 2008, C1116. */
- switch (st)
- {
- case ST_DATA_DECL:
- case ST_COMMON:
- case ST_DATA:
- case ST_TYPE:
- case ST_END_BLOCK_DATA:
- case ST_ATTR_DECL:
- case ST_EQUIVALENCE:
- case ST_PARAMETER:
- case ST_IMPLICIT:
- case ST_IMPLICIT_NONE:
- case ST_DERIVED_DECL:
- case ST_USE:
- break;
- case ST_NONE:
- break;
-
- default:
- gfc_error ("%s statement is not allowed inside of BLOCK DATA at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- break;
- }
-
- /* If we find a statement that can not be followed by an IMPLICIT statement
- (and thus we can expect to see none any further), type the function result
- if it has not yet been typed. Be careful not to give the END statement
- to verify_st_order! */
- if (!function_result_typed && st != ST_GET_FCN_CHARACTERISTICS)
- {
- bool verify_now = false;
- if (st == ST_END_FUNCTION || st == ST_CONTAINS)
- verify_now = true;
- else
- {
- st_state dummyss;
- verify_st_order (&dummyss, ST_NONE, false);
- verify_st_order (&dummyss, st, false);
- if (!verify_st_order (&dummyss, ST_IMPLICIT, true))
- verify_now = true;
- }
- if (verify_now)
- {
- check_function_result_typed ();
- function_result_typed = true;
- }
- }
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_IMPLICIT_NONE:
- case ST_IMPLICIT:
- if (!function_result_typed)
- {
- check_function_result_typed ();
- function_result_typed = true;
- }
- goto declSt;
- case ST_FORMAT:
- case ST_ENTRY:
- case ST_DATA: /* Not allowed in interfaces */
- if (gfc_current_state () == COMP_INTERFACE)
- break;
- /* Fall through */
- case ST_USE:
- case ST_IMPORT:
- case ST_PARAMETER:
- case ST_PUBLIC:
- case ST_PRIVATE:
- case ST_DERIVED_DECL:
- case_decl:
- declSt:
- if (!verify_st_order (&ss, st, false))
- {
- reject_statement ();
- st = next_statement ();
- goto loop;
- }
- switch (st)
- {
- case ST_INTERFACE:
- parse_interface ();
- break;
- case ST_DERIVED_DECL:
- parse_derived ();
- break;
- case ST_PUBLIC:
- case ST_PRIVATE:
- if (gfc_current_state () != COMP_MODULE)
- {
- gfc_error ("%s statement must appear in a MODULE",
- gfc_ascii_statement (st));
- reject_statement ();
- break;
- }
- if (gfc_current_ns->default_access != ACCESS_UNKNOWN)
- {
- gfc_error ("%s statement at %C follows another accessibility "
- "specification", gfc_ascii_statement (st));
- reject_statement ();
- break;
- }
- gfc_current_ns->default_access = (st == ST_PUBLIC)
- ? ACCESS_PUBLIC : ACCESS_PRIVATE;
- break;
- case ST_STATEMENT_FUNCTION:
- if (gfc_current_state () == COMP_MODULE)
- {
- unexpected_statement (st);
- break;
- }
- default:
- break;
- }
- accept_statement (st);
- st = next_statement ();
- goto loop;
- case ST_ENUM:
- accept_statement (st);
- parse_enum();
- st = next_statement ();
- goto loop;
- case ST_GET_FCN_CHARACTERISTICS:
- /* This statement triggers the association of a function's result
- characteristics. */
- ts = &gfc_current_block ()->result->ts;
- if (match_deferred_characteristics (ts) != MATCH_YES)
- bad_characteristic = true;
- st = next_statement ();
- goto loop;
- case ST_OACC_DECLARE:
- if (!verify_st_order(&ss, st, false))
- {
- reject_statement ();
- st = next_statement ();
- goto loop;
- }
- if (gfc_state_stack->ext.oacc_declare_clauses == NULL)
- gfc_state_stack->ext.oacc_declare_clauses = new_st.ext.omp_clauses;
- accept_statement (st);
- st = next_statement ();
- goto loop;
- default:
- break;
- }
- /* If match_deferred_characteristics failed, then there is an error. */
- if (bad_characteristic)
- {
- ts = &gfc_current_block ()->result->ts;
- if (ts->type != BT_DERIVED)
- gfc_error ("Bad kind expression for function %qs at %L",
- gfc_current_block ()->name,
- &gfc_current_block ()->declared_at);
- else
- gfc_error ("The type for function %qs at %L is not accessible",
- gfc_current_block ()->name,
- &gfc_current_block ()->declared_at);
- gfc_current_block ()->ts.kind = 0;
- /* Keep the derived type; if it's bad, it will be discovered later. */
- if (!(ts->type == BT_DERIVED && ts->u.derived))
- ts->type = BT_UNKNOWN;
- }
- return st;
- }
- /* Parse a WHERE block, (not a simple WHERE statement). */
- static void
- parse_where_block (void)
- {
- int seen_empty_else;
- gfc_code *top, *d;
- gfc_state_data s;
- gfc_statement st;
- accept_statement (ST_WHERE_BLOCK);
- top = gfc_state_stack->tail;
- push_state (&s, COMP_WHERE, gfc_new_block);
- d = add_statement ();
- d->expr1 = top->expr1;
- d->op = EXEC_WHERE;
- top->expr1 = NULL;
- top->block = d;
- seen_empty_else = 0;
- do
- {
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_WHERE_BLOCK:
- parse_where_block ();
- break;
- case ST_ASSIGNMENT:
- case ST_WHERE:
- accept_statement (st);
- break;
- case ST_ELSEWHERE:
- if (seen_empty_else)
- {
- gfc_error ("ELSEWHERE statement at %C follows previous "
- "unmasked ELSEWHERE");
- reject_statement ();
- break;
- }
- if (new_st.expr1 == NULL)
- seen_empty_else = 1;
- d = new_level (gfc_state_stack->head);
- d->op = EXEC_WHERE;
- d->expr1 = new_st.expr1;
- accept_statement (st);
- break;
- case ST_END_WHERE:
- accept_statement (st);
- break;
- default:
- gfc_error ("Unexpected %s statement in WHERE block at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- break;
- }
- }
- while (st != ST_END_WHERE);
- pop_state ();
- }
- /* Parse a FORALL block (not a simple FORALL statement). */
- static void
- parse_forall_block (void)
- {
- gfc_code *top, *d;
- gfc_state_data s;
- gfc_statement st;
- accept_statement (ST_FORALL_BLOCK);
- top = gfc_state_stack->tail;
- push_state (&s, COMP_FORALL, gfc_new_block);
- d = add_statement ();
- d->op = EXEC_FORALL;
- top->block = d;
- do
- {
- st = next_statement ();
- switch (st)
- {
- case ST_ASSIGNMENT:
- case ST_POINTER_ASSIGNMENT:
- case ST_WHERE:
- case ST_FORALL:
- accept_statement (st);
- break;
- case ST_WHERE_BLOCK:
- parse_where_block ();
- break;
- case ST_FORALL_BLOCK:
- parse_forall_block ();
- break;
- case ST_END_FORALL:
- accept_statement (st);
- break;
- case ST_NONE:
- unexpected_eof ();
- default:
- gfc_error ("Unexpected %s statement in FORALL block at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- break;
- }
- }
- while (st != ST_END_FORALL);
- pop_state ();
- }
- static gfc_statement parse_executable (gfc_statement);
- /* parse the statements of an IF-THEN-ELSEIF-ELSE-ENDIF block. */
- static void
- parse_if_block (void)
- {
- gfc_code *top, *d;
- gfc_statement st;
- locus else_locus;
- gfc_state_data s;
- int seen_else;
- seen_else = 0;
- accept_statement (ST_IF_BLOCK);
- top = gfc_state_stack->tail;
- push_state (&s, COMP_IF, gfc_new_block);
- new_st.op = EXEC_IF;
- d = add_statement ();
- d->expr1 = top->expr1;
- top->expr1 = NULL;
- top->block = d;
- do
- {
- st = parse_executable (ST_NONE);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_ELSEIF:
- if (seen_else)
- {
- gfc_error_1 ("ELSE IF statement at %C cannot follow ELSE "
- "statement at %L", &else_locus);
- reject_statement ();
- break;
- }
- d = new_level (gfc_state_stack->head);
- d->op = EXEC_IF;
- d->expr1 = new_st.expr1;
- accept_statement (st);
- break;
- case ST_ELSE:
- if (seen_else)
- {
- gfc_error ("Duplicate ELSE statements at %L and %C",
- &else_locus);
- reject_statement ();
- break;
- }
- seen_else = 1;
- else_locus = gfc_current_locus;
- d = new_level (gfc_state_stack->head);
- d->op = EXEC_IF;
- accept_statement (st);
- break;
- case ST_ENDIF:
- break;
- default:
- unexpected_statement (st);
- break;
- }
- }
- while (st != ST_ENDIF);
- pop_state ();
- accept_statement (st);
- }
- /* Parse a SELECT block. */
- static void
- parse_select_block (void)
- {
- gfc_statement st;
- gfc_code *cp;
- gfc_state_data s;
- accept_statement (ST_SELECT_CASE);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_SELECT, gfc_new_block);
- /* Make sure that the next statement is a CASE or END SELECT. */
- for (;;)
- {
- st = next_statement ();
- if (st == ST_NONE)
- unexpected_eof ();
- if (st == ST_END_SELECT)
- {
- /* Empty SELECT CASE is OK. */
- accept_statement (st);
- pop_state ();
- return;
- }
- if (st == ST_CASE)
- break;
- gfc_error ("Expected a CASE or END SELECT statement following SELECT "
- "CASE at %C");
- reject_statement ();
- }
- /* At this point, we're got a nonempty select block. */
- cp = new_level (cp);
- *cp = new_st;
- accept_statement (st);
- do
- {
- st = parse_executable (ST_NONE);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_CASE:
- cp = new_level (gfc_state_stack->head);
- *cp = new_st;
- gfc_clear_new_st ();
- accept_statement (st);
- /* Fall through */
- case ST_END_SELECT:
- break;
- /* Can't have an executable statement because of
- parse_executable(). */
- default:
- unexpected_statement (st);
- break;
- }
- }
- while (st != ST_END_SELECT);
- pop_state ();
- accept_statement (st);
- }
- /* Pop the current selector from the SELECT TYPE stack. */
- static void
- select_type_pop (void)
- {
- gfc_select_type_stack *old = select_type_stack;
- select_type_stack = old->prev;
- free (old);
- }
- /* Parse a SELECT TYPE construct (F03:R821). */
- static void
- parse_select_type_block (void)
- {
- gfc_statement st;
- gfc_code *cp;
- gfc_state_data s;
- accept_statement (ST_SELECT_TYPE);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_SELECT_TYPE, gfc_new_block);
- /* Make sure that the next statement is a TYPE IS, CLASS IS, CLASS DEFAULT
- or END SELECT. */
- for (;;)
- {
- st = next_statement ();
- if (st == ST_NONE)
- unexpected_eof ();
- if (st == ST_END_SELECT)
- /* Empty SELECT CASE is OK. */
- goto done;
- if (st == ST_TYPE_IS || st == ST_CLASS_IS)
- break;
- gfc_error ("Expected TYPE IS, CLASS IS or END SELECT statement "
- "following SELECT TYPE at %C");
- reject_statement ();
- }
- /* At this point, we're got a nonempty select block. */
- cp = new_level (cp);
- *cp = new_st;
- accept_statement (st);
- do
- {
- st = parse_executable (ST_NONE);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_TYPE_IS:
- case ST_CLASS_IS:
- cp = new_level (gfc_state_stack->head);
- *cp = new_st;
- gfc_clear_new_st ();
- accept_statement (st);
- /* Fall through */
- case ST_END_SELECT:
- break;
- /* Can't have an executable statement because of
- parse_executable(). */
- default:
- unexpected_statement (st);
- break;
- }
- }
- while (st != ST_END_SELECT);
- done:
- pop_state ();
- accept_statement (st);
- gfc_current_ns = gfc_current_ns->parent;
- select_type_pop ();
- }
- /* Given a symbol, make sure it is not an iteration variable for a DO
- statement. This subroutine is called when the symbol is seen in a
- context that causes it to become redefined. If the symbol is an
- iterator, we generate an error message and return nonzero. */
- int
- gfc_check_do_variable (gfc_symtree *st)
- {
- gfc_state_data *s;
- for (s=gfc_state_stack; s; s = s->previous)
- if (s->do_variable == st)
- {
- gfc_error_now_1 ("Variable '%s' at %C cannot be redefined inside "
- "loop beginning at %L", st->name, &s->head->loc);
- return 1;
- }
- return 0;
- }
-
- /* Checks to see if the current statement label closes an enddo.
- Returns 0 if not, 1 if closes an ENDDO correctly, or 2 (and issues
- an error) if it incorrectly closes an ENDDO. */
- static int
- check_do_closure (void)
- {
- gfc_state_data *p;
- if (gfc_statement_label == NULL)
- return 0;
- for (p = gfc_state_stack; p; p = p->previous)
- if (p->state == COMP_DO || p->state == COMP_DO_CONCURRENT)
- break;
- if (p == NULL)
- return 0; /* No loops to close */
- if (p->ext.end_do_label == gfc_statement_label)
- {
- if (p == gfc_state_stack)
- return 1;
- gfc_error ("End of nonblock DO statement at %C is within another block");
- return 2;
- }
- /* At this point, the label doesn't terminate the innermost loop.
- Make sure it doesn't terminate another one. */
- for (; p; p = p->previous)
- if ((p->state == COMP_DO || p->state == COMP_DO_CONCURRENT)
- && p->ext.end_do_label == gfc_statement_label)
- {
- gfc_error ("End of nonblock DO statement at %C is interwoven "
- "with another DO loop");
- return 2;
- }
- return 0;
- }
- /* Parse a series of contained program units. */
- static void parse_progunit (gfc_statement);
- /* Parse a CRITICAL block. */
- static void
- parse_critical_block (void)
- {
- gfc_code *top, *d;
- gfc_state_data s, *sd;
- gfc_statement st;
- for (sd = gfc_state_stack; sd; sd = sd->previous)
- if (sd->state == COMP_OMP_STRUCTURED_BLOCK)
- gfc_error_now (is_oacc (sd)
- ? "CRITICAL block inside of OpenACC region at %C"
- : "CRITICAL block inside of OpenMP region at %C");
- s.ext.end_do_label = new_st.label1;
- accept_statement (ST_CRITICAL);
- top = gfc_state_stack->tail;
- push_state (&s, COMP_CRITICAL, gfc_new_block);
- d = add_statement ();
- d->op = EXEC_CRITICAL;
- top->block = d;
- do
- {
- st = parse_executable (ST_NONE);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- break;
- case ST_END_CRITICAL:
- if (s.ext.end_do_label != NULL
- && s.ext.end_do_label != gfc_statement_label)
- gfc_error_now ("Statement label in END CRITICAL at %C does not "
- "match CRITICAL label");
- if (gfc_statement_label != NULL)
- {
- new_st.op = EXEC_NOP;
- add_statement ();
- }
- break;
- default:
- unexpected_statement (st);
- break;
- }
- }
- while (st != ST_END_CRITICAL);
- pop_state ();
- accept_statement (st);
- }
- /* Set up the local namespace for a BLOCK construct. */
- gfc_namespace*
- gfc_build_block_ns (gfc_namespace *parent_ns)
- {
- gfc_namespace* my_ns;
- static int numblock = 1;
- my_ns = gfc_get_namespace (parent_ns, 1);
- my_ns->construct_entities = 1;
- /* Give the BLOCK a symbol of flavor LABEL; this is later needed for correct
- code generation (so it must not be NULL).
- We set its recursive argument if our container procedure is recursive, so
- that local variables are accordingly placed on the stack when it
- will be necessary. */
- if (gfc_new_block)
- my_ns->proc_name = gfc_new_block;
- else
- {
- bool t;
- char buffer[20]; /* Enough to hold "block@2147483648\n". */
- snprintf(buffer, sizeof(buffer), "block@%d", numblock++);
- gfc_get_symbol (buffer, my_ns, &my_ns->proc_name);
- t = gfc_add_flavor (&my_ns->proc_name->attr, FL_LABEL,
- my_ns->proc_name->name, NULL);
- gcc_assert (t);
- gfc_commit_symbol (my_ns->proc_name);
- }
- if (parent_ns->proc_name)
- my_ns->proc_name->attr.recursive = parent_ns->proc_name->attr.recursive;
- return my_ns;
- }
- /* Parse a BLOCK construct. */
- static void
- parse_block_construct (void)
- {
- gfc_namespace* my_ns;
- gfc_state_data s;
- gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C");
- my_ns = gfc_build_block_ns (gfc_current_ns);
- new_st.op = EXEC_BLOCK;
- new_st.ext.block.ns = my_ns;
- new_st.ext.block.assoc = NULL;
- accept_statement (ST_BLOCK);
- push_state (&s, COMP_BLOCK, my_ns->proc_name);
- gfc_current_ns = my_ns;
- parse_progunit (ST_NONE);
- gfc_current_ns = gfc_current_ns->parent;
- pop_state ();
- }
- /* Parse an ASSOCIATE construct. This is essentially a BLOCK construct
- behind the scenes with compiler-generated variables. */
- static void
- parse_associate (void)
- {
- gfc_namespace* my_ns;
- gfc_state_data s;
- gfc_statement st;
- gfc_association_list* a;
- gfc_notify_std (GFC_STD_F2003, "ASSOCIATE construct at %C");
- my_ns = gfc_build_block_ns (gfc_current_ns);
- new_st.op = EXEC_BLOCK;
- new_st.ext.block.ns = my_ns;
- gcc_assert (new_st.ext.block.assoc);
- /* Add all associate-names as BLOCK variables. Creating them is enough
- for now, they'll get their values during trans-* phase. */
- gfc_current_ns = my_ns;
- for (a = new_st.ext.block.assoc; a; a = a->next)
- {
- gfc_symbol* sym;
- if (gfc_get_sym_tree (a->name, NULL, &a->st, false))
- gcc_unreachable ();
- sym = a->st->n.sym;
- sym->attr.flavor = FL_VARIABLE;
- sym->assoc = a;
- sym->declared_at = a->where;
- gfc_set_sym_referenced (sym);
- /* Initialize the typespec. It is not available in all cases,
- however, as it may only be set on the target during resolution.
- Still, sometimes it helps to have it right now -- especially
- for parsing component references on the associate-name
- in case of association to a derived-type. */
- sym->ts = a->target->ts;
- }
- accept_statement (ST_ASSOCIATE);
- push_state (&s, COMP_ASSOCIATE, my_ns->proc_name);
- loop:
- st = parse_executable (ST_NONE);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case_end:
- accept_statement (st);
- my_ns->code = gfc_state_stack->head;
- break;
- default:
- unexpected_statement (st);
- goto loop;
- }
- gfc_current_ns = gfc_current_ns->parent;
- pop_state ();
- }
- /* Parse a DO loop. Note that the ST_CYCLE and ST_EXIT statements are
- handled inside of parse_executable(), because they aren't really
- loop statements. */
- static void
- parse_do_block (void)
- {
- gfc_statement st;
- gfc_code *top;
- gfc_state_data s;
- gfc_symtree *stree;
- gfc_exec_op do_op;
- do_op = new_st.op;
- s.ext.end_do_label = new_st.label1;
- if (new_st.ext.iterator != NULL)
- stree = new_st.ext.iterator->var->symtree;
- else
- stree = NULL;
- accept_statement (ST_DO);
- top = gfc_state_stack->tail;
- push_state (&s, do_op == EXEC_DO_CONCURRENT ? COMP_DO_CONCURRENT : COMP_DO,
- gfc_new_block);
- s.do_variable = stree;
- top->block = new_level (top);
- top->block->op = EXEC_DO;
- loop:
- st = parse_executable (ST_NONE);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_ENDDO:
- if (s.ext.end_do_label != NULL
- && s.ext.end_do_label != gfc_statement_label)
- gfc_error_now ("Statement label in ENDDO at %C doesn't match "
- "DO label");
- if (gfc_statement_label != NULL)
- {
- new_st.op = EXEC_NOP;
- add_statement ();
- }
- break;
- case ST_IMPLIED_ENDDO:
- /* If the do-stmt of this DO construct has a do-construct-name,
- the corresponding end-do must be an end-do-stmt (with a matching
- name, but in that case we must have seen ST_ENDDO first).
- We only complain about this in pedantic mode. */
- if (gfc_current_block () != NULL)
- gfc_error_now ("Named block DO at %L requires matching ENDDO name",
- &gfc_current_block()->declared_at);
- break;
- default:
- unexpected_statement (st);
- goto loop;
- }
- pop_state ();
- accept_statement (st);
- }
- /* Parse the statements of OpenMP do/parallel do. */
- static gfc_statement
- parse_omp_do (gfc_statement omp_st)
- {
- gfc_statement st;
- gfc_code *cp, *np;
- gfc_state_data s;
- accept_statement (omp_st);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
- np = new_level (cp);
- np->op = cp->op;
- np->block = NULL;
- for (;;)
- {
- st = next_statement ();
- if (st == ST_NONE)
- unexpected_eof ();
- else if (st == ST_DO)
- break;
- else
- unexpected_statement (st);
- }
- parse_do_block ();
- if (gfc_statement_label != NULL
- && gfc_state_stack->previous != NULL
- && gfc_state_stack->previous->state == COMP_DO
- && gfc_state_stack->previous->ext.end_do_label == gfc_statement_label)
- {
- /* In
- DO 100 I=1,10
- !$OMP DO
- DO J=1,10
- ...
- 100 CONTINUE
- there should be no !$OMP END DO. */
- pop_state ();
- return ST_IMPLIED_ENDDO;
- }
- check_do_closure ();
- pop_state ();
- st = next_statement ();
- gfc_statement omp_end_st = ST_OMP_END_DO;
- switch (omp_st)
- {
- case ST_OMP_DISTRIBUTE: omp_end_st = ST_OMP_END_DISTRIBUTE; break;
- case ST_OMP_DISTRIBUTE_PARALLEL_DO:
- omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO;
- break;
- case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_DISTRIBUTE_SIMD:
- omp_end_st = ST_OMP_END_DISTRIBUTE_SIMD;
- break;
- case ST_OMP_DO: omp_end_st = ST_OMP_END_DO; break;
- case ST_OMP_DO_SIMD: omp_end_st = ST_OMP_END_DO_SIMD; break;
- case ST_OMP_PARALLEL_DO: omp_end_st = ST_OMP_END_PARALLEL_DO; break;
- case ST_OMP_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_SIMD: omp_end_st = ST_OMP_END_SIMD; break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_SIMD;
- break;
- default: gcc_unreachable ();
- }
- if (st == omp_end_st)
- {
- if (new_st.op == EXEC_OMP_END_NOWAIT)
- cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
- else
- gcc_assert (new_st.op == EXEC_NOP);
- gfc_clear_new_st ();
- gfc_commit_symbols ();
- gfc_warning_check ();
- st = next_statement ();
- }
- return st;
- }
- /* Parse the statements of OpenMP atomic directive. */
- static gfc_statement
- parse_omp_atomic (void)
- {
- gfc_statement st;
- gfc_code *cp, *np;
- gfc_state_data s;
- int count;
- accept_statement (ST_OMP_ATOMIC);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
- np = new_level (cp);
- np->op = cp->op;
- np->block = NULL;
- count = 1 + ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- == GFC_OMP_ATOMIC_CAPTURE);
- while (count)
- {
- st = next_statement ();
- if (st == ST_NONE)
- unexpected_eof ();
- else if (st == ST_ASSIGNMENT)
- {
- accept_statement (st);
- count--;
- }
- else
- unexpected_statement (st);
- }
- pop_state ();
- st = next_statement ();
- if (st == ST_OMP_END_ATOMIC)
- {
- gfc_clear_new_st ();
- gfc_commit_symbols ();
- gfc_warning_check ();
- st = next_statement ();
- }
- else if ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- == GFC_OMP_ATOMIC_CAPTURE)
- gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
- return st;
- }
- /* Parse the statements of an OpenACC structured block. */
- static void
- parse_oacc_structured_block (gfc_statement acc_st)
- {
- gfc_statement st, acc_end_st;
- gfc_code *cp, *np;
- gfc_state_data s, *sd;
- for (sd = gfc_state_stack; sd; sd = sd->previous)
- if (sd->state == COMP_CRITICAL)
- gfc_error_now ("OpenACC directive inside of CRITICAL block at %C");
- accept_statement (acc_st);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
- np = new_level (cp);
- np->op = cp->op;
- np->block = NULL;
- switch (acc_st)
- {
- case ST_OACC_PARALLEL:
- acc_end_st = ST_OACC_END_PARALLEL;
- break;
- case ST_OACC_KERNELS:
- acc_end_st = ST_OACC_END_KERNELS;
- break;
- case ST_OACC_DATA:
- acc_end_st = ST_OACC_END_DATA;
- break;
- case ST_OACC_HOST_DATA:
- acc_end_st = ST_OACC_END_HOST_DATA;
- break;
- default:
- gcc_unreachable ();
- }
- do
- {
- st = parse_executable (ST_NONE);
- if (st == ST_NONE)
- unexpected_eof ();
- else if (st != acc_end_st)
- gfc_error ("Expecting %s at %C", gfc_ascii_statement (acc_end_st));
- reject_statement ();
- }
- while (st != acc_end_st);
- gcc_assert (new_st.op == EXEC_NOP);
- gfc_clear_new_st ();
- gfc_commit_symbols ();
- gfc_warning_check ();
- pop_state ();
- }
- /* Parse the statements of OpenACC loop/parallel loop/kernels loop. */
- static gfc_statement
- parse_oacc_loop (gfc_statement acc_st)
- {
- gfc_statement st;
- gfc_code *cp, *np;
- gfc_state_data s, *sd;
- for (sd = gfc_state_stack; sd; sd = sd->previous)
- if (sd->state == COMP_CRITICAL)
- gfc_error_now ("OpenACC directive inside of CRITICAL block at %C");
- accept_statement (acc_st);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
- np = new_level (cp);
- np->op = cp->op;
- np->block = NULL;
- for (;;)
- {
- st = next_statement ();
- if (st == ST_NONE)
- unexpected_eof ();
- else if (st == ST_DO)
- break;
- else
- {
- gfc_error ("Expected DO loop at %C");
- reject_statement ();
- }
- }
- parse_do_block ();
- if (gfc_statement_label != NULL
- && gfc_state_stack->previous != NULL
- && gfc_state_stack->previous->state == COMP_DO
- && gfc_state_stack->previous->ext.end_do_label == gfc_statement_label)
- {
- pop_state ();
- return ST_IMPLIED_ENDDO;
- }
- check_do_closure ();
- pop_state ();
- st = next_statement ();
- if (st == ST_OACC_END_LOOP)
- gfc_warning (0, "Redundant !$ACC END LOOP at %C");
- if ((acc_st == ST_OACC_PARALLEL_LOOP && st == ST_OACC_END_PARALLEL_LOOP) ||
- (acc_st == ST_OACC_KERNELS_LOOP && st == ST_OACC_END_KERNELS_LOOP) ||
- (acc_st == ST_OACC_LOOP && st == ST_OACC_END_LOOP))
- {
- gcc_assert (new_st.op == EXEC_NOP);
- gfc_clear_new_st ();
- gfc_commit_symbols ();
- gfc_warning_check ();
- st = next_statement ();
- }
- return st;
- }
- /* Parse the statements of an OpenMP structured block. */
- static void
- parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
- {
- gfc_statement st, omp_end_st;
- gfc_code *cp, *np;
- gfc_state_data s;
- accept_statement (omp_st);
- cp = gfc_state_stack->tail;
- push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
- np = new_level (cp);
- np->op = cp->op;
- np->block = NULL;
- switch (omp_st)
- {
- case ST_OMP_PARALLEL:
- omp_end_st = ST_OMP_END_PARALLEL;
- break;
- case ST_OMP_PARALLEL_SECTIONS:
- omp_end_st = ST_OMP_END_PARALLEL_SECTIONS;
- break;
- case ST_OMP_SECTIONS:
- omp_end_st = ST_OMP_END_SECTIONS;
- break;
- case ST_OMP_ORDERED:
- omp_end_st = ST_OMP_END_ORDERED;
- break;
- case ST_OMP_CRITICAL:
- omp_end_st = ST_OMP_END_CRITICAL;
- break;
- case ST_OMP_MASTER:
- omp_end_st = ST_OMP_END_MASTER;
- break;
- case ST_OMP_SINGLE:
- omp_end_st = ST_OMP_END_SINGLE;
- break;
- case ST_OMP_TARGET:
- omp_end_st = ST_OMP_END_TARGET;
- break;
- case ST_OMP_TARGET_DATA:
- omp_end_st = ST_OMP_END_TARGET_DATA;
- break;
- case ST_OMP_TARGET_TEAMS:
- omp_end_st = ST_OMP_END_TARGET_TEAMS;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD;
- break;
- case ST_OMP_TASK:
- omp_end_st = ST_OMP_END_TASK;
- break;
- case ST_OMP_TASKGROUP:
- omp_end_st = ST_OMP_END_TASKGROUP;
- break;
- case ST_OMP_TEAMS:
- omp_end_st = ST_OMP_END_TEAMS;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
- omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_SIMD;
- break;
- case ST_OMP_DISTRIBUTE:
- omp_end_st = ST_OMP_END_DISTRIBUTE;
- break;
- case ST_OMP_DISTRIBUTE_PARALLEL_DO:
- omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO;
- break;
- case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD;
- break;
- case ST_OMP_DISTRIBUTE_SIMD:
- omp_end_st = ST_OMP_END_DISTRIBUTE_SIMD;
- break;
- case ST_OMP_WORKSHARE:
- omp_end_st = ST_OMP_END_WORKSHARE;
- break;
- case ST_OMP_PARALLEL_WORKSHARE:
- omp_end_st = ST_OMP_END_PARALLEL_WORKSHARE;
- break;
- default:
- gcc_unreachable ();
- }
- do
- {
- if (workshare_stmts_only)
- {
- /* Inside of !$omp workshare, only
- scalar assignments
- array assignments
- where statements and constructs
- forall statements and constructs
- !$omp atomic
- !$omp critical
- !$omp parallel
- are allowed. For !$omp critical these
- restrictions apply recursively. */
- bool cycle = true;
- st = next_statement ();
- for (;;)
- {
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_ASSIGNMENT:
- case ST_WHERE:
- case ST_FORALL:
- accept_statement (st);
- break;
- case ST_WHERE_BLOCK:
- parse_where_block ();
- break;
- case ST_FORALL_BLOCK:
- parse_forall_block ();
- break;
- case ST_OMP_PARALLEL:
- case ST_OMP_PARALLEL_SECTIONS:
- parse_omp_structured_block (st, false);
- break;
- case ST_OMP_PARALLEL_WORKSHARE:
- case ST_OMP_CRITICAL:
- parse_omp_structured_block (st, true);
- break;
- case ST_OMP_PARALLEL_DO:
- case ST_OMP_PARALLEL_DO_SIMD:
- st = parse_omp_do (st);
- continue;
- case ST_OMP_ATOMIC:
- st = parse_omp_atomic ();
- continue;
- default:
- cycle = false;
- break;
- }
- if (!cycle)
- break;
- st = next_statement ();
- }
- }
- else
- st = parse_executable (ST_NONE);
- if (st == ST_NONE)
- unexpected_eof ();
- else if (st == ST_OMP_SECTION
- && (omp_st == ST_OMP_SECTIONS
- || omp_st == ST_OMP_PARALLEL_SECTIONS))
- {
- np = new_level (np);
- np->op = cp->op;
- np->block = NULL;
- }
- else if (st != omp_end_st)
- unexpected_statement (st);
- }
- while (st != omp_end_st);
- switch (new_st.op)
- {
- case EXEC_OMP_END_NOWAIT:
- cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
- break;
- case EXEC_OMP_CRITICAL:
- if (((cp->ext.omp_name == NULL) ^ (new_st.ext.omp_name == NULL))
- || (new_st.ext.omp_name != NULL
- && strcmp (cp->ext.omp_name, new_st.ext.omp_name) != 0))
- gfc_error ("Name after !$omp critical and !$omp end critical does "
- "not match at %C");
- free (CONST_CAST (char *, new_st.ext.omp_name));
- break;
- case EXEC_OMP_END_SINGLE:
- cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE]
- = new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE];
- new_st.ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE] = NULL;
- gfc_free_omp_clauses (new_st.ext.omp_clauses);
- break;
- case EXEC_NOP:
- break;
- default:
- gcc_unreachable ();
- }
- gfc_clear_new_st ();
- gfc_commit_symbols ();
- gfc_warning_check ();
- pop_state ();
- }
- /* Accept a series of executable statements. We return the first
- statement that doesn't fit to the caller. Any block statements are
- passed on to the correct handler, which usually passes the buck
- right back here. */
- static gfc_statement
- parse_executable (gfc_statement st)
- {
- int close_flag;
- if (st == ST_NONE)
- st = next_statement ();
- for (;;)
- {
- close_flag = check_do_closure ();
- if (close_flag)
- switch (st)
- {
- case ST_GOTO:
- case ST_END_PROGRAM:
- case ST_RETURN:
- case ST_EXIT:
- case ST_END_FUNCTION:
- case ST_CYCLE:
- case ST_PAUSE:
- case ST_STOP:
- case ST_ERROR_STOP:
- case ST_END_SUBROUTINE:
- case ST_DO:
- case ST_FORALL:
- case ST_WHERE:
- case ST_SELECT_CASE:
- gfc_error ("%s statement at %C cannot terminate a non-block "
- "DO loop", gfc_ascii_statement (st));
- break;
- default:
- break;
- }
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_DATA:
- gfc_notify_std (GFC_STD_F95_OBS, "DATA statement at %C after the "
- "first executable statement");
- /* Fall through. */
- case ST_FORMAT:
- case ST_ENTRY:
- case_executable:
- accept_statement (st);
- if (close_flag == 1)
- return ST_IMPLIED_ENDDO;
- break;
- case ST_BLOCK:
- parse_block_construct ();
- break;
- case ST_ASSOCIATE:
- parse_associate ();
- break;
- case ST_IF_BLOCK:
- parse_if_block ();
- break;
- case ST_SELECT_CASE:
- parse_select_block ();
- break;
- case ST_SELECT_TYPE:
- parse_select_type_block();
- break;
- case ST_DO:
- parse_do_block ();
- if (check_do_closure () == 1)
- return ST_IMPLIED_ENDDO;
- break;
- case ST_CRITICAL:
- parse_critical_block ();
- break;
- case ST_WHERE_BLOCK:
- parse_where_block ();
- break;
- case ST_FORALL_BLOCK:
- parse_forall_block ();
- break;
- case ST_OACC_PARALLEL_LOOP:
- case ST_OACC_KERNELS_LOOP:
- case ST_OACC_LOOP:
- st = parse_oacc_loop (st);
- if (st == ST_IMPLIED_ENDDO)
- return st;
- continue;
- case ST_OACC_PARALLEL:
- case ST_OACC_KERNELS:
- case ST_OACC_DATA:
- case ST_OACC_HOST_DATA:
- parse_oacc_structured_block (st);
- break;
- case ST_OMP_PARALLEL:
- case ST_OMP_PARALLEL_SECTIONS:
- case ST_OMP_SECTIONS:
- case ST_OMP_ORDERED:
- case ST_OMP_CRITICAL:
- case ST_OMP_MASTER:
- case ST_OMP_SINGLE:
- case ST_OMP_TARGET:
- case ST_OMP_TARGET_DATA:
- case ST_OMP_TARGET_TEAMS:
- case ST_OMP_TEAMS:
- case ST_OMP_TASK:
- case ST_OMP_TASKGROUP:
- parse_omp_structured_block (st, false);
- break;
- case ST_OMP_WORKSHARE:
- case ST_OMP_PARALLEL_WORKSHARE:
- parse_omp_structured_block (st, true);
- break;
- case ST_OMP_DISTRIBUTE:
- case ST_OMP_DISTRIBUTE_PARALLEL_DO:
- case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- case ST_OMP_DISTRIBUTE_SIMD:
- case ST_OMP_DO:
- case ST_OMP_DO_SIMD:
- case ST_OMP_PARALLEL_DO:
- case ST_OMP_PARALLEL_DO_SIMD:
- case ST_OMP_SIMD:
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- case ST_OMP_TEAMS_DISTRIBUTE:
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
- st = parse_omp_do (st);
- if (st == ST_IMPLIED_ENDDO)
- return st;
- continue;
- case ST_OMP_ATOMIC:
- st = parse_omp_atomic ();
- continue;
- default:
- return st;
- }
- st = next_statement ();
- }
- }
- /* Fix the symbols for sibling functions. These are incorrectly added to
- the child namespace as the parser didn't know about this procedure. */
- static void
- gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
- {
- gfc_namespace *ns;
- gfc_symtree *st;
- gfc_symbol *old_sym;
- for (ns = siblings; ns; ns = ns->sibling)
- {
- st = gfc_find_symtree (ns->sym_root, sym->name);
- if (!st || (st->n.sym->attr.dummy && ns == st->n.sym->ns))
- goto fixup_contained;
- if ((st->n.sym->attr.flavor == FL_DERIVED
- && sym->attr.generic && sym->attr.function)
- ||(sym->attr.flavor == FL_DERIVED
- && st->n.sym->attr.generic && st->n.sym->attr.function))
- goto fixup_contained;
- old_sym = st->n.sym;
- if (old_sym->ns == ns
- && !old_sym->attr.contained
- /* By 14.6.1.3, host association should be excluded
- for the following. */
- && !(old_sym->attr.external
- || (old_sym->ts.type != BT_UNKNOWN
- && !old_sym->attr.implicit_type)
- || old_sym->attr.flavor == FL_PARAMETER
- || old_sym->attr.use_assoc
- || old_sym->attr.in_common
- || old_sym->attr.in_equivalence
- || old_sym->attr.data
- || old_sym->attr.dummy
- || old_sym->attr.result
- || old_sym->attr.dimension
- || old_sym->attr.allocatable
- || old_sym->attr.intrinsic
- || old_sym->attr.generic
- || old_sym->attr.flavor == FL_NAMELIST
- || old_sym->attr.flavor == FL_LABEL
- || old_sym->attr.proc == PROC_ST_FUNCTION))
- {
- /* Replace it with the symbol from the parent namespace. */
- st->n.sym = sym;
- sym->refs++;
- gfc_release_symbol (old_sym);
- }
- fixup_contained:
- /* Do the same for any contained procedures. */
- gfc_fixup_sibling_symbols (sym, ns->contained);
- }
- }
- static void
- parse_contained (int module)
- {
- gfc_namespace *ns, *parent_ns, *tmp;
- gfc_state_data s1, s2;
- gfc_statement st;
- gfc_symbol *sym;
- gfc_entry_list *el;
- int contains_statements = 0;
- int seen_error = 0;
- push_state (&s1, COMP_CONTAINS, NULL);
- parent_ns = gfc_current_ns;
- do
- {
- gfc_current_ns = gfc_get_namespace (parent_ns, 1);
- gfc_current_ns->sibling = parent_ns->contained;
- parent_ns->contained = gfc_current_ns;
- next:
- /* Process the next available statement. We come here if we got an error
- and rejected the last statement. */
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_FUNCTION:
- case ST_SUBROUTINE:
- contains_statements = 1;
- accept_statement (st);
- push_state (&s2,
- (st == ST_FUNCTION) ? COMP_FUNCTION : COMP_SUBROUTINE,
- gfc_new_block);
- /* For internal procedures, create/update the symbol in the
- parent namespace. */
- if (!module)
- {
- if (gfc_get_symbol (gfc_new_block->name, parent_ns, &sym))
- gfc_error ("Contained procedure %qs at %C is already "
- "ambiguous", gfc_new_block->name);
- else
- {
- if (gfc_add_procedure (&sym->attr, PROC_INTERNAL,
- sym->name,
- &gfc_new_block->declared_at))
- {
- if (st == ST_FUNCTION)
- gfc_add_function (&sym->attr, sym->name,
- &gfc_new_block->declared_at);
- else
- gfc_add_subroutine (&sym->attr, sym->name,
- &gfc_new_block->declared_at);
- }
- }
- gfc_commit_symbols ();
- }
- else
- sym = gfc_new_block;
- /* Mark this as a contained function, so it isn't replaced
- by other module functions. */
- sym->attr.contained = 1;
- /* Set implicit_pure so that it can be reset if any of the
- tests for purity fail. This is used for some optimisation
- during translation. */
- if (!sym->attr.pure)
- sym->attr.implicit_pure = 1;
- parse_progunit (ST_NONE);
- /* Fix up any sibling functions that refer to this one. */
- gfc_fixup_sibling_symbols (sym, gfc_current_ns);
- /* Or refer to any of its alternate entry points. */
- for (el = gfc_current_ns->entries; el; el = el->next)
- gfc_fixup_sibling_symbols (el->sym, gfc_current_ns);
- gfc_current_ns->code = s2.head;
- gfc_current_ns = parent_ns;
- pop_state ();
- break;
- /* These statements are associated with the end of the host unit. */
- case ST_END_FUNCTION:
- case ST_END_MODULE:
- case ST_END_PROGRAM:
- case ST_END_SUBROUTINE:
- accept_statement (st);
- gfc_current_ns->code = s1.head;
- break;
- default:
- gfc_error ("Unexpected %s statement in CONTAINS section at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- seen_error = 1;
- goto next;
- break;
- }
- }
- while (st != ST_END_FUNCTION && st != ST_END_SUBROUTINE
- && st != ST_END_MODULE && st != ST_END_PROGRAM);
- /* The first namespace in the list is guaranteed to not have
- anything (worthwhile) in it. */
- tmp = gfc_current_ns;
- gfc_current_ns = parent_ns;
- if (seen_error && tmp->refs > 1)
- gfc_free_namespace (tmp);
- ns = gfc_current_ns->contained;
- gfc_current_ns->contained = ns->sibling;
- gfc_free_namespace (ns);
- pop_state ();
- if (!contains_statements)
- gfc_notify_std (GFC_STD_F2008, "CONTAINS statement without "
- "FUNCTION or SUBROUTINE statement at %C");
- }
- /* Parse a PROGRAM, SUBROUTINE, FUNCTION unit or BLOCK construct. */
- static void
- parse_progunit (gfc_statement st)
- {
- gfc_state_data *p;
- int n;
- st = parse_spec (st);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_CONTAINS:
- /* This is not allowed within BLOCK! */
- if (gfc_current_state () != COMP_BLOCK)
- goto contains;
- break;
- case_end:
- accept_statement (st);
- goto done;
- default:
- break;
- }
- if (gfc_current_state () == COMP_FUNCTION)
- gfc_check_function_type (gfc_current_ns);
- loop:
- for (;;)
- {
- st = parse_executable (st);
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_CONTAINS:
- /* This is not allowed within BLOCK! */
- if (gfc_current_state () != COMP_BLOCK)
- goto contains;
- break;
- case_end:
- accept_statement (st);
- goto done;
- default:
- break;
- }
- unexpected_statement (st);
- reject_statement ();
- st = next_statement ();
- }
- contains:
- n = 0;
- for (p = gfc_state_stack; p; p = p->previous)
- if (p->state == COMP_CONTAINS)
- n++;
- if (gfc_find_state (COMP_MODULE) == true)
- n--;
- if (n > 0)
- {
- gfc_error ("CONTAINS statement at %C is already in a contained "
- "program unit");
- reject_statement ();
- st = next_statement ();
- goto loop;
- }
- parse_contained (0);
- done:
- gfc_current_ns->code = gfc_state_stack->head;
- if (gfc_state_stack->state == COMP_PROGRAM
- || gfc_state_stack->state == COMP_MODULE
- || gfc_state_stack->state == COMP_SUBROUTINE
- || gfc_state_stack->state == COMP_FUNCTION
- || gfc_state_stack->state == COMP_BLOCK)
- gfc_current_ns->oacc_declare_clauses
- = gfc_state_stack->ext.oacc_declare_clauses;
- }
- /* Come here to complain about a global symbol already in use as
- something else. */
- void
- gfc_global_used (gfc_gsymbol *sym, locus *where)
- {
- const char *name;
- if (where == NULL)
- where = &gfc_current_locus;
- switch(sym->type)
- {
- case GSYM_PROGRAM:
- name = "PROGRAM";
- break;
- case GSYM_FUNCTION:
- name = "FUNCTION";
- break;
- case GSYM_SUBROUTINE:
- name = "SUBROUTINE";
- break;
- case GSYM_COMMON:
- name = "COMMON";
- break;
- case GSYM_BLOCK_DATA:
- name = "BLOCK DATA";
- break;
- case GSYM_MODULE:
- name = "MODULE";
- break;
- default:
- gfc_internal_error ("gfc_global_used(): Bad type");
- name = NULL;
- }
- if (sym->binding_label)
- gfc_error_1 ("Global binding name '%s' at %L is already being used as a %s "
- "at %L", sym->binding_label, where, name, &sym->where);
- else
- gfc_error_1 ("Global name '%s' at %L is already being used as a %s at %L",
- sym->name, where, name, &sym->where);
- }
- /* Parse a block data program unit. */
- static void
- parse_block_data (void)
- {
- gfc_statement st;
- static locus blank_locus;
- static int blank_block=0;
- gfc_gsymbol *s;
- gfc_current_ns->proc_name = gfc_new_block;
- gfc_current_ns->is_block_data = 1;
- if (gfc_new_block == NULL)
- {
- if (blank_block)
- gfc_error ("Blank BLOCK DATA at %C conflicts with "
- "prior BLOCK DATA at %L", &blank_locus);
- else
- {
- blank_block = 1;
- blank_locus = gfc_current_locus;
- }
- }
- else
- {
- s = gfc_get_gsymbol (gfc_new_block->name);
- if (s->defined
- || (s->type != GSYM_UNKNOWN && s->type != GSYM_BLOCK_DATA))
- gfc_global_used (s, &gfc_new_block->declared_at);
- else
- {
- s->type = GSYM_BLOCK_DATA;
- s->where = gfc_new_block->declared_at;
- s->defined = 1;
- }
- }
- st = parse_spec (ST_NONE);
- while (st != ST_END_BLOCK_DATA)
- {
- gfc_error ("Unexpected %s statement in BLOCK DATA at %C",
- gfc_ascii_statement (st));
- reject_statement ();
- st = next_statement ();
- }
- }
- /* Parse a module subprogram. */
- static void
- parse_module (void)
- {
- gfc_statement st;
- gfc_gsymbol *s;
- bool error;
- s = gfc_get_gsymbol (gfc_new_block->name);
- if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_MODULE))
- gfc_global_used (s, &gfc_new_block->declared_at);
- else
- {
- s->type = GSYM_MODULE;
- s->where = gfc_new_block->declared_at;
- s->defined = 1;
- }
- st = parse_spec (ST_NONE);
- error = false;
- loop:
- switch (st)
- {
- case ST_NONE:
- unexpected_eof ();
- case ST_CONTAINS:
- parse_contained (1);
- break;
- case ST_END_MODULE:
- accept_statement (st);
- break;
- default:
- gfc_error ("Unexpected %s statement in MODULE at %C",
- gfc_ascii_statement (st));
- error = true;
- reject_statement ();
- st = next_statement ();
- goto loop;
- }
- /* Make sure not to free the namespace twice on error. */
- if (!error)
- s->ns = gfc_current_ns;
- }
- /* Add a procedure name to the global symbol table. */
- static void
- add_global_procedure (bool sub)
- {
- gfc_gsymbol *s;
- /* Only in Fortran 2003: For procedures with a binding label also the Fortran
- name is a global identifier. */
- if (!gfc_new_block->binding_label || gfc_notification_std (GFC_STD_F2008))
- {
- s = gfc_get_gsymbol (gfc_new_block->name);
- if (s->defined
- || (s->type != GSYM_UNKNOWN
- && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
- {
- gfc_global_used (s, &gfc_new_block->declared_at);
- /* Silence follow-up errors. */
- gfc_new_block->binding_label = NULL;
- }
- else
- {
- s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
- s->sym_name = gfc_new_block->name;
- s->where = gfc_new_block->declared_at;
- s->defined = 1;
- s->ns = gfc_current_ns;
- }
- }
- /* Don't add the symbol multiple times. */
- if (gfc_new_block->binding_label
- && (!gfc_notification_std (GFC_STD_F2008)
- || strcmp (gfc_new_block->name, gfc_new_block->binding_label) != 0))
- {
- s = gfc_get_gsymbol (gfc_new_block->binding_label);
- if (s->defined
- || (s->type != GSYM_UNKNOWN
- && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
- {
- gfc_global_used (s, &gfc_new_block->declared_at);
- /* Silence follow-up errors. */
- gfc_new_block->binding_label = NULL;
- }
- else
- {
- s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
- s->sym_name = gfc_new_block->name;
- s->binding_label = gfc_new_block->binding_label;
- s->where = gfc_new_block->declared_at;
- s->defined = 1;
- s->ns = gfc_current_ns;
- }
- }
- }
- /* Add a program to the global symbol table. */
- static void
- add_global_program (void)
- {
- gfc_gsymbol *s;
- if (gfc_new_block == NULL)
- return;
- s = gfc_get_gsymbol (gfc_new_block->name);
- if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_PROGRAM))
- gfc_global_used (s, &gfc_new_block->declared_at);
- else
- {
- s->type = GSYM_PROGRAM;
- s->where = gfc_new_block->declared_at;
- s->defined = 1;
- s->ns = gfc_current_ns;
- }
- }
- /* Resolve all the program units. */
- static void
- resolve_all_program_units (gfc_namespace *gfc_global_ns_list)
- {
- gfc_free_dt_list ();
- gfc_current_ns = gfc_global_ns_list;
- for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
- {
- if (gfc_current_ns->proc_name
- && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
- continue; /* Already resolved. */
- if (gfc_current_ns->proc_name)
- gfc_current_locus = gfc_current_ns->proc_name->declared_at;
- gfc_resolve (gfc_current_ns);
- gfc_current_ns->derived_types = gfc_derived_types;
- gfc_derived_types = NULL;
- }
- }
- static void
- clean_up_modules (gfc_gsymbol *gsym)
- {
- if (gsym == NULL)
- return;
- clean_up_modules (gsym->left);
- clean_up_modules (gsym->right);
- if (gsym->type != GSYM_MODULE || !gsym->ns)
- return;
- gfc_current_ns = gsym->ns;
- gfc_derived_types = gfc_current_ns->derived_types;
- gfc_done_2 ();
- gsym->ns = NULL;
- return;
- }
- /* Translate all the program units. This could be in a different order
- to resolution if there are forward references in the file. */
- static void
- translate_all_program_units (gfc_namespace *gfc_global_ns_list)
- {
- int errors;
- gfc_current_ns = gfc_global_ns_list;
- gfc_get_errors (NULL, &errors);
- /* We first translate all modules to make sure that later parts
- of the program can use the decl. Then we translate the nonmodules. */
- for (; !errors && gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
- {
- if (!gfc_current_ns->proc_name
- || gfc_current_ns->proc_name->attr.flavor != FL_MODULE)
- continue;
- gfc_current_locus = gfc_current_ns->proc_name->declared_at;
- gfc_derived_types = gfc_current_ns->derived_types;
- gfc_generate_module_code (gfc_current_ns);
- gfc_current_ns->translated = 1;
- }
- gfc_current_ns = gfc_global_ns_list;
- for (; !errors && gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
- {
- if (gfc_current_ns->proc_name
- && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
- continue;
- gfc_current_locus = gfc_current_ns->proc_name->declared_at;
- gfc_derived_types = gfc_current_ns->derived_types;
- gfc_generate_code (gfc_current_ns);
- gfc_current_ns->translated = 1;
- }
- /* Clean up all the namespaces after translation. */
- gfc_current_ns = gfc_global_ns_list;
- for (;gfc_current_ns;)
- {
- gfc_namespace *ns;
- if (gfc_current_ns->proc_name
- && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
- {
- gfc_current_ns = gfc_current_ns->sibling;
- continue;
- }
- ns = gfc_current_ns->sibling;
- gfc_derived_types = gfc_current_ns->derived_types;
- gfc_done_2 ();
- gfc_current_ns = ns;
- }
- clean_up_modules (gfc_gsym_root);
- }
- /* Top level parser. */
- bool
- gfc_parse_file (void)
- {
- int seen_program, errors_before, errors;
- gfc_state_data top, s;
- gfc_statement st;
- locus prog_locus;
- gfc_namespace *next;
- gfc_start_source_files ();
- top.state = COMP_NONE;
- top.sym = NULL;
- top.previous = NULL;
- top.head = top.tail = NULL;
- top.do_variable = NULL;
- gfc_state_stack = ⊤
- gfc_clear_new_st ();
- gfc_statement_label = NULL;
- if (setjmp (eof_buf))
- return false; /* Come here on unexpected EOF */
- /* Prepare the global namespace that will contain the
- program units. */
- gfc_global_ns_list = next = NULL;
- seen_program = 0;
- errors_before = 0;
- /* Exit early for empty files. */
- if (gfc_at_eof ())
- goto done;
- loop:
- gfc_init_2 ();
- st = next_statement ();
- switch (st)
- {
- case ST_NONE:
- gfc_done_2 ();
- goto done;
- case ST_PROGRAM:
- if (seen_program)
- goto duplicate_main;
- seen_program = 1;
- prog_locus = gfc_current_locus;
- push_state (&s, COMP_PROGRAM, gfc_new_block);
- main_program_symbol(gfc_current_ns, gfc_new_block->name);
- accept_statement (st);
- add_global_program ();
- parse_progunit (ST_NONE);
- goto prog_units;
- break;
- case ST_SUBROUTINE:
- add_global_procedure (true);
- push_state (&s, COMP_SUBROUTINE, gfc_new_block);
- accept_statement (st);
- parse_progunit (ST_NONE);
- goto prog_units;
- break;
- case ST_FUNCTION:
- add_global_procedure (false);
- push_state (&s, COMP_FUNCTION, gfc_new_block);
- accept_statement (st);
- parse_progunit (ST_NONE);
- goto prog_units;
- break;
- case ST_BLOCK_DATA:
- push_state (&s, COMP_BLOCK_DATA, gfc_new_block);
- accept_statement (st);
- parse_block_data ();
- break;
- case ST_MODULE:
- push_state (&s, COMP_MODULE, gfc_new_block);
- accept_statement (st);
- gfc_get_errors (NULL, &errors_before);
- parse_module ();
- break;
- /* Anything else starts a nameless main program block. */
- default:
- if (seen_program)
- goto duplicate_main;
- seen_program = 1;
- prog_locus = gfc_current_locus;
- push_state (&s, COMP_PROGRAM, gfc_new_block);
- main_program_symbol (gfc_current_ns, "MAIN__");
- parse_progunit (st);
- goto prog_units;
- break;
- }
- /* Handle the non-program units. */
- gfc_current_ns->code = s.head;
- gfc_resolve (gfc_current_ns);
- /* Dump the parse tree if requested. */
- if (flag_dump_fortran_original)
- gfc_dump_parse_tree (gfc_current_ns, stdout);
- gfc_get_errors (NULL, &errors);
- if (s.state == COMP_MODULE)
- {
- gfc_dump_module (s.sym->name, errors_before == errors);
- gfc_current_ns->derived_types = gfc_derived_types;
- gfc_derived_types = NULL;
- goto prog_units;
- }
- else
- {
- if (errors == 0)
- gfc_generate_code (gfc_current_ns);
- pop_state ();
- gfc_done_2 ();
- }
- goto loop;
- prog_units:
- /* The main program and non-contained procedures are put
- in the global namespace list, so that they can be processed
- later and all their interfaces resolved. */
- gfc_current_ns->code = s.head;
- if (next)
- {
- for (; next->sibling; next = next->sibling)
- ;
- next->sibling = gfc_current_ns;
- }
- else
- gfc_global_ns_list = gfc_current_ns;
- next = gfc_current_ns;
- pop_state ();
- goto loop;
- done:
- /* Do the resolution. */
- resolve_all_program_units (gfc_global_ns_list);
- /* Do the parse tree dump. */
- gfc_current_ns
- = flag_dump_fortran_original ? gfc_global_ns_list : NULL;
- for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
- if (!gfc_current_ns->proc_name
- || gfc_current_ns->proc_name->attr.flavor != FL_MODULE)
- {
- gfc_dump_parse_tree (gfc_current_ns, stdout);
- fputs ("------------------------------------------\n\n", stdout);
- }
- /* Do the translation. */
- translate_all_program_units (gfc_global_ns_list);
- gfc_end_source_files ();
- return true;
- duplicate_main:
- /* If we see a duplicate main program, shut down. If the second
- instance is an implied main program, i.e. data decls or executable
- statements, we're in for lots of errors. */
- gfc_error_1 ("Two main PROGRAMs at %L and %C", &prog_locus);
- reject_statement ();
- gfc_done_2 ();
- return true;
- }
- /* Return true if this state data represents an OpenACC region. */
- bool
- is_oacc (gfc_state_data *sd)
- {
- switch (sd->construct->op)
- {
- case EXEC_OACC_PARALLEL_LOOP:
- case EXEC_OACC_PARALLEL:
- case EXEC_OACC_KERNELS_LOOP:
- case EXEC_OACC_KERNELS:
- case EXEC_OACC_DATA:
- case EXEC_OACC_HOST_DATA:
- case EXEC_OACC_LOOP:
- case EXEC_OACC_UPDATE:
- case EXEC_OACC_WAIT:
- case EXEC_OACC_CACHE:
- case EXEC_OACC_ENTER_DATA:
- case EXEC_OACC_EXIT_DATA:
- return true;
- default:
- return false;
- }
- }
|