123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628 |
- //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements decl-related attribute processing.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/AST/ASTConsumer.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/ASTMutationListener.h"
- #include "clang/AST/CXXInheritance.h"
- #include "clang/AST/DeclCXX.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/Expr.h"
- #include "clang/AST/ExprCXX.h"
- #include "clang/AST/Mangle.h"
- #include "clang/AST/RecursiveASTVisitor.h"
- #include "clang/Basic/CharInfo.h"
- #include "clang/Basic/SourceManager.h"
- #include "clang/Basic/TargetInfo.h"
- #include "clang/Lex/Preprocessor.h"
- #include "clang/Sema/DeclSpec.h"
- #include "clang/Sema/DelayedDiagnostic.h"
- #include "clang/Sema/Initialization.h"
- #include "clang/Sema/Lookup.h"
- #include "clang/Sema/Scope.h"
- #include "clang/Sema/ScopeInfo.h"
- #include "clang/Sema/SemaInternal.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/Support/MathExtras.h"
- using namespace clang;
- using namespace sema;
- namespace AttributeLangSupport {
- enum LANG {
- C,
- Cpp,
- ObjC
- };
- } // end namespace AttributeLangSupport
- //===----------------------------------------------------------------------===//
- // Helper functions
- //===----------------------------------------------------------------------===//
- /// isFunctionOrMethod - Return true if the given decl has function
- /// type (function or function-typed variable) or an Objective-C
- /// method.
- static bool isFunctionOrMethod(const Decl *D) {
- return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
- }
- /// Return true if the given decl has function type (function or
- /// function-typed variable) or an Objective-C method or a block.
- static bool isFunctionOrMethodOrBlock(const Decl *D) {
- return isFunctionOrMethod(D) || isa<BlockDecl>(D);
- }
- /// Return true if the given decl has a declarator that should have
- /// been processed by Sema::GetTypeForDeclarator.
- static bool hasDeclarator(const Decl *D) {
- // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
- return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) ||
- isa<ObjCPropertyDecl>(D);
- }
- /// hasFunctionProto - Return true if the given decl has a argument
- /// information. This decl should have already passed
- /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
- static bool hasFunctionProto(const Decl *D) {
- if (const FunctionType *FnTy = D->getFunctionType())
- return isa<FunctionProtoType>(FnTy);
- return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
- }
- /// getFunctionOrMethodNumParams - Return number of function or method
- /// parameters. It is an error to call this on a K&R function (use
- /// hasFunctionProto first).
- static unsigned getFunctionOrMethodNumParams(const Decl *D) {
- if (const FunctionType *FnTy = D->getFunctionType())
- return cast<FunctionProtoType>(FnTy)->getNumParams();
- if (const auto *BD = dyn_cast<BlockDecl>(D))
- return BD->getNumParams();
- return cast<ObjCMethodDecl>(D)->param_size();
- }
- static const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
- unsigned Idx) {
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- return FD->getParamDecl(Idx);
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
- return MD->getParamDecl(Idx);
- if (const auto *BD = dyn_cast<BlockDecl>(D))
- return BD->getParamDecl(Idx);
- return nullptr;
- }
- static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
- if (const FunctionType *FnTy = D->getFunctionType())
- return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
- if (const auto *BD = dyn_cast<BlockDecl>(D))
- return BD->getParamDecl(Idx)->getType();
- return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
- }
- static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
- if (auto *PVD = getFunctionOrMethodParam(D, Idx))
- return PVD->getSourceRange();
- return SourceRange();
- }
- static QualType getFunctionOrMethodResultType(const Decl *D) {
- if (const FunctionType *FnTy = D->getFunctionType())
- return FnTy->getReturnType();
- return cast<ObjCMethodDecl>(D)->getReturnType();
- }
- static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- return FD->getReturnTypeSourceRange();
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
- return MD->getReturnTypeSourceRange();
- return SourceRange();
- }
- static bool isFunctionOrMethodVariadic(const Decl *D) {
- if (const FunctionType *FnTy = D->getFunctionType())
- return cast<FunctionProtoType>(FnTy)->isVariadic();
- if (const auto *BD = dyn_cast<BlockDecl>(D))
- return BD->isVariadic();
- return cast<ObjCMethodDecl>(D)->isVariadic();
- }
- static bool isInstanceMethod(const Decl *D) {
- if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
- return MethodDecl->isInstance();
- return false;
- }
- static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
- const auto *PT = T->getAs<ObjCObjectPointerType>();
- if (!PT)
- return false;
- ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
- if (!Cls)
- return false;
- IdentifierInfo* ClsName = Cls->getIdentifier();
- // FIXME: Should we walk the chain of classes?
- return ClsName == &Ctx.Idents.get("NSString") ||
- ClsName == &Ctx.Idents.get("NSMutableString");
- }
- static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
- const auto *PT = T->getAs<PointerType>();
- if (!PT)
- return false;
- const auto *RT = PT->getPointeeType()->getAs<RecordType>();
- if (!RT)
- return false;
- const RecordDecl *RD = RT->getDecl();
- if (RD->getTagKind() != TTK_Struct)
- return false;
- return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
- }
- static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
- // FIXME: Include the type in the argument list.
- return AL.getNumArgs() + AL.hasParsedType();
- }
- template <typename Compare>
- static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
- unsigned Num, unsigned Diag,
- Compare Comp) {
- if (Comp(getNumAttributeArgs(AL), Num)) {
- S.Diag(AL.getLoc(), Diag) << AL << Num;
- return false;
- }
- return true;
- }
- /// Check if the attribute has exactly as many args as Num. May
- /// output an error.
- static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) {
- return checkAttributeNumArgsImpl(S, AL, Num,
- diag::err_attribute_wrong_number_arguments,
- std::not_equal_to<unsigned>());
- }
- /// Check if the attribute has at least as many args as Num. May
- /// output an error.
- static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, AL, Num,
- diag::err_attribute_too_few_arguments,
- std::less<unsigned>());
- }
- /// Check if the attribute has at most as many args as Num. May
- /// output an error.
- static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, AL, Num,
- diag::err_attribute_too_many_arguments,
- std::greater<unsigned>());
- }
- /// A helper function to provide Attribute Location for the Attr types
- /// AND the ParsedAttr.
- template <typename AttrInfo>
- static typename std::enable_if<std::is_base_of<Attr, AttrInfo>::value,
- SourceLocation>::type
- getAttrLoc(const AttrInfo &AL) {
- return AL.getLocation();
- }
- static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
- /// If Expr is a valid integer constant, get the value of the integer
- /// expression and return success or failure. May output an error.
- ///
- /// Negative argument is implicitly converted to unsigned, unless
- /// \p StrictlyUnsigned is true.
- template <typename AttrInfo>
- static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
- uint32_t &Val, unsigned Idx = UINT_MAX,
- bool StrictlyUnsigned = false) {
- llvm::APSInt I(32);
- if (Expr->isTypeDependent() || Expr->isValueDependent() ||
- !Expr->isIntegerConstantExpr(I, S.Context)) {
- if (Idx != UINT_MAX)
- S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
- << &AI << Idx << AANT_ArgumentIntegerConstant
- << Expr->getSourceRange();
- else
- S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
- << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
- return false;
- }
- if (!I.isIntN(32)) {
- S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
- << I.toString(10, false) << 32 << /* Unsigned */ 1;
- return false;
- }
- if (StrictlyUnsigned && I.isSigned() && I.isNegative()) {
- S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
- << &AI << /*non-negative*/ 1;
- return false;
- }
- Val = (uint32_t)I.getZExtValue();
- return true;
- }
- /// Wrapper around checkUInt32Argument, with an extra check to be sure
- /// that the result will fit into a regular (signed) int. All args have the same
- /// purpose as they do in checkUInt32Argument.
- template <typename AttrInfo>
- static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr,
- int &Val, unsigned Idx = UINT_MAX) {
- uint32_t UVal;
- if (!checkUInt32Argument(S, AI, Expr, UVal, Idx))
- return false;
- if (UVal > (uint32_t)std::numeric_limits<int>::max()) {
- llvm::APSInt I(32); // for toString
- I = UVal;
- S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
- << I.toString(10, false) << 32 << /* Unsigned */ 0;
- return false;
- }
- Val = UVal;
- return true;
- }
- /// Diagnose mutually exclusive attributes when present on a given
- /// declaration. Returns true if diagnosed.
- template <typename AttrTy>
- static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (const auto *A = D->getAttr<AttrTy>()) {
- S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A;
- S.Diag(A->getLocation(), diag::note_conflicting_attribute);
- return true;
- }
- return false;
- }
- template <typename AttrTy>
- static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) {
- if (const auto *A = D->getAttr<AttrTy>()) {
- S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL
- << A;
- S.Diag(A->getLocation(), diag::note_conflicting_attribute);
- return true;
- }
- return false;
- }
- /// Check if IdxExpr is a valid parameter index for a function or
- /// instance method D. May output an error.
- ///
- /// \returns true if IdxExpr is a valid index.
- template <typename AttrInfo>
- static bool checkFunctionOrMethodParameterIndex(
- Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,
- const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) {
- assert(isFunctionOrMethodOrBlock(D));
- // In C++ the implicit 'this' function parameter also counts.
- // Parameters are counted from one.
- bool HP = hasFunctionProto(D);
- bool HasImplicitThisParam = isInstanceMethod(D);
- bool IV = HP && isFunctionOrMethodVariadic(D);
- unsigned NumParams =
- (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
- llvm::APSInt IdxInt;
- if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
- !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
- S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
- << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
- << IdxExpr->getSourceRange();
- return false;
- }
- unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX);
- if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
- S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
- << &AI << AttrArgNum << IdxExpr->getSourceRange();
- return false;
- }
- if (HasImplicitThisParam && !CanIndexImplicitThis) {
- if (IdxSource == 1) {
- S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
- << &AI << IdxExpr->getSourceRange();
- return false;
- }
- }
- Idx = ParamIdx(IdxSource, D);
- return true;
- }
- /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
- /// If not emit an error and return false. If the argument is an identifier it
- /// will emit an error with a fixit hint and treat it as if it was a string
- /// literal.
- bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
- StringRef &Str,
- SourceLocation *ArgLocation) {
- // Look for identifiers. If we have one emit a hint to fix it to a literal.
- if (AL.isArgIdent(ArgNum)) {
- IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum);
- Diag(Loc->Loc, diag::err_attribute_argument_type)
- << AL << AANT_ArgumentString
- << FixItHint::CreateInsertion(Loc->Loc, "\"")
- << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
- Str = Loc->Ident->getName();
- if (ArgLocation)
- *ArgLocation = Loc->Loc;
- return true;
- }
- // Now check for an actual string literal.
- Expr *ArgExpr = AL.getArgAsExpr(ArgNum);
- const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
- if (ArgLocation)
- *ArgLocation = ArgExpr->getBeginLoc();
- if (!Literal || !Literal->isAscii()) {
- Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentString;
- return false;
- }
- Str = Literal->getString();
- return true;
- }
- /// Applies the given attribute to the Decl without performing any
- /// additional semantic checking.
- template <typename AttrType>
- static void handleSimpleAttribute(Sema &S, Decl *D, SourceRange SR,
- unsigned SpellingIndex) {
- D->addAttr(::new (S.Context) AttrType(SR, S.Context, SpellingIndex));
- }
- template <typename AttrType>
- static void handleSimpleAttribute(Sema &S, Decl *D, const ParsedAttr &AL) {
- handleSimpleAttribute<AttrType>(S, D, AL.getRange(),
- AL.getAttributeSpellingListIndex());
- }
- template <typename... DiagnosticArgs>
- static const Sema::SemaDiagnosticBuilder&
- appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
- return Bldr;
- }
- template <typename T, typename... DiagnosticArgs>
- static const Sema::SemaDiagnosticBuilder&
- appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
- DiagnosticArgs &&... ExtraArgs) {
- return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
- std::forward<DiagnosticArgs>(ExtraArgs)...);
- }
- /// Add an attribute {@code AttrType} to declaration {@code D}, provided that
- /// {@code PassesCheck} is true.
- /// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters
- /// specified in {@code ExtraArgs}.
- template <typename AttrType, typename... DiagnosticArgs>
- static void
- handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, SourceRange SR,
- unsigned SpellingIndex,
- bool PassesCheck,
- unsigned DiagID, DiagnosticArgs&&... ExtraArgs) {
- if (!PassesCheck) {
- Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
- appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
- return;
- }
- handleSimpleAttribute<AttrType>(S, D, SR, SpellingIndex);
- }
- template <typename AttrType, typename... DiagnosticArgs>
- static void
- handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, const ParsedAttr &AL,
- bool PassesCheck,
- unsigned DiagID,
- DiagnosticArgs&&... ExtraArgs) {
- return handleSimpleAttributeOrDiagnose<AttrType>(
- S, D, AL.getRange(), AL.getAttributeSpellingListIndex(), PassesCheck,
- DiagID, std::forward<DiagnosticArgs>(ExtraArgs)...);
- }
- template <typename AttrType>
- static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- handleSimpleAttribute<AttrType>(S, D, AL);
- }
- /// Applies the given attribute to the Decl so long as the Decl doesn't
- /// already have one of the given incompatible attributes.
- template <typename AttrType, typename IncompatibleAttrType,
- typename... IncompatibleAttrTypes>
- static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL))
- return;
- handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D,
- AL);
- }
- /// Check if the passed-in expression is of type int or bool.
- static bool isIntOrBool(Expr *Exp) {
- QualType QT = Exp->getType();
- return QT->isBooleanType() || QT->isIntegerType();
- }
- // Check to see if the type is a smart pointer of some kind. We assume
- // it's a smart pointer if it defines both operator-> and operator*.
- static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
- auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record,
- OverloadedOperatorKind Op) {
- DeclContextLookupResult Result =
- Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op));
- return !Result.empty();
- };
- const RecordDecl *Record = RT->getDecl();
- bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
- bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
- if (foundStarOperator && foundArrowOperator)
- return true;
- const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record);
- if (!CXXRecord)
- return false;
- for (auto BaseSpecifier : CXXRecord->bases()) {
- if (!foundStarOperator)
- foundStarOperator = IsOverloadedOperatorPresent(
- BaseSpecifier.getType()->getAsRecordDecl(), OO_Star);
- if (!foundArrowOperator)
- foundArrowOperator = IsOverloadedOperatorPresent(
- BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow);
- }
- if (foundStarOperator && foundArrowOperator)
- return true;
- return false;
- }
- /// Check if passed in Decl is a pointer type.
- /// Note that this function may produce an error message.
- /// \return true if the Decl is a pointer type; false otherwise
- static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
- const ParsedAttr &AL) {
- const auto *VD = cast<ValueDecl>(D);
- QualType QT = VD->getType();
- if (QT->isAnyPointerType())
- return true;
- if (const auto *RT = QT->getAs<RecordType>()) {
- // If it's an incomplete type, it could be a smart pointer; skip it.
- // (We don't want to force template instantiation if we can avoid it,
- // since that would alter the order in which templates are instantiated.)
- if (RT->isIncompleteType())
- return true;
- if (threadSafetyCheckIsSmartPointer(S, RT))
- return true;
- }
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT;
- return false;
- }
- /// Checks that the passed in QualType either is of RecordType or points
- /// to RecordType. Returns the relevant RecordType, null if it does not exit.
- static const RecordType *getRecordType(QualType QT) {
- if (const auto *RT = QT->getAs<RecordType>())
- return RT;
- // Now check if we point to record type.
- if (const auto *PT = QT->getAs<PointerType>())
- return PT->getPointeeType()->getAs<RecordType>();
- return nullptr;
- }
- template <typename AttrType>
- static bool checkRecordDeclForAttr(const RecordDecl *RD) {
- // Check if the record itself has the attribute.
- if (RD->hasAttr<AttrType>())
- return true;
- // Else check if any base classes have the attribute.
- if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases(
- [](const CXXBaseSpecifier *BS, CXXBasePath &) {
- const auto &Ty = *BS->getType();
- // If it's type-dependent, we assume it could have the attribute.
- if (Ty.isDependentType())
- return true;
- return Ty.getAs<RecordType>()->getDecl()->hasAttr<AttrType>();
- },
- BPaths, true))
- return true;
- }
- return false;
- }
- static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
- const RecordType *RT = getRecordType(Ty);
- if (!RT)
- return false;
- // Don't check for the capability if the class hasn't been defined yet.
- if (RT->isIncompleteType())
- return true;
- // Allow smart pointers to be used as capability objects.
- // FIXME -- Check the type that the smart pointer points to.
- if (threadSafetyCheckIsSmartPointer(S, RT))
- return true;
- return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl());
- }
- static bool checkTypedefTypeForCapability(QualType Ty) {
- const auto *TD = Ty->getAs<TypedefType>();
- if (!TD)
- return false;
- TypedefNameDecl *TN = TD->getDecl();
- if (!TN)
- return false;
- return TN->hasAttr<CapabilityAttr>();
- }
- static bool typeHasCapability(Sema &S, QualType Ty) {
- if (checkTypedefTypeForCapability(Ty))
- return true;
- if (checkRecordTypeForCapability(S, Ty))
- return true;
- return false;
- }
- static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
- // Capability expressions are simple expressions involving the boolean logic
- // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once
- // a DeclRefExpr is found, its type should be checked to determine whether it
- // is a capability or not.
- if (const auto *E = dyn_cast<CastExpr>(Ex))
- return isCapabilityExpr(S, E->getSubExpr());
- else if (const auto *E = dyn_cast<ParenExpr>(Ex))
- return isCapabilityExpr(S, E->getSubExpr());
- else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
- if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf ||
- E->getOpcode() == UO_Deref)
- return isCapabilityExpr(S, E->getSubExpr());
- return false;
- } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
- if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr)
- return isCapabilityExpr(S, E->getLHS()) &&
- isCapabilityExpr(S, E->getRHS());
- return false;
- }
- return typeHasCapability(S, Ex->getType());
- }
- /// Checks that all attribute arguments, starting from Sidx, resolve to
- /// a capability object.
- /// \param Sidx The attribute argument index to start checking with.
- /// \param ParamIdxOk Whether an argument can be indexing into a function
- /// parameter list.
- static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
- const ParsedAttr &AL,
- SmallVectorImpl<Expr *> &Args,
- unsigned Sidx = 0,
- bool ParamIdxOk = false) {
- if (Sidx == AL.getNumArgs()) {
- // If we don't have any capability arguments, the attribute implicitly
- // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're
- // a non-static method, and that the class is a (scoped) capability.
- const auto *MD = dyn_cast<const CXXMethodDecl>(D);
- if (MD && !MD->isStatic()) {
- const CXXRecordDecl *RD = MD->getParent();
- // FIXME -- need to check this again on template instantiation
- if (!checkRecordDeclForAttr<CapabilityAttr>(RD) &&
- !checkRecordDeclForAttr<ScopedLockableAttr>(RD))
- S.Diag(AL.getLoc(),
- diag::warn_thread_attribute_not_on_capability_member)
- << AL << MD->getParent();
- } else {
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member)
- << AL;
- }
- }
- for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) {
- Expr *ArgExp = AL.getArgAsExpr(Idx);
- if (ArgExp->isTypeDependent()) {
- // FIXME -- need to check this again on template instantiation
- Args.push_back(ArgExp);
- continue;
- }
- if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
- if (StrLit->getLength() == 0 ||
- (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
- // Pass empty strings to the analyzer without warnings.
- // Treat "*" as the universal lock.
- Args.push_back(ArgExp);
- continue;
- }
- // We allow constant strings to be used as a placeholder for expressions
- // that are not valid C++ syntax, but warn that they are ignored.
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL;
- Args.push_back(ArgExp);
- continue;
- }
- QualType ArgTy = ArgExp->getType();
- // A pointer to member expression of the form &MyClass::mu is treated
- // specially -- we need to look at the type of the member.
- if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp))
- if (UOp->getOpcode() == UO_AddrOf)
- if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
- if (DRE->getDecl()->isCXXInstanceMember())
- ArgTy = DRE->getDecl()->getType();
- // First see if we can just cast to record type, or pointer to record type.
- const RecordType *RT = getRecordType(ArgTy);
- // Now check if we index into a record type function param.
- if(!RT && ParamIdxOk) {
- const auto *FD = dyn_cast<FunctionDecl>(D);
- const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
- if(FD && IL) {
- unsigned int NumParams = FD->getNumParams();
- llvm::APInt ArgValue = IL->getValue();
- uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
- uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
- if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
- S.Diag(AL.getLoc(),
- diag::err_attribute_argument_out_of_bounds_extra_info)
- << AL << Idx + 1 << NumParams;
- continue;
- }
- ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
- }
- }
- // If the type does not have a capability, see if the components of the
- // expression have capabilities. This allows for writing C code where the
- // capability may be on the type, and the expression is a capability
- // boolean logic expression. Eg) requires_capability(A || B && !C)
- if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
- << AL << ArgTy;
- Args.push_back(ArgExp);
- }
- }
- //===----------------------------------------------------------------------===//
- // Attribute Implementations
- //===----------------------------------------------------------------------===//
- static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!threadSafetyCheckIsPointer(S, D, AL))
- return;
- D->addAttr(::new (S.Context)
- PtGuardedVarAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
- Expr *&Arg) {
- SmallVector<Expr *, 1> Args;
- // check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
- unsigned Size = Args.size();
- if (Size != 1)
- return false;
- Arg = Args[0];
- return true;
- }
- static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- Expr *Arg = nullptr;
- if (!checkGuardedByAttrCommon(S, D, AL, Arg))
- return;
- D->addAttr(::new (S.Context) GuardedByAttr(
- AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex()));
- }
- static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- Expr *Arg = nullptr;
- if (!checkGuardedByAttrCommon(S, D, AL, Arg))
- return;
- if (!threadSafetyCheckIsPointer(S, D, AL))
- return;
- D->addAttr(::new (S.Context) PtGuardedByAttr(
- AL.getRange(), S.Context, Arg, AL.getAttributeSpellingListIndex()));
- }
- static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
- SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return false;
- // Check that this attribute only applies to lockable types.
- QualType QT = cast<ValueDecl>(D)->getType();
- if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
- S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL;
- return false;
- }
- // Check that all arguments are lockable objects.
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
- if (Args.empty())
- return false;
- return true;
- }
- static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<Expr *, 1> Args;
- if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
- return;
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) AcquiredAfterAttr(
- AL.getRange(), S.Context, StartArg, Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<Expr *, 1> Args;
- if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
- return;
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context) AcquiredBeforeAttr(
- AL.getRange(), S.Context, StartArg, Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
- SmallVectorImpl<Expr *> &Args) {
- // zero or more arguments ok
- // check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true);
- return true;
- }
- static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<Expr *, 1> Args;
- if (!checkLockFunAttrCommon(S, D, AL, Args))
- return;
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? nullptr : &Args[0];
- D->addAttr(::new (S.Context)
- AssertSharedLockAttr(AL.getRange(), S.Context, StartArg, Size,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr *, 1> Args;
- if (!checkLockFunAttrCommon(S, D, AL, Args))
- return;
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? nullptr : &Args[0];
- D->addAttr(::new (S.Context) AssertExclusiveLockAttr(
- AL.getRange(), S.Context, StartArg, Size,
- AL.getAttributeSpellingListIndex()));
- }
- /// Checks to be sure that the given parameter number is in bounds, and
- /// is an integral type. Will emit appropriate diagnostics if this returns
- /// false.
- ///
- /// AttrArgNo is used to actually retrieve the argument, so it's base-0.
- template <typename AttrInfo>
- static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttrInfo &AI, unsigned AttrArgNo) {
- assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");
- Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);
- ParamIdx Idx;
- if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg,
- Idx))
- return false;
- const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex());
- if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
- SourceLocation SrcLoc = AttrArg->getBeginLoc();
- S.Diag(SrcLoc, diag::err_attribute_integers_only)
- << AI << Param->getSourceRange();
- return false;
- }
- return true;
- }
- static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
- !checkAttributeAtMostNumArgs(S, AL, 2))
- return;
- const auto *FD = cast<FunctionDecl>(D);
- if (!FD->getReturnType()->isPointerType()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL;
- return;
- }
- const Expr *SizeExpr = AL.getArgAsExpr(0);
- int SizeArgNoVal;
- // Parameter indices are 1-indexed, hence Index=1
- if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Index=*/1))
- return;
- if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0))
- return;
- ParamIdx SizeArgNo(SizeArgNoVal, D);
- ParamIdx NumberArgNo;
- if (AL.getNumArgs() == 2) {
- const Expr *NumberExpr = AL.getArgAsExpr(1);
- int Val;
- // Parameter indices are 1-based, hence Index=2
- if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Index=*/2))
- return;
- if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1))
- return;
- NumberArgNo = ParamIdx(Val, D);
- }
- D->addAttr(::new (S.Context)
- AllocSizeAttr(AL.getRange(), S.Context, SizeArgNo, NumberArgNo,
- AL.getAttributeSpellingListIndex()));
- }
- static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
- SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return false;
- if (!isIntOrBool(AL.getArgAsExpr(0))) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIntOrBool;
- return false;
- }
- // check that all arguments are lockable objects
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1);
- return true;
- }
- static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, AL, Args))
- return;
- D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(
- AL.getRange(), S.Context, AL.getArgAsExpr(0), Args.data(), Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, AL, Args))
- return;
- D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
- AL.getRange(), S.Context, AL.getArgAsExpr(0), Args.data(),
- Args.size(), AL.getAttributeSpellingListIndex()));
- }
- static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // check that the argument is lockable object
- SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
- unsigned Size = Args.size();
- if (Size == 0)
- return;
- D->addAttr(::new (S.Context)
- LockReturnedAttr(AL.getRange(), S.Context, Args[0],
- AL.getAttributeSpellingListIndex()));
- }
- static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- // check that all arguments are lockable objects
- SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
- unsigned Size = Args.size();
- if (Size == 0)
- return;
- Expr **StartArg = &Args[0];
- D->addAttr(::new (S.Context)
- LocksExcludedAttr(AL.getRange(), S.Context, StartArg, Size,
- AL.getAttributeSpellingListIndex()));
- }
- static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL,
- Expr *&Cond, StringRef &Msg) {
- Cond = AL.getArgAsExpr(0);
- if (!Cond->isTypeDependent()) {
- ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
- if (Converted.isInvalid())
- return false;
- Cond = Converted.get();
- }
- if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg))
- return false;
- if (Msg.empty())
- Msg = "<no message provided>";
- SmallVector<PartialDiagnosticAt, 8> Diags;
- if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
- !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
- Diags)) {
- S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL;
- for (const PartialDiagnosticAt &PDiag : Diags)
- S.Diag(PDiag.first, PDiag.second);
- return false;
- }
- return true;
- }
- static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- S.Diag(AL.getLoc(), diag::ext_clang_enable_if);
- Expr *Cond;
- StringRef Msg;
- if (checkFunctionConditionAttr(S, D, AL, Cond, Msg))
- D->addAttr(::new (S.Context)
- EnableIfAttr(AL.getRange(), S.Context, Cond, Msg,
- AL.getAttributeSpellingListIndex()));
- }
- namespace {
- /// Determines if a given Expr references any of the given function's
- /// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
- class ArgumentDependenceChecker
- : public RecursiveASTVisitor<ArgumentDependenceChecker> {
- #ifndef NDEBUG
- const CXXRecordDecl *ClassType;
- #endif
- llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms;
- bool Result;
- public:
- ArgumentDependenceChecker(const FunctionDecl *FD) {
- #ifndef NDEBUG
- if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
- ClassType = MD->getParent();
- else
- ClassType = nullptr;
- #endif
- Parms.insert(FD->param_begin(), FD->param_end());
- }
- bool referencesArgs(Expr *E) {
- Result = false;
- TraverseStmt(E);
- return Result;
- }
- bool VisitCXXThisExpr(CXXThisExpr *E) {
- assert(E->getType()->getPointeeCXXRecordDecl() == ClassType &&
- "`this` doesn't refer to the enclosing class?");
- Result = true;
- return false;
- }
- bool VisitDeclRefExpr(DeclRefExpr *DRE) {
- if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
- if (Parms.count(PVD)) {
- Result = true;
- return false;
- }
- return true;
- }
- };
- }
- static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if);
- Expr *Cond;
- StringRef Msg;
- if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg))
- return;
- StringRef DiagTypeStr;
- if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr))
- return;
- DiagnoseIfAttr::DiagnosticType DiagType;
- if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) {
- S.Diag(AL.getArgAsExpr(2)->getBeginLoc(),
- diag::err_diagnose_if_invalid_diagnostic_type);
- return;
- }
- bool ArgDependent = false;
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
- D->addAttr(::new (S.Context) DiagnoseIfAttr(
- AL.getRange(), S.Context, Cond, Msg, DiagType, ArgDependent,
- cast<NamedDecl>(D), AL.getAttributeSpellingListIndex()));
- }
- static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (D->hasAttr<PassObjectSizeAttr>()) {
- S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL;
- return;
- }
- Expr *E = AL.getArgAsExpr(0);
- uint32_t Type;
- if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1))
- return;
- // pass_object_size's argument is passed in as the second argument of
- // __builtin_object_size. So, it has the same constraints as that second
- // argument; namely, it must be in the range [0, 3].
- if (Type > 3) {
- S.Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range)
- << AL << 0 << 3 << E->getSourceRange();
- return;
- }
- // pass_object_size is only supported on constant pointer parameters; as a
- // kindness to users, we allow the parameter to be non-const for declarations.
- // At this point, we have no clue if `D` belongs to a function declaration or
- // definition, so we defer the constness check until later.
- if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
- S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1;
- return;
- }
- D->addAttr(::new (S.Context) PassObjectSizeAttr(
- AL.getRange(), S.Context, (int)Type, AL.getAttributeSpellingListIndex()));
- }
- static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- ConsumableAttr::ConsumedState DefaultState;
- if (AL.isArgIdent(0)) {
- IdentifierLoc *IL = AL.getArgAsIdent(0);
- if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
- DefaultState)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
- << IL->Ident;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- D->addAttr(::new (S.Context)
- ConsumableAttr(AL.getRange(), S.Context, DefaultState,
- AL.getAttributeSpellingListIndex()));
- }
- static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
- const ParsedAttr &AL) {
- QualType ThisType = MD->getThisType()->getPointeeType();
- if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
- if (!RD->hasAttr<ConsumableAttr>()) {
- S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) <<
- RD->getNameAsString();
- return false;
- }
- }
- return true;
- }
- static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
- return;
- SmallVector<CallableWhenAttr::ConsumedState, 3> States;
- for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) {
- CallableWhenAttr::ConsumedState CallableState;
- StringRef StateString;
- SourceLocation Loc;
- if (AL.isArgIdent(ArgIndex)) {
- IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex);
- StateString = Ident->Ident->getName();
- Loc = Ident->Loc;
- } else {
- if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc))
- return;
- }
- if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
- CallableState)) {
- S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString;
- return;
- }
- States.push_back(CallableState);
- }
- D->addAttr(::new (S.Context)
- CallableWhenAttr(AL.getRange(), S.Context, States.data(),
- States.size(), AL.getAttributeSpellingListIndex()));
- }
- static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- ParamTypestateAttr::ConsumedState ParamState;
- if (AL.isArgIdent(0)) {
- IdentifierLoc *Ident = AL.getArgAsIdent(0);
- StringRef StateString = Ident->Ident->getName();
- if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
- ParamState)) {
- S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
- << AL << StateString;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- // FIXME: This check is currently being done in the analysis. It can be
- // enabled here only after the parser propagates attributes at
- // template specialization definition, not declaration.
- //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
- //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
- //
- //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
- // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
- // ReturnType.getAsString();
- // return;
- //}
- D->addAttr(::new (S.Context)
- ParamTypestateAttr(AL.getRange(), S.Context, ParamState,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- ReturnTypestateAttr::ConsumedState ReturnState;
- if (AL.isArgIdent(0)) {
- IdentifierLoc *IL = AL.getArgAsIdent(0);
- if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
- ReturnState)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
- << IL->Ident;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- // FIXME: This check is currently being done in the analysis. It can be
- // enabled here only after the parser propagates attributes at
- // template specialization definition, not declaration.
- //QualType ReturnType;
- //
- //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
- // ReturnType = Param->getType();
- //
- //} else if (const CXXConstructorDecl *Constructor =
- // dyn_cast<CXXConstructorDecl>(D)) {
- // ReturnType = Constructor->getThisType()->getPointeeType();
- //
- //} else {
- //
- // ReturnType = cast<FunctionDecl>(D)->getCallResultType();
- //}
- //
- //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
- //
- //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
- // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
- // ReturnType.getAsString();
- // return;
- //}
- D->addAttr(::new (S.Context)
- ReturnTypestateAttr(AL.getRange(), S.Context, ReturnState,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
- return;
- SetTypestateAttr::ConsumedState NewState;
- if (AL.isArgIdent(0)) {
- IdentifierLoc *Ident = AL.getArgAsIdent(0);
- StringRef Param = Ident->Ident->getName();
- if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
- S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
- << Param;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- D->addAttr(::new (S.Context)
- SetTypestateAttr(AL.getRange(), S.Context, NewState,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
- return;
- TestTypestateAttr::ConsumedState TestState;
- if (AL.isArgIdent(0)) {
- IdentifierLoc *Ident = AL.getArgAsIdent(0);
- StringRef Param = Ident->Ident->getName();
- if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
- S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
- << Param;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- D->addAttr(::new (S.Context)
- TestTypestateAttr(AL.getRange(), S.Context, TestState,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Remember this typedef decl, we will need it later for diagnostics.
- S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
- }
- static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (auto *TD = dyn_cast<TagDecl>(D))
- TD->addAttr(::new (S.Context) PackedAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- else if (auto *FD = dyn_cast<FieldDecl>(D)) {
- bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
- !FD->getType()->isIncompleteType() &&
- FD->isBitField() &&
- S.Context.getTypeAlign(FD->getType()) <= 8);
- if (S.getASTContext().getTargetInfo().getTriple().isPS4()) {
- if (BitfieldByteAligned)
- // The PS4 target needs to maintain ABI backwards compatibility.
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
- << AL << FD->getType();
- else
- FD->addAttr(::new (S.Context) PackedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- } else {
- // Report warning about changed offset in the newer compiler versions.
- if (BitfieldByteAligned)
- S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield);
- FD->addAttr(::new (S.Context) PackedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- } else
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
- }
- static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
- // The IBOutlet/IBOutletCollection attributes only apply to instance
- // variables or properties of Objective-C classes. The outlet must also
- // have an object reference type.
- if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
- if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
- S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
- << AL << VD->getType() << 0;
- return false;
- }
- }
- else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
- if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
- S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
- << AL << PD->getType() << 1;
- return false;
- }
- }
- else {
- S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
- return false;
- }
- return true;
- }
- static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkIBOutletCommon(S, D, AL))
- return;
- D->addAttr(::new (S.Context)
- IBOutletAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) {
- // The iboutletcollection attribute can have zero or one arguments.
- if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
- return;
- }
- if (!checkIBOutletCommon(S, D, AL))
- return;
- ParsedType PT;
- if (AL.hasParsedType())
- PT = AL.getTypeArg();
- else {
- PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(),
- S.getScopeForContext(D->getDeclContext()->getParent()));
- if (!PT) {
- S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
- return;
- }
- }
- TypeSourceInfo *QTLoc = nullptr;
- QualType QT = S.GetTypeFromParser(PT, &QTLoc);
- if (!QTLoc)
- QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc());
- // Diagnose use of non-object type in iboutletcollection attribute.
- // FIXME. Gnu attribute extension ignores use of builtin types in
- // attributes. So, __attribute__((iboutletcollection(char))) will be
- // treated as __attribute__((iboutletcollection())).
- if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
- S.Diag(AL.getLoc(),
- QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
- : diag::err_iboutletcollection_type) << QT;
- return;
- }
- D->addAttr(::new (S.Context)
- IBOutletCollectionAttr(AL.getRange(), S.Context, QTLoc,
- AL.getAttributeSpellingListIndex()));
- }
- bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
- if (RefOkay) {
- if (T->isReferenceType())
- return true;
- } else {
- T = T.getNonReferenceType();
- }
- // The nonnull attribute, and other similar attributes, can be applied to a
- // transparent union that contains a pointer type.
- if (const RecordType *UT = T->getAsUnionType()) {
- if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
- RecordDecl *UD = UT->getDecl();
- for (const auto *I : UD->fields()) {
- QualType QT = I->getType();
- if (QT->isAnyPointerType() || QT->isBlockPointerType())
- return true;
- }
- }
- }
- return T->isAnyPointerType() || T->isBlockPointerType();
- }
- static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL,
- SourceRange AttrParmRange,
- SourceRange TypeRange,
- bool isReturnValue = false) {
- if (!S.isValidPointerAttrType(T)) {
- if (isReturnValue)
- S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
- << AL << AttrParmRange << TypeRange;
- else
- S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
- << AL << AttrParmRange << TypeRange << 0;
- return false;
- }
- return true;
- }
- static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<ParamIdx, 8> NonNullArgs;
- for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
- Expr *Ex = AL.getArgAsExpr(I);
- ParamIdx Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx))
- return;
- // Is the function argument a pointer type?
- if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) &&
- !attrNonNullArgCheck(
- S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL,
- Ex->getSourceRange(),
- getFunctionOrMethodParamRange(D, Idx.getASTIndex())))
- continue;
- NonNullArgs.push_back(Idx);
- }
- // If no arguments were specified to __attribute__((nonnull)) then all pointer
- // arguments have a nonnull attribute; warn if there aren't any. Skip this
- // check if the attribute came from a macro expansion or a template
- // instantiation.
- if (NonNullArgs.empty() && AL.getLoc().isFileID() &&
- !S.inTemplateInstantiation()) {
- bool AnyPointers = isFunctionOrMethodVariadic(D);
- for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
- I != E && !AnyPointers; ++I) {
- QualType T = getFunctionOrMethodParamType(D, I);
- if (T->isDependentType() || S.isValidPointerAttrType(T))
- AnyPointers = true;
- }
- if (!AnyPointers)
- S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers);
- }
- ParamIdx *Start = NonNullArgs.data();
- unsigned Size = NonNullArgs.size();
- llvm::array_pod_sort(Start, Start + Size);
- D->addAttr(::new (S.Context)
- NonNullAttr(AL.getRange(), S.Context, Start, Size,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
- const ParsedAttr &AL) {
- if (AL.getNumArgs() > 0) {
- if (D->getFunctionType()) {
- handleNonNullAttr(S, D, AL);
- } else {
- S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
- << D->getSourceRange();
- }
- return;
- }
- // Is the argument a pointer type?
- if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(),
- D->getSourceRange()))
- return;
- D->addAttr(::new (S.Context)
- NonNullAttr(AL.getRange(), S.Context, nullptr, 0,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- QualType ResultType = getFunctionOrMethodResultType(D);
- SourceRange SR = getFunctionOrMethodResultSourceRange(D);
- if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR,
- /* isReturnValue */ true))
- return;
- D->addAttr(::new (S.Context)
- ReturnsNonNullAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (D->isInvalidDecl())
- return;
- // noescape only applies to pointer types.
- QualType T = cast<ParmVarDecl>(D)->getType();
- if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
- << AL << AL.getRange() << 0;
- return;
- }
- D->addAttr(::new (S.Context) NoEscapeAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- Expr *E = AL.getArgAsExpr(0),
- *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr;
- S.AddAssumeAlignedAttr(AL.getRange(), D, E, OE,
- AL.getAttributeSpellingListIndex());
- }
- static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- S.AddAllocAlignAttr(AL.getRange(), D, AL.getArgAsExpr(0),
- AL.getAttributeSpellingListIndex());
- }
- void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
- Expr *OE, unsigned SpellingListIndex) {
- QualType ResultType = getFunctionOrMethodResultType(D);
- SourceRange SR = getFunctionOrMethodResultSourceRange(D);
- AssumeAlignedAttr TmpAttr(AttrRange, Context, E, OE, SpellingListIndex);
- SourceLocation AttrLoc = AttrRange.getBegin();
- if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
- Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
- << &TmpAttr << AttrRange << SR;
- return;
- }
- if (!E->isValueDependent()) {
- llvm::APSInt I(64);
- if (!E->isIntegerConstantExpr(I, Context)) {
- if (OE)
- Diag(AttrLoc, diag::err_attribute_argument_n_type)
- << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
- else
- Diag(AttrLoc, diag::err_attribute_argument_type)
- << &TmpAttr << AANT_ArgumentIntegerConstant
- << E->getSourceRange();
- return;
- }
- if (!I.isPowerOf2()) {
- Diag(AttrLoc, diag::err_alignment_not_power_of_two)
- << E->getSourceRange();
- return;
- }
- }
- if (OE) {
- if (!OE->isValueDependent()) {
- llvm::APSInt I(64);
- if (!OE->isIntegerConstantExpr(I, Context)) {
- Diag(AttrLoc, diag::err_attribute_argument_n_type)
- << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
- << OE->getSourceRange();
- return;
- }
- }
- }
- D->addAttr(::new (Context)
- AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex));
- }
- void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
- unsigned SpellingListIndex) {
- QualType ResultType = getFunctionOrMethodResultType(D);
- AllocAlignAttr TmpAttr(AttrRange, Context, ParamIdx(), SpellingListIndex);
- SourceLocation AttrLoc = AttrRange.getBegin();
- if (!ResultType->isDependentType() &&
- !isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
- Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
- << &TmpAttr << AttrRange << getFunctionOrMethodResultSourceRange(D);
- return;
- }
- ParamIdx Idx;
- const auto *FuncDecl = cast<FunctionDecl>(D);
- if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr,
- /*AttrArgNo=*/1, ParamExpr, Idx))
- return;
- QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
- if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) {
- Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only)
- << &TmpAttr
- << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
- return;
- }
- D->addAttr(::new (Context)
- AllocAlignAttr(AttrRange, Context, Idx, SpellingListIndex));
- }
- /// Normalize the attribute, __foo__ becomes foo.
- /// Returns true if normalization was applied.
- static bool normalizeName(StringRef &AttrName) {
- if (AttrName.size() > 4 && AttrName.startswith("__") &&
- AttrName.endswith("__")) {
- AttrName = AttrName.drop_front(2).drop_back(2);
- return true;
- }
- return false;
- }
- static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // This attribute must be applied to a function declaration. The first
- // argument to the attribute must be an identifier, the name of the resource,
- // for example: malloc. The following arguments must be argument indexes, the
- // arguments must be of integer type for Returns, otherwise of pointer type.
- // The difference between Holds and Takes is that a pointer may still be used
- // after being held. free() should be __attribute((ownership_takes)), whereas
- // a list append function may well be __attribute((ownership_holds)).
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIdentifier;
- return;
- }
- // Figure out our Kind.
- OwnershipAttr::OwnershipKind K =
- OwnershipAttr(AL.getLoc(), S.Context, nullptr, nullptr, 0,
- AL.getAttributeSpellingListIndex()).getOwnKind();
- // Check arguments.
- switch (K) {
- case OwnershipAttr::Takes:
- case OwnershipAttr::Holds:
- if (AL.getNumArgs() < 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2;
- return;
- }
- break;
- case OwnershipAttr::Returns:
- if (AL.getNumArgs() > 2) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
- return;
- }
- break;
- }
- IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
- StringRef ModuleName = Module->getName();
- if (normalizeName(ModuleName)) {
- Module = &S.PP.getIdentifierTable().get(ModuleName);
- }
- SmallVector<ParamIdx, 8> OwnershipArgs;
- for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
- Expr *Ex = AL.getArgAsExpr(i);
- ParamIdx Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
- return;
- // Is the function argument a pointer type?
- QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex());
- int Err = -1; // No error
- switch (K) {
- case OwnershipAttr::Takes:
- case OwnershipAttr::Holds:
- if (!T->isAnyPointerType() && !T->isBlockPointerType())
- Err = 0;
- break;
- case OwnershipAttr::Returns:
- if (!T->isIntegerType())
- Err = 1;
- break;
- }
- if (-1 != Err) {
- S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err
- << Ex->getSourceRange();
- return;
- }
- // Check we don't have a conflict with another ownership attribute.
- for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
- // Cannot have two ownership attributes of different kinds for the same
- // index.
- if (I->getOwnKind() != K && I->args_end() !=
- std::find(I->args_begin(), I->args_end(), Idx)) {
- S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I;
- return;
- } else if (K == OwnershipAttr::Returns &&
- I->getOwnKind() == OwnershipAttr::Returns) {
- // A returns attribute conflicts with any other returns attribute using
- // a different index.
- if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
- S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
- << I->args_begin()->getSourceIndex();
- if (I->args_size())
- S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
- << Idx.getSourceIndex() << Ex->getSourceRange();
- return;
- }
- }
- }
- OwnershipArgs.push_back(Idx);
- }
- ParamIdx *Start = OwnershipArgs.data();
- unsigned Size = OwnershipArgs.size();
- llvm::array_pod_sort(Start, Start + Size);
- D->addAttr(::new (S.Context)
- OwnershipAttr(AL.getLoc(), S.Context, Module, Start, Size,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Check the attribute arguments.
- if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
- return;
- }
- // gcc rejects
- // class c {
- // static int a __attribute__((weakref ("v2")));
- // static int b() __attribute__((weakref ("f3")));
- // };
- // and ignores the attributes of
- // void f(void) {
- // static int a __attribute__((weakref ("v2")));
- // }
- // we reject them
- const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
- if (!Ctx->isFileContext()) {
- S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context)
- << cast<NamedDecl>(D);
- return;
- }
- // The GCC manual says
- //
- // At present, a declaration to which `weakref' is attached can only
- // be `static'.
- //
- // It also says
- //
- // Without a TARGET,
- // given as an argument to `weakref' or to `alias', `weakref' is
- // equivalent to `weak'.
- //
- // gcc 4.4.1 will accept
- // int a7 __attribute__((weakref));
- // as
- // int a7 __attribute__((weak));
- // This looks like a bug in gcc. We reject that for now. We should revisit
- // it if this behaviour is actually used.
- // GCC rejects
- // static ((alias ("y"), weakref)).
- // Should we? How to check that weakref is before or after alias?
- // FIXME: it would be good for us to keep the WeakRefAttr as-written instead
- // of transforming it into an AliasAttr. The WeakRefAttr never uses the
- // StringRef parameter it was given anyway.
- StringRef Str;
- if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str))
- // GCC will accept anything as the argument of weakref. Should we
- // check for an existing decl?
- D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- D->addAttr(::new (S.Context)
- WeakRefAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
- return;
- // Aliases should be on declarations, not definitions.
- const auto *FD = cast<FunctionDecl>(D);
- if (FD->isThisDeclarationADefinition()) {
- S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1;
- return;
- }
- D->addAttr(::new (S.Context) IFuncAttr(AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
- return;
- if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
- S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin);
- return;
- }
- if (S.Context.getTargetInfo().getTriple().isNVPTX()) {
- S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx);
- }
- // Aliases should be on declarations, not definitions.
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isThisDeclarationADefinition()) {
- S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0;
- return;
- }
- } else {
- const auto *VD = cast<VarDecl>(D);
- if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) {
- S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0;
- return;
- }
- }
- // Mark target used to prevent unneeded-internal-declaration warnings.
- if (!S.LangOpts.CPlusPlus) {
- // FIXME: demangle Str for C++, as the attribute refers to the mangled
- // linkage name, not the pre-mangled identifier.
- const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc());
- LookupResult LR(S, target, Sema::LookupOrdinaryName);
- if (S.LookupQualifiedName(LR, S.getCurLexicalContext()))
- for (NamedDecl *ND : LR)
- ND->markUsed(S.Context);
- }
- D->addAttr(::new (S.Context) AliasAttr(AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef Model;
- SourceLocation LiteralLoc;
- // Check that it is a string.
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc))
- return;
- // Check that the value.
- if (Model != "global-dynamic" && Model != "local-dynamic"
- && Model != "initial-exec" && Model != "local-exec") {
- S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);
- return;
- }
- D->addAttr(::new (S.Context)
- TLSModelAttr(AL.getRange(), S.Context, Model,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- QualType ResultType = getFunctionOrMethodResultType(D);
- if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
- D->addAttr(::new (S.Context) RestrictAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- return;
- }
- S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
- << AL << getFunctionOrMethodResultSourceRange(D);
- }
- static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- FunctionDecl *FD = cast<FunctionDecl>(D);
- if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (MD->getParent()->isLambda()) {
- S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL;
- return;
- }
- }
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- SmallVector<IdentifierInfo *, 8> CPUs;
- for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) {
- if (!AL.isArgIdent(ArgNo)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo);
- StringRef CPUName = CPUArg->Ident->getName().trim();
- if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) {
- S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value)
- << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch);
- return;
- }
- const TargetInfo &Target = S.Context.getTargetInfo();
- if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) {
- return Target.CPUSpecificManglingCharacter(CPUName) ==
- Target.CPUSpecificManglingCharacter(Cur->getName());
- })) {
- S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries);
- return;
- }
- CPUs.push_back(CPUArg->Ident);
- }
- FD->setIsMultiVersion(true);
- if (AL.getKind() == ParsedAttr::AT_CPUSpecific)
- D->addAttr(::new (S.Context) CPUSpecificAttr(
- AL.getRange(), S.Context, CPUs.data(), CPUs.size(),
- AL.getAttributeSpellingListIndex()));
- else
- D->addAttr(::new (S.Context) CPUDispatchAttr(
- AL.getRange(), S.Context, CPUs.data(), CPUs.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (S.LangOpts.CPlusPlus) {
- S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
- << AL << AttributeLangSupport::Cpp;
- return;
- }
- if (CommonAttr *CA = S.mergeCommonAttr(D, AL))
- D->addAttr(CA);
- }
- static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL))
- return;
- if (AL.isDeclspecAttribute()) {
- const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
- const auto &Arch = Triple.getArch();
- if (Arch != llvm::Triple::x86 &&
- (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) {
- S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch)
- << AL << Triple.getArchName();
- return;
- }
- }
- D->addAttr(::new (S.Context) NakedAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
- if (hasDeclarator(D)) return;
- if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attrs << ExpectedFunctionOrMethod;
- return;
- }
- D->addAttr(::new (S.Context) NoReturnAttr(
- Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
- }
- static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
- if (!S.getLangOpts().CFProtectionBranch)
- S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
- else
- handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs);
- }
- bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
- if (!checkAttributeNumArgs(*this, Attrs, 0)) {
- Attrs.setInvalid();
- return true;
- }
- return false;
- }
- bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
- // Check whether the attribute is valid on the current target.
- if (!AL.existsInTarget(Context.getTargetInfo())) {
- Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL;
- AL.setInvalid();
- return true;
- }
- return false;
- }
- static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // The checking path for 'noreturn' and 'analyzer_noreturn' are different
- // because 'analyzer_noreturn' does not impact the type.
- if (!isFunctionOrMethodOrBlock(D)) {
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (!VD || (!VD->getType()->isBlockPointerType() &&
- !VD->getType()->isFunctionPointerType())) {
- S.Diag(AL.getLoc(), AL.isCXX11Attribute()
- ? diag::err_attribute_wrong_decl_type
- : diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionMethodOrBlock;
- return;
- }
- }
- D->addAttr(::new (S.Context)
- AnalyzerNoReturnAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- // PS3 PPU-specific.
- static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- /*
- Returning a Vector Class in Registers
- According to the PPU ABI specifications, a class with a single member of
- vector type is returned in memory when used as the return value of a
- function.
- This results in inefficient code when implementing vector classes. To return
- the value in a single vector register, add the vecreturn attribute to the
- class definition. This attribute is also applicable to struct types.
- Example:
- struct Vector
- {
- __vector float xyzw;
- } __attribute__((vecreturn));
- Vector Add(Vector lhs, Vector rhs)
- {
- Vector result;
- result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
- return result; // This will be returned in a register
- }
- */
- if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
- S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A;
- return;
- }
- const auto *R = cast<RecordDecl>(D);
- int count = 0;
- if (!isa<CXXRecordDecl>(R)) {
- S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
- return;
- }
- if (!cast<CXXRecordDecl>(R)->isPOD()) {
- S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
- return;
- }
- for (const auto *I : R->fields()) {
- if ((count == 1) || !I->getType()->isVectorType()) {
- S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
- return;
- }
- count++;
- }
- D->addAttr(::new (S.Context) VecReturnAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
- const ParsedAttr &AL) {
- if (isa<ParmVarDecl>(D)) {
- // [[carries_dependency]] can only be applied to a parameter if it is a
- // parameter of a function declaration or lambda.
- if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
- S.Diag(AL.getLoc(),
- diag::err_carries_dependency_param_not_function_decl);
- return;
- }
- }
- D->addAttr(::new (S.Context) CarriesDependencyAttr(
- AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName();
- // If this is spelled as the standard C++17 attribute, but not in C++17, warn
- // about using it as an extension.
- if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr)
- S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
- D->addAttr(::new (S.Context) UnusedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t priority = ConstructorAttr::DefaultPriority;
- if (AL.getNumArgs() &&
- !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
- return;
- D->addAttr(::new (S.Context)
- ConstructorAttr(AL.getRange(), S.Context, priority,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t priority = DestructorAttr::DefaultPriority;
- if (AL.getNumArgs() &&
- !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
- return;
- D->addAttr(::new (S.Context)
- DestructorAttr(AL.getRange(), S.Context, priority,
- AL.getAttributeSpellingListIndex()));
- }
- template <typename AttrTy>
- static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Handle the case where the attribute has a text message.
- StringRef Str;
- if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str))
- return;
- D->addAttr(::new (S.Context) AttrTy(AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
- S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
- << AL << AL.getRange();
- return;
- }
- D->addAttr(::new (S.Context)
- ObjCExplicitProtocolImplAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
- IdentifierInfo *Platform,
- VersionTuple Introduced,
- VersionTuple Deprecated,
- VersionTuple Obsoleted) {
- StringRef PlatformName
- = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
- if (PlatformName.empty())
- PlatformName = Platform->getName();
- // Ensure that Introduced <= Deprecated <= Obsoleted (although not all
- // of these steps are needed).
- if (!Introduced.empty() && !Deprecated.empty() &&
- !(Introduced <= Deprecated)) {
- S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
- << 1 << PlatformName << Deprecated.getAsString()
- << 0 << Introduced.getAsString();
- return true;
- }
- if (!Introduced.empty() && !Obsoleted.empty() &&
- !(Introduced <= Obsoleted)) {
- S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
- << 2 << PlatformName << Obsoleted.getAsString()
- << 0 << Introduced.getAsString();
- return true;
- }
- if (!Deprecated.empty() && !Obsoleted.empty() &&
- !(Deprecated <= Obsoleted)) {
- S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
- << 2 << PlatformName << Obsoleted.getAsString()
- << 1 << Deprecated.getAsString();
- return true;
- }
- return false;
- }
- /// Check whether the two versions match.
- ///
- /// If either version tuple is empty, then they are assumed to match. If
- /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
- static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y,
- bool BeforeIsOkay) {
- if (X.empty() || Y.empty())
- return true;
- if (X == Y)
- return true;
- if (BeforeIsOkay && X < Y)
- return true;
- return false;
- }
- AvailabilityAttr *Sema::mergeAvailabilityAttr(
- NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
- VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted,
- bool IsUnavailable, StringRef Message, bool IsStrict, StringRef Replacement,
- AvailabilityMergeKind AMK, int Priority, unsigned AttrSpellingListIndex) {
- VersionTuple MergedIntroduced = Introduced;
- VersionTuple MergedDeprecated = Deprecated;
- VersionTuple MergedObsoleted = Obsoleted;
- bool FoundAny = false;
- bool OverrideOrImpl = false;
- switch (AMK) {
- case AMK_None:
- case AMK_Redeclaration:
- OverrideOrImpl = false;
- break;
- case AMK_Override:
- case AMK_ProtocolImplementation:
- OverrideOrImpl = true;
- break;
- }
- if (D->hasAttrs()) {
- AttrVec &Attrs = D->getAttrs();
- for (unsigned i = 0, e = Attrs.size(); i != e;) {
- const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
- if (!OldAA) {
- ++i;
- continue;
- }
- IdentifierInfo *OldPlatform = OldAA->getPlatform();
- if (OldPlatform != Platform) {
- ++i;
- continue;
- }
- // If there is an existing availability attribute for this platform that
- // has a lower priority use the existing one and discard the new
- // attribute.
- if (OldAA->getPriority() < Priority)
- return nullptr;
- // If there is an existing attribute for this platform that has a higher
- // priority than the new attribute then erase the old one and continue
- // processing the attributes.
- if (OldAA->getPriority() > Priority) {
- Attrs.erase(Attrs.begin() + i);
- --e;
- continue;
- }
- FoundAny = true;
- VersionTuple OldIntroduced = OldAA->getIntroduced();
- VersionTuple OldDeprecated = OldAA->getDeprecated();
- VersionTuple OldObsoleted = OldAA->getObsoleted();
- bool OldIsUnavailable = OldAA->getUnavailable();
- if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) ||
- !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) ||
- !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) ||
- !(OldIsUnavailable == IsUnavailable ||
- (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) {
- if (OverrideOrImpl) {
- int Which = -1;
- VersionTuple FirstVersion;
- VersionTuple SecondVersion;
- if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) {
- Which = 0;
- FirstVersion = OldIntroduced;
- SecondVersion = Introduced;
- } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) {
- Which = 1;
- FirstVersion = Deprecated;
- SecondVersion = OldDeprecated;
- } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) {
- Which = 2;
- FirstVersion = Obsoleted;
- SecondVersion = OldObsoleted;
- }
- if (Which == -1) {
- Diag(OldAA->getLocation(),
- diag::warn_mismatched_availability_override_unavail)
- << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
- << (AMK == AMK_Override);
- } else {
- Diag(OldAA->getLocation(),
- diag::warn_mismatched_availability_override)
- << Which
- << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
- << FirstVersion.getAsString() << SecondVersion.getAsString()
- << (AMK == AMK_Override);
- }
- if (AMK == AMK_Override)
- Diag(Range.getBegin(), diag::note_overridden_method);
- else
- Diag(Range.getBegin(), diag::note_protocol_method);
- } else {
- Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
- Diag(Range.getBegin(), diag::note_previous_attribute);
- }
- Attrs.erase(Attrs.begin() + i);
- --e;
- continue;
- }
- VersionTuple MergedIntroduced2 = MergedIntroduced;
- VersionTuple MergedDeprecated2 = MergedDeprecated;
- VersionTuple MergedObsoleted2 = MergedObsoleted;
- if (MergedIntroduced2.empty())
- MergedIntroduced2 = OldIntroduced;
- if (MergedDeprecated2.empty())
- MergedDeprecated2 = OldDeprecated;
- if (MergedObsoleted2.empty())
- MergedObsoleted2 = OldObsoleted;
- if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform,
- MergedIntroduced2, MergedDeprecated2,
- MergedObsoleted2)) {
- Attrs.erase(Attrs.begin() + i);
- --e;
- continue;
- }
- MergedIntroduced = MergedIntroduced2;
- MergedDeprecated = MergedDeprecated2;
- MergedObsoleted = MergedObsoleted2;
- ++i;
- }
- }
- if (FoundAny &&
- MergedIntroduced == Introduced &&
- MergedDeprecated == Deprecated &&
- MergedObsoleted == Obsoleted)
- return nullptr;
- // Only create a new attribute if !OverrideOrImpl, but we want to do
- // the checking.
- if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced,
- MergedDeprecated, MergedObsoleted) &&
- !OverrideOrImpl) {
- auto *Avail = ::new (Context)
- AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated,
- Obsoleted, IsUnavailable, Message, IsStrict,
- Replacement, Priority, AttrSpellingListIndex);
- Avail->setImplicit(Implicit);
- return Avail;
- }
- return nullptr;
- }
- static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeNumArgs(S, AL, 1))
- return;
- IdentifierLoc *Platform = AL.getArgAsIdent(0);
- unsigned Index = AL.getAttributeSpellingListIndex();
- IdentifierInfo *II = Platform->Ident;
- if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
- S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
- << Platform->Ident;
- auto *ND = dyn_cast<NamedDecl>(D);
- if (!ND) // We warned about this already, so just return.
- return;
- AvailabilityChange Introduced = AL.getAvailabilityIntroduced();
- AvailabilityChange Deprecated = AL.getAvailabilityDeprecated();
- AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted();
- bool IsUnavailable = AL.getUnavailableLoc().isValid();
- bool IsStrict = AL.getStrictLoc().isValid();
- StringRef Str;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr()))
- Str = SE->getString();
- StringRef Replacement;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr()))
- Replacement = SE->getString();
- if (II->isStr("swift")) {
- if (Introduced.isValid() || Obsoleted.isValid() ||
- (!IsUnavailable && !Deprecated.isValid())) {
- S.Diag(AL.getLoc(),
- diag::warn_availability_swift_unavailable_deprecated_only);
- return;
- }
- }
- int PriorityModifier = AL.isPragmaClangAttribute()
- ? Sema::AP_PragmaClangAttribute
- : Sema::AP_Explicit;
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
- ND, AL.getRange(), II, false /*Implicit*/, Introduced.Version,
- Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict,
- Replacement, Sema::AMK_None, PriorityModifier, Index);
- if (NewAttr)
- D->addAttr(NewAttr);
- // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
- // matches before the start of the watchOS platform.
- if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
- IdentifierInfo *NewII = nullptr;
- if (II->getName() == "ios")
- NewII = &S.Context.Idents.get("watchos");
- else if (II->getName() == "ios_app_extension")
- NewII = &S.Context.Idents.get("watchos_app_extension");
- if (NewII) {
- auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
- if (Version.empty())
- return Version;
- auto Major = Version.getMajor();
- auto NewMajor = Major >= 9 ? Major - 7 : 0;
- if (NewMajor >= 2) {
- if (Version.getMinor().hasValue()) {
- if (Version.getSubminor().hasValue())
- return VersionTuple(NewMajor, Version.getMinor().getValue(),
- Version.getSubminor().getValue());
- else
- return VersionTuple(NewMajor, Version.getMinor().getValue());
- }
- }
- return VersionTuple(2, 0);
- };
- auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
- auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
- auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
- ND, AL.getRange(), NewII, true /*Implicit*/, NewIntroduced,
- NewDeprecated, NewObsoleted, IsUnavailable, Str, IsStrict,
- Replacement, Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform, Index);
- if (NewAttr)
- D->addAttr(NewAttr);
- }
- } else if (S.Context.getTargetInfo().getTriple().isTvOS()) {
- // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning
- // matches before the start of the tvOS platform.
- IdentifierInfo *NewII = nullptr;
- if (II->getName() == "ios")
- NewII = &S.Context.Idents.get("tvos");
- else if (II->getName() == "ios_app_extension")
- NewII = &S.Context.Idents.get("tvos_app_extension");
- if (NewII) {
- AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
- ND, AL.getRange(), NewII, true /*Implicit*/, Introduced.Version,
- Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict,
- Replacement, Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform, Index);
- if (NewAttr)
- D->addAttr(NewAttr);
- }
- }
- }
- static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- assert(checkAttributeAtMostNumArgs(S, AL, 3) &&
- "Invalid number of arguments in an external_source_symbol attribute");
- StringRef Language;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0)))
- Language = SE->getString();
- StringRef DefinedIn;
- if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1)))
- DefinedIn = SE->getString();
- bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr;
- D->addAttr(::new (S.Context) ExternalSourceSymbolAttr(
- AL.getRange(), S.Context, Language, DefinedIn, IsGeneratedDeclaration,
- AL.getAttributeSpellingListIndex()));
- }
- template <class T>
- static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range,
- typename T::VisibilityType value,
- unsigned attrSpellingListIndex) {
- T *existingAttr = D->getAttr<T>();
- if (existingAttr) {
- typename T::VisibilityType existingValue = existingAttr->getVisibility();
- if (existingValue == value)
- return nullptr;
- S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
- S.Diag(range.getBegin(), diag::note_previous_attribute);
- D->dropAttr<T>();
- }
- return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex);
- }
- VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range,
- VisibilityAttr::VisibilityType Vis,
- unsigned AttrSpellingListIndex) {
- return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis,
- AttrSpellingListIndex);
- }
- TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
- TypeVisibilityAttr::VisibilityType Vis,
- unsigned AttrSpellingListIndex) {
- return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis,
- AttrSpellingListIndex);
- }
- static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
- bool isTypeVisibility) {
- // Visibility attributes don't mean anything on a typedef.
- if (isa<TypedefNameDecl>(D)) {
- S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
- return;
- }
- // 'type_visibility' can only go on a type or namespace.
- if (isTypeVisibility &&
- !(isa<TagDecl>(D) ||
- isa<ObjCInterfaceDecl>(D) ||
- isa<NamespaceDecl>(D))) {
- S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedTypeOrNamespace;
- return;
- }
- // Check that the argument is a string literal.
- StringRef TypeStr;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc))
- return;
- VisibilityAttr::VisibilityType type;
- if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
- S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL
- << TypeStr;
- return;
- }
- // Complain about attempts to use protected visibility on targets
- // (like Darwin) that don't support it.
- if (type == VisibilityAttr::Protected &&
- !S.Context.getTargetInfo().hasProtectedVisibility()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility);
- type = VisibilityAttr::Default;
- }
- unsigned Index = AL.getAttributeSpellingListIndex();
- Attr *newAttr;
- if (isTypeVisibility) {
- newAttr = S.mergeTypeVisibilityAttr(D, AL.getRange(),
- (TypeVisibilityAttr::VisibilityType) type,
- Index);
- } else {
- newAttr = S.mergeVisibilityAttr(D, AL.getRange(), type, Index);
- }
- if (newAttr)
- D->addAttr(newAttr);
- }
- static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- const auto *M = cast<ObjCMethodDecl>(D);
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIdentifier;
- return;
- }
- IdentifierLoc *IL = AL.getArgAsIdent(0);
- ObjCMethodFamilyAttr::FamilyKind F;
- if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
- S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident;
- return;
- }
- if (F == ObjCMethodFamilyAttr::OMF_init &&
- !M->getReturnType()->isObjCObjectPointerType()) {
- S.Diag(M->getLocation(), diag::err_init_method_bad_return_type)
- << M->getReturnType();
- // Ignore the attribute.
- return;
- }
- D->addAttr(new (S.Context) ObjCMethodFamilyAttr(
- AL.getRange(), S.Context, F, AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
- QualType T = TD->getUnderlyingType();
- if (!T->isCARCBridgableType()) {
- S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
- return;
- }
- }
- else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
- QualType T = PD->getType();
- if (!T->isCARCBridgableType()) {
- S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
- return;
- }
- }
- else {
- // It is okay to include this attribute on properties, e.g.:
- //
- // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
- //
- // In this case it follows tradition and suppresses an error in the above
- // case.
- S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
- }
- D->addAttr(::new (S.Context)
- ObjCNSObjectAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
- QualType T = TD->getUnderlyingType();
- if (!T->isObjCObjectPointerType()) {
- S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
- return;
- }
- } else {
- S.Diag(D->getLocation(), diag::warn_independentclass_attribute);
- return;
- }
- D->addAttr(::new (S.Context)
- ObjCIndependentClassAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIdentifier;
- return;
- }
- IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
- BlocksAttr::BlockType type;
- if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
- return;
- }
- D->addAttr(::new (S.Context)
- BlocksAttr(AL.getRange(), S.Context, type,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
- if (AL.getNumArgs() > 0) {
- Expr *E = AL.getArgAsExpr(0);
- llvm::APSInt Idx(32);
- if (E->isTypeDependent() || E->isValueDependent() ||
- !E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange();
- return;
- }
- if (Idx.isSigned() && Idx.isNegative()) {
- S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
- << E->getSourceRange();
- return;
- }
- sentinel = Idx.getZExtValue();
- }
- unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
- if (AL.getNumArgs() > 1) {
- Expr *E = AL.getArgAsExpr(1);
- llvm::APSInt Idx(32);
- if (E->isTypeDependent() || E->isValueDependent() ||
- !E->isIntegerConstantExpr(Idx, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange();
- return;
- }
- nullPos = Idx.getZExtValue();
- if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) {
- // FIXME: This error message could be improved, it would be nice
- // to say what the bounds actually are.
- S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
- << E->getSourceRange();
- return;
- }
- }
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- const FunctionType *FT = FD->getType()->castAs<FunctionType>();
- if (isa<FunctionNoProtoType>(FT)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments);
- return;
- }
- if (!cast<FunctionProtoType>(FT)->isVariadic()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
- return;
- }
- } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (!MD->isVariadic()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
- return;
- }
- } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
- if (!BD->isVariadic()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
- return;
- }
- } else if (const auto *V = dyn_cast<VarDecl>(D)) {
- QualType Ty = V->getType();
- if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
- const FunctionType *FT = Ty->isFunctionPointerType()
- ? D->getFunctionType()
- : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
- if (!cast<FunctionProtoType>(FT)->isVariadic()) {
- int m = Ty->isFunctionPointerType() ? 0 : 1;
- S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionMethodOrBlock;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionMethodOrBlock;
- return;
- }
- D->addAttr(::new (S.Context)
- SentinelAttr(AL.getRange(), S.Context, sentinel, nullPos,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (D->getFunctionType() &&
- D->getFunctionType()->getReturnType()->isVoidType()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0;
- return;
- }
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
- if (MD->getReturnType()->isVoidType()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1;
- return;
- }
- // If this is spelled as the standard C++17 attribute, but not in C++17, warn
- // about using it as an extension.
- if (!S.getLangOpts().CPlusPlus17 && AL.isCXX11Attribute() &&
- !AL.getScopeName())
- S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
- D->addAttr(::new (S.Context)
- WarnUnusedResultAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // weak_import only applies to variable & function declarations.
- bool isDef = false;
- if (!D->canBeWeakImported(isDef)) {
- if (isDef)
- S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition)
- << "weak_import";
- else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
- (S.Context.getTargetInfo().getTriple().isOSDarwin() &&
- (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
- // Nothing to warn about here.
- } else
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedVariableOrFunction;
- return;
- }
- D->addAttr(::new (S.Context)
- WeakImportAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- // Handles reqd_work_group_size and work_group_size_hint.
- template <typename WorkGroupAttr>
- static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t WGSize[3];
- for (unsigned i = 0; i < 3; ++i) {
- const Expr *E = AL.getArgAsExpr(i);
- if (!checkUInt32Argument(S, AL, E, WGSize[i], i,
- /*StrictlyUnsigned=*/true))
- return;
- if (WGSize[i] == 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
- << AL << E->getSourceRange();
- return;
- }
- }
- WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
- if (Existing && !(Existing->getXDim() == WGSize[0] &&
- Existing->getYDim() == WGSize[1] &&
- Existing->getZDim() == WGSize[2]))
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
- D->addAttr(::new (S.Context) WorkGroupAttr(AL.getRange(), S.Context,
- WGSize[0], WGSize[1], WGSize[2],
- AL.getAttributeSpellingListIndex()));
- }
- // Handles intel_reqd_sub_group_size.
- static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t SGSize;
- const Expr *E = AL.getArgAsExpr(0);
- if (!checkUInt32Argument(S, AL, E, SGSize))
- return;
- if (SGSize == 0) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
- << AL << E->getSourceRange();
- return;
- }
- OpenCLIntelReqdSubGroupSizeAttr *Existing =
- D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
- if (Existing && Existing->getSubGroupSize() != SGSize)
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
- D->addAttr(::new (S.Context) OpenCLIntelReqdSubGroupSizeAttr(
- AL.getRange(), S.Context, SGSize,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!AL.hasParsedType()) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
- return;
- }
- TypeSourceInfo *ParmTSI = nullptr;
- QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
- assert(ParmTSI && "no type source info for attribute argument");
- if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
- (ParmType->isBooleanType() ||
- !ParmType->isIntegralType(S.getASTContext()))) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_vec_type_hint)
- << ParmType;
- return;
- }
- if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
- if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
- return;
- }
- }
- D->addAttr(::new (S.Context) VecTypeHintAttr(AL.getLoc(), S.Context,
- ParmTSI,
- AL.getAttributeSpellingListIndex()));
- }
- SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
- StringRef Name,
- unsigned AttrSpellingListIndex) {
- // Explicit or partial specializations do not inherit
- // the section attribute from the primary template.
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (AttrSpellingListIndex == SectionAttr::Declspec_allocate &&
- FD->isFunctionTemplateSpecialization())
- return nullptr;
- }
- if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
- if (ExistingAttr->getName() == Name)
- return nullptr;
- Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
- << 1 /*section*/;
- Diag(Range.getBegin(), diag::note_previous_attribute);
- return nullptr;
- }
- return ::new (Context) SectionAttr(Range, Context, Name,
- AttrSpellingListIndex);
- }
- bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
- std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
- if (!Error.empty()) {
- Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
- << 1 /*'section'*/;
- return false;
- }
- return true;
- }
- static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Make sure that there is a string literal as the sections's single
- // argument.
- StringRef Str;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
- return;
- if (!S.checkSectionName(LiteralLoc, Str))
- return;
- // If the target wants to validate the section specifier, make it happen.
- std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
- if (!Error.empty()) {
- S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
- << Error;
- return;
- }
- unsigned Index = AL.getAttributeSpellingListIndex();
- SectionAttr *NewAttr = S.mergeSectionAttr(D, AL.getRange(), Str, Index);
- if (NewAttr)
- D->addAttr(NewAttr);
- }
- static bool checkCodeSegName(Sema&S, SourceLocation LiteralLoc, StringRef CodeSegName) {
- std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName);
- if (!Error.empty()) {
- S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
- << 0 /*'code-seg'*/;
- return false;
- }
- return true;
- }
- CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, SourceRange Range,
- StringRef Name,
- unsigned AttrSpellingListIndex) {
- // Explicit or partial specializations do not inherit
- // the code_seg attribute from the primary template.
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isFunctionTemplateSpecialization())
- return nullptr;
- }
- if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
- if (ExistingAttr->getName() == Name)
- return nullptr;
- Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
- << 0 /*codeseg*/;
- Diag(Range.getBegin(), diag::note_previous_attribute);
- return nullptr;
- }
- return ::new (Context) CodeSegAttr(Range, Context, Name,
- AttrSpellingListIndex);
- }
- static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef Str;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
- return;
- if (!checkCodeSegName(S, LiteralLoc, Str))
- return;
- if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
- if (!ExistingAttr->isImplicit()) {
- S.Diag(AL.getLoc(),
- ExistingAttr->getName() == Str
- ? diag::warn_duplicate_codeseg_attribute
- : diag::err_conflicting_codeseg_attribute);
- return;
- }
- D->dropAttr<CodeSegAttr>();
- }
- if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL.getRange(), Str,
- AL.getAttributeSpellingListIndex()))
- D->addAttr(CSA);
- }
- // Check for things we'd like to warn about. Multiversioning issues are
- // handled later in the process, once we know how many exist.
- bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
- enum FirstParam { Unsupported, Duplicate };
- enum SecondParam { None, Architecture };
- for (auto Str : {"tune=", "fpmath="})
- if (AttrStr.find(Str) != StringRef::npos)
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str;
- TargetAttr::ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr);
- if (!ParsedAttrs.Architecture.empty() &&
- !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << Architecture << ParsedAttrs.Architecture;
- if (ParsedAttrs.DuplicateArchitecture)
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Duplicate << None << "arch=";
- for (const auto &Feature : ParsedAttrs.Features) {
- auto CurFeature = StringRef(Feature).drop_front(); // remove + or -.
- if (!Context.getTargetInfo().isValidFeatureName(CurFeature))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << CurFeature;
- }
- return false;
- }
- static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef Str;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
- S.checkTargetAttr(LiteralLoc, Str))
- return;
- unsigned Index = AL.getAttributeSpellingListIndex();
- TargetAttr *NewAttr =
- ::new (S.Context) TargetAttr(AL.getRange(), S.Context, Str, Index);
- D->addAttr(NewAttr);
- }
- static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- Expr *E = AL.getArgAsExpr(0);
- uint32_t VecWidth;
- if (!checkUInt32Argument(S, AL, E, VecWidth)) {
- AL.setInvalid();
- return;
- }
- MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>();
- if (Existing && Existing->getVectorWidth() != VecWidth) {
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
- return;
- }
- D->addAttr(::new (S.Context)
- MinVectorWidthAttr(AL.getRange(), S.Context, VecWidth,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- Expr *E = AL.getArgAsExpr(0);
- SourceLocation Loc = E->getExprLoc();
- FunctionDecl *FD = nullptr;
- DeclarationNameInfo NI;
- // gcc only allows for simple identifiers. Since we support more than gcc, we
- // will warn the user.
- if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (DRE->hasQualifier())
- S.Diag(Loc, diag::warn_cleanup_ext);
- FD = dyn_cast<FunctionDecl>(DRE->getDecl());
- NI = DRE->getNameInfo();
- if (!FD) {
- S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
- << NI.getName();
- return;
- }
- } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
- if (ULE->hasExplicitTemplateArgs())
- S.Diag(Loc, diag::warn_cleanup_ext);
- FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
- NI = ULE->getNameInfo();
- if (!FD) {
- S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
- << NI.getName();
- if (ULE->getType() == S.Context.OverloadTy)
- S.NoteAllOverloadCandidates(ULE);
- return;
- }
- } else {
- S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;
- return;
- }
- if (FD->getNumParams() != 1) {
- S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
- << NI.getName();
- return;
- }
- // We're currently more strict than GCC about what function types we accept.
- // If this ever proves to be a problem it should be easy to fix.
- QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType());
- QualType ParamTy = FD->getParamDecl(0)->getType();
- if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
- ParamTy, Ty) != Sema::Compatible) {
- S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
- << NI.getName() << ParamTy << Ty;
- return;
- }
- D->addAttr(::new (S.Context)
- CleanupAttr(AL.getRange(), S.Context, FD,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 0 << AANT_ArgumentIdentifier;
- return;
- }
- EnumExtensibilityAttr::Kind ExtensibilityKind;
- IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
- if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(),
- ExtensibilityKind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
- return;
- }
- D->addAttr(::new (S.Context) EnumExtensibilityAttr(
- AL.getRange(), S.Context, ExtensibilityKind,
- AL.getAttributeSpellingListIndex()));
- }
- /// Handle __attribute__((format_arg((idx)))) attribute based on
- /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
- static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- Expr *IdxExpr = AL.getArgAsExpr(0);
- ParamIdx Idx;
- if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx))
- return;
- // Make sure the format string is really a string.
- QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
- bool NotNSStringTy = !isNSStringType(Ty, S.Context);
- if (NotNSStringTy &&
- !isCFStringType(Ty, S.Context) &&
- (!Ty->isPointerType() ||
- !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- S.Diag(AL.getLoc(), diag::err_format_attribute_not)
- << "a string type" << IdxExpr->getSourceRange()
- << getFunctionOrMethodParamRange(D, 0);
- return;
- }
- Ty = getFunctionOrMethodResultType(D);
- if (!isNSStringType(Ty, S.Context) &&
- !isCFStringType(Ty, S.Context) &&
- (!Ty->isPointerType() ||
- !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
- S.Diag(AL.getLoc(), diag::err_format_attribute_result_not)
- << (NotNSStringTy ? "string type" : "NSString")
- << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
- return;
- }
- D->addAttr(::new (S.Context) FormatArgAttr(
- AL.getRange(), S.Context, Idx, AL.getAttributeSpellingListIndex()));
- }
- enum FormatAttrKind {
- CFStringFormat,
- NSStringFormat,
- StrftimeFormat,
- SupportedFormat,
- IgnoredFormat,
- InvalidFormat
- };
- /// getFormatAttrKind - Map from format attribute names to supported format
- /// types.
- static FormatAttrKind getFormatAttrKind(StringRef Format) {
- return llvm::StringSwitch<FormatAttrKind>(Format)
- // Check for formats that get handled specially.
- .Case("NSString", NSStringFormat)
- .Case("CFString", CFStringFormat)
- .Case("strftime", StrftimeFormat)
- // Otherwise, check for supported formats.
- .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
- .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
- .Case("kprintf", SupportedFormat) // OpenBSD.
- .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
- .Case("os_trace", SupportedFormat)
- .Case("os_log", SupportedFormat)
- .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
- .Default(InvalidFormat);
- }
- /// Handle __attribute__((init_priority(priority))) attributes based on
- /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
- static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!S.getLangOpts().CPlusPlus) {
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
- return;
- }
- if (S.getCurFunctionOrMethodDecl()) {
- S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
- AL.setInvalid();
- return;
- }
- QualType T = cast<VarDecl>(D)->getType();
- if (S.Context.getAsArrayType(T))
- T = S.Context.getBaseElementType(T);
- if (!T->getAs<RecordType>()) {
- S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
- AL.setInvalid();
- return;
- }
- Expr *E = AL.getArgAsExpr(0);
- uint32_t prioritynum;
- if (!checkUInt32Argument(S, AL, E, prioritynum)) {
- AL.setInvalid();
- return;
- }
- if (prioritynum < 101 || prioritynum > 65535) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
- << E->getSourceRange() << AL << 101 << 65535;
- AL.setInvalid();
- return;
- }
- D->addAttr(::new (S.Context)
- InitPriorityAttr(AL.getRange(), S.Context, prioritynum,
- AL.getAttributeSpellingListIndex()));
- }
- FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
- IdentifierInfo *Format, int FormatIdx,
- int FirstArg,
- unsigned AttrSpellingListIndex) {
- // Check whether we already have an equivalent format attribute.
- for (auto *F : D->specific_attrs<FormatAttr>()) {
- if (F->getType() == Format &&
- F->getFormatIdx() == FormatIdx &&
- F->getFirstArg() == FirstArg) {
- // If we don't have a valid location for this attribute, adopt the
- // location.
- if (F->getLocation().isInvalid())
- F->setRange(Range);
- return nullptr;
- }
- }
- return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx,
- FirstArg, AttrSpellingListIndex);
- }
- /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
- /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
- static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIdentifier;
- return;
- }
- // In C++ the implicit 'this' function parameter also counts, and they are
- // counted from one.
- bool HasImplicitThisParam = isInstanceMethod(D);
- unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
- IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
- StringRef Format = II->getName();
- if (normalizeName(Format)) {
- // If we've modified the string name, we need a new identifier for it.
- II = &S.Context.Idents.get(Format);
- }
- // Check for supported formats.
- FormatAttrKind Kind = getFormatAttrKind(Format);
- if (Kind == IgnoredFormat)
- return;
- if (Kind == InvalidFormat) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL << II->getName();
- return;
- }
- // checks for the 2nd argument
- Expr *IdxExpr = AL.getArgAsExpr(1);
- uint32_t Idx;
- if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2))
- return;
- if (Idx < 1 || Idx > NumArgs) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << 2 << IdxExpr->getSourceRange();
- return;
- }
- // FIXME: Do we need to bounds check?
- unsigned ArgIdx = Idx - 1;
- if (HasImplicitThisParam) {
- if (ArgIdx == 0) {
- S.Diag(AL.getLoc(),
- diag::err_format_attribute_implicit_this_format_string)
- << IdxExpr->getSourceRange();
- return;
- }
- ArgIdx--;
- }
- // make sure the format string is really a string
- QualType Ty = getFunctionOrMethodParamType(D, ArgIdx);
- if (Kind == CFStringFormat) {
- if (!isCFStringType(Ty, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_format_attribute_not)
- << "a CFString" << IdxExpr->getSourceRange()
- << getFunctionOrMethodParamRange(D, ArgIdx);
- return;
- }
- } else if (Kind == NSStringFormat) {
- // FIXME: do we need to check if the type is NSString*? What are the
- // semantics?
- if (!isNSStringType(Ty, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_format_attribute_not)
- << "an NSString" << IdxExpr->getSourceRange()
- << getFunctionOrMethodParamRange(D, ArgIdx);
- return;
- }
- } else if (!Ty->isPointerType() ||
- !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
- S.Diag(AL.getLoc(), diag::err_format_attribute_not)
- << "a string type" << IdxExpr->getSourceRange()
- << getFunctionOrMethodParamRange(D, ArgIdx);
- return;
- }
- // check the 3rd argument
- Expr *FirstArgExpr = AL.getArgAsExpr(2);
- uint32_t FirstArg;
- if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3))
- return;
- // check if the function is variadic if the 3rd argument non-zero
- if (FirstArg != 0) {
- if (isFunctionOrMethodVariadic(D)) {
- ++NumArgs; // +1 for ...
- } else {
- S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic);
- return;
- }
- }
- // strftime requires FirstArg to be 0 because it doesn't read from any
- // variable the input is just the current time + the format string.
- if (Kind == StrftimeFormat) {
- if (FirstArg != 0) {
- S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter)
- << FirstArgExpr->getSourceRange();
- return;
- }
- // if 0 it disables parameter checking (to use with e.g. va_list)
- } else if (FirstArg != 0 && FirstArg != NumArgs) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << 3 << FirstArgExpr->getSourceRange();
- return;
- }
- FormatAttr *NewAttr = S.mergeFormatAttr(D, AL.getRange(), II,
- Idx, FirstArg,
- AL.getAttributeSpellingListIndex());
- if (NewAttr)
- D->addAttr(NewAttr);
- }
- /// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes.
- static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // The index that identifies the callback callee is mandatory.
- if (AL.getNumArgs() == 0) {
- S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee)
- << AL.getRange();
- return;
- }
- bool HasImplicitThisParam = isInstanceMethod(D);
- int32_t NumArgs = getFunctionOrMethodNumParams(D);
- FunctionDecl *FD = D->getAsFunction();
- assert(FD && "Expected a function declaration!");
- llvm::StringMap<int> NameIdxMapping;
- NameIdxMapping["__"] = -1;
- NameIdxMapping["this"] = 0;
- int Idx = 1;
- for (const ParmVarDecl *PVD : FD->parameters())
- NameIdxMapping[PVD->getName()] = Idx++;
- auto UnknownName = NameIdxMapping.end();
- SmallVector<int, 8> EncodingIndices;
- for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) {
- SourceRange SR;
- int32_t ArgIdx;
- if (AL.isArgIdent(I)) {
- IdentifierLoc *IdLoc = AL.getArgAsIdent(I);
- auto It = NameIdxMapping.find(IdLoc->Ident->getName());
- if (It == UnknownName) {
- S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown)
- << IdLoc->Ident << IdLoc->Loc;
- return;
- }
- SR = SourceRange(IdLoc->Loc);
- ArgIdx = It->second;
- } else if (AL.isArgExpr(I)) {
- Expr *IdxExpr = AL.getArgAsExpr(I);
- // If the expression is not parseable as an int32_t we have a problem.
- if (!checkUInt32Argument(S, AL, IdxExpr, (uint32_t &)ArgIdx, I + 1,
- false)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << (I + 1) << IdxExpr->getSourceRange();
- return;
- }
- // Check oob, excluding the special values, 0 and -1.
- if (ArgIdx < -1 || ArgIdx > NumArgs) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << (I + 1) << IdxExpr->getSourceRange();
- return;
- }
- SR = IdxExpr->getSourceRange();
- } else {
- llvm_unreachable("Unexpected ParsedAttr argument type!");
- }
- if (ArgIdx == 0 && !HasImplicitThisParam) {
- S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available)
- << (I + 1) << SR;
- return;
- }
- // Adjust for the case we do not have an implicit "this" parameter. In this
- // case we decrease all positive values by 1 to get LLVM argument indices.
- if (!HasImplicitThisParam && ArgIdx > 0)
- ArgIdx -= 1;
- EncodingIndices.push_back(ArgIdx);
- }
- int CalleeIdx = EncodingIndices.front();
- // Check if the callee index is proper, thus not "this" and not "unknown".
- // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam"
- // is false and positive if "HasImplicitThisParam" is true.
- if (CalleeIdx < (int)HasImplicitThisParam) {
- S.Diag(AL.getLoc(), diag::err_callback_attribute_invalid_callee)
- << AL.getRange();
- return;
- }
- // Get the callee type, note the index adjustment as the AST doesn't contain
- // the this type (which the callee cannot reference anyway!).
- const Type *CalleeType =
- getFunctionOrMethodParamType(D, CalleeIdx - HasImplicitThisParam)
- .getTypePtr();
- if (!CalleeType || !CalleeType->isFunctionPointerType()) {
- S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type)
- << AL.getRange();
- return;
- }
- const Type *CalleeFnType =
- CalleeType->getPointeeType()->getUnqualifiedDesugaredType();
- // TODO: Check the type of the callee arguments.
- const auto *CalleeFnProtoType = dyn_cast<FunctionProtoType>(CalleeFnType);
- if (!CalleeFnProtoType) {
- S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type)
- << AL.getRange();
- return;
- }
- if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL << (unsigned)(EncodingIndices.size() - 1);
- return;
- }
- if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
- << AL << (unsigned)(EncodingIndices.size() - 1);
- return;
- }
- if (CalleeFnProtoType->isVariadic()) {
- S.Diag(AL.getLoc(), diag::err_callback_callee_is_variadic) << AL.getRange();
- return;
- }
- // Do not allow multiple callback attributes.
- if (D->hasAttr<CallbackAttr>()) {
- S.Diag(AL.getLoc(), diag::err_callback_attribute_multiple) << AL.getRange();
- return;
- }
- D->addAttr(::new (S.Context) CallbackAttr(
- AL.getRange(), S.Context, EncodingIndices.data(), EncodingIndices.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Try to find the underlying union declaration.
- RecordDecl *RD = nullptr;
- const auto *TD = dyn_cast<TypedefNameDecl>(D);
- if (TD && TD->getUnderlyingType()->isUnionType())
- RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
- else
- RD = dyn_cast<RecordDecl>(D);
- if (!RD || !RD->isUnion()) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL
- << ExpectedUnion;
- return;
- }
- if (!RD->isCompleteDefinition()) {
- if (!RD->isBeingDefined())
- S.Diag(AL.getLoc(),
- diag::warn_transparent_union_attribute_not_definition);
- return;
- }
- RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end();
- if (Field == FieldEnd) {
- S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
- return;
- }
- FieldDecl *FirstField = *Field;
- QualType FirstType = FirstField->getType();
- if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
- S.Diag(FirstField->getLocation(),
- diag::warn_transparent_union_attribute_floating)
- << FirstType->isVectorType() << FirstType;
- return;
- }
- if (FirstType->isIncompleteType())
- return;
- uint64_t FirstSize = S.Context.getTypeSize(FirstType);
- uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
- for (; Field != FieldEnd; ++Field) {
- QualType FieldType = Field->getType();
- if (FieldType->isIncompleteType())
- return;
- // FIXME: this isn't fully correct; we also need to test whether the
- // members of the union would all have the same calling convention as the
- // first member of the union. Checking just the size and alignment isn't
- // sufficient (consider structs passed on the stack instead of in registers
- // as an example).
- if (S.Context.getTypeSize(FieldType) != FirstSize ||
- S.Context.getTypeAlign(FieldType) > FirstAlign) {
- // Warn if we drop the attribute.
- bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
- unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
- : S.Context.getTypeAlign(FieldType);
- S.Diag(Field->getLocation(),
- diag::warn_transparent_union_attribute_field_size_align)
- << isSize << Field->getDeclName() << FieldBits;
- unsigned FirstBits = isSize? FirstSize : FirstAlign;
- S.Diag(FirstField->getLocation(),
- diag::note_transparent_union_first_field_size_align)
- << isSize << FirstBits;
- return;
- }
- }
- RD->addAttr(::new (S.Context)
- TransparentUnionAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Make sure that there is a string literal as the annotation's single
- // argument.
- StringRef Str;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
- return;
- // Don't duplicate annotations that are already set.
- for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
- if (I->getAnnotation() == Str)
- return;
- }
- D->addAttr(::new (S.Context)
- AnnotateAttr(AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- S.AddAlignValueAttr(AL.getRange(), D, AL.getArgAsExpr(0),
- AL.getAttributeSpellingListIndex());
- }
- void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
- unsigned SpellingListIndex) {
- AlignValueAttr TmpAttr(AttrRange, Context, E, SpellingListIndex);
- SourceLocation AttrLoc = AttrRange.getBegin();
- QualType T;
- if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
- T = TD->getUnderlyingType();
- else if (const auto *VD = dyn_cast<ValueDecl>(D))
- T = VD->getType();
- else
- llvm_unreachable("Unknown decl type for align_value");
- if (!T->isDependentType() && !T->isAnyPointerType() &&
- !T->isReferenceType() && !T->isMemberPointerType()) {
- Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
- << &TmpAttr /*TmpAttr.getName()*/ << T << D->getSourceRange();
- return;
- }
- if (!E->isValueDependent()) {
- llvm::APSInt Alignment;
- ExprResult ICE
- = VerifyIntegerConstantExpression(E, &Alignment,
- diag::err_align_value_attribute_argument_not_int,
- /*AllowFold*/ false);
- if (ICE.isInvalid())
- return;
- if (!Alignment.isPowerOf2()) {
- Diag(AttrLoc, diag::err_alignment_not_power_of_two)
- << E->getSourceRange();
- return;
- }
- D->addAttr(::new (Context)
- AlignValueAttr(AttrRange, Context, ICE.get(),
- SpellingListIndex));
- return;
- }
- // Save dependent expressions in the AST to be instantiated.
- D->addAttr(::new (Context) AlignValueAttr(TmpAttr));
- }
- static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // check the attribute arguments.
- if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
- return;
- }
- if (AL.getNumArgs() == 0) {
- D->addAttr(::new (S.Context) AlignedAttr(AL.getRange(), S.Context,
- true, nullptr, AL.getAttributeSpellingListIndex()));
- return;
- }
- Expr *E = AL.getArgAsExpr(0);
- if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
- S.Diag(AL.getEllipsisLoc(),
- diag::err_pack_expansion_without_parameter_packs);
- return;
- }
- if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
- return;
- S.AddAlignedAttr(AL.getRange(), D, E, AL.getAttributeSpellingListIndex(),
- AL.isPackExpansion());
- }
- void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
- unsigned SpellingListIndex, bool IsPackExpansion) {
- AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex);
- SourceLocation AttrLoc = AttrRange.getBegin();
- // C++11 alignas(...) and C11 _Alignas(...) have additional requirements.
- if (TmpAttr.isAlignas()) {
- // C++11 [dcl.align]p1:
- // An alignment-specifier may be applied to a variable or to a class
- // data member, but it shall not be applied to a bit-field, a function
- // parameter, the formal parameter of a catch clause, or a variable
- // declared with the register storage class specifier. An
- // alignment-specifier may also be applied to the declaration of a class
- // or enumeration type.
- // C11 6.7.5/2:
- // An alignment attribute shall not be specified in a declaration of
- // a typedef, or a bit-field, or a function, or a parameter, or an
- // object declared with the register storage-class specifier.
- int DiagKind = -1;
- if (isa<ParmVarDecl>(D)) {
- DiagKind = 0;
- } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
- if (VD->getStorageClass() == SC_Register)
- DiagKind = 1;
- if (VD->isExceptionVariable())
- DiagKind = 2;
- } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
- if (FD->isBitField())
- DiagKind = 3;
- } else if (!isa<TagDecl>(D)) {
- Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
- << (TmpAttr.isC11() ? ExpectedVariableOrField
- : ExpectedVariableFieldOrTag);
- return;
- }
- if (DiagKind != -1) {
- Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
- << &TmpAttr << DiagKind;
- return;
- }
- }
- if (E->isValueDependent()) {
- // We can't support a dependent alignment on a non-dependent type,
- // because we have no way to model that a type is "alignment-dependent"
- // but not dependent in any other way.
- if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
- if (!TND->getUnderlyingType()->isDependentType()) {
- Diag(AttrLoc, diag::err_alignment_dependent_typedef_name)
- << E->getSourceRange();
- return;
- }
- }
- // Save dependent expressions in the AST to be instantiated.
- AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr);
- AA->setPackExpansion(IsPackExpansion);
- D->addAttr(AA);
- return;
- }
- // FIXME: Cache the number on the AL object?
- llvm::APSInt Alignment;
- ExprResult ICE
- = VerifyIntegerConstantExpression(E, &Alignment,
- diag::err_aligned_attribute_argument_not_int,
- /*AllowFold*/ false);
- if (ICE.isInvalid())
- return;
- uint64_t AlignVal = Alignment.getZExtValue();
- // C++11 [dcl.align]p2:
- // -- if the constant expression evaluates to zero, the alignment
- // specifier shall have no effect
- // C11 6.7.5p6:
- // An alignment specification of zero has no effect.
- if (!(TmpAttr.isAlignas() && !Alignment)) {
- if (!llvm::isPowerOf2_64(AlignVal)) {
- Diag(AttrLoc, diag::err_alignment_not_power_of_two)
- << E->getSourceRange();
- return;
- }
- }
- // Alignment calculations can wrap around if it's greater than 2**28.
- unsigned MaxValidAlignment =
- Context.getTargetInfo().getTriple().isOSBinFormatCOFF() ? 8192
- : 268435456;
- if (AlignVal > MaxValidAlignment) {
- Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
- << E->getSourceRange();
- return;
- }
- if (Context.getTargetInfo().isTLSSupported()) {
- unsigned MaxTLSAlign =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
- .getQuantity();
- const auto *VD = dyn_cast<VarDecl>(D);
- if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
- VD->getTLSKind() != VarDecl::TLS_None) {
- Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
- << (unsigned)AlignVal << VD << MaxTLSAlign;
- return;
- }
- }
- AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
- ICE.get(), SpellingListIndex);
- AA->setPackExpansion(IsPackExpansion);
- D->addAttr(AA);
- }
- void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
- unsigned SpellingListIndex, bool IsPackExpansion) {
- // FIXME: Cache the number on the AL object if non-dependent?
- // FIXME: Perform checking of type validity
- AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS,
- SpellingListIndex);
- AA->setPackExpansion(IsPackExpansion);
- D->addAttr(AA);
- }
- void Sema::CheckAlignasUnderalignment(Decl *D) {
- assert(D->hasAttrs() && "no attributes on decl");
- QualType UnderlyingTy, DiagTy;
- if (const auto *VD = dyn_cast<ValueDecl>(D)) {
- UnderlyingTy = DiagTy = VD->getType();
- } else {
- UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
- if (const auto *ED = dyn_cast<EnumDecl>(D))
- UnderlyingTy = ED->getIntegerType();
- }
- if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
- return;
- // C++11 [dcl.align]p5, C11 6.7.5/4:
- // The combined effect of all alignment attributes in a declaration shall
- // not specify an alignment that is less strict than the alignment that
- // would otherwise be required for the entity being declared.
- AlignedAttr *AlignasAttr = nullptr;
- unsigned Align = 0;
- for (auto *I : D->specific_attrs<AlignedAttr>()) {
- if (I->isAlignmentDependent())
- return;
- if (I->isAlignas())
- AlignasAttr = I;
- Align = std::max(Align, I->getAlignment(Context));
- }
- if (AlignasAttr && Align) {
- CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
- CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy);
- if (NaturalAlign > RequestedAlign)
- Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
- << DiagTy << (unsigned)NaturalAlign.getQuantity();
- }
- }
- bool Sema::checkMSInheritanceAttrOnDefinition(
- CXXRecordDecl *RD, SourceRange Range, bool BestCase,
- MSInheritanceAttr::Spelling SemanticSpelling) {
- assert(RD->hasDefinition() && "RD has no definition!");
- // We may not have seen base specifiers or any virtual methods yet. We will
- // have to wait until the record is defined to catch any mismatches.
- if (!RD->getDefinition()->isCompleteDefinition())
- return false;
- // The unspecified model never matches what a definition could need.
- if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance)
- return false;
- if (BestCase) {
- if (RD->calculateInheritanceModel() == SemanticSpelling)
- return false;
- } else {
- if (RD->calculateInheritanceModel() <= SemanticSpelling)
- return false;
- }
- Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
- << 0 /*definition*/;
- Diag(RD->getDefinition()->getLocation(), diag::note_defined_here)
- << RD->getNameAsString();
- return true;
- }
- /// parseModeAttrArg - Parses attribute mode string and returns parsed type
- /// attribute.
- static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
- bool &IntegerMode, bool &ComplexMode) {
- IntegerMode = true;
- ComplexMode = false;
- switch (Str.size()) {
- case 2:
- switch (Str[0]) {
- case 'Q':
- DestWidth = 8;
- break;
- case 'H':
- DestWidth = 16;
- break;
- case 'S':
- DestWidth = 32;
- break;
- case 'D':
- DestWidth = 64;
- break;
- case 'X':
- DestWidth = 96;
- break;
- case 'T':
- DestWidth = 128;
- break;
- }
- if (Str[1] == 'F') {
- IntegerMode = false;
- } else if (Str[1] == 'C') {
- IntegerMode = false;
- ComplexMode = true;
- } else if (Str[1] != 'I') {
- DestWidth = 0;
- }
- break;
- case 4:
- // FIXME: glibc uses 'word' to define register_t; this is narrower than a
- // pointer on PIC16 and other embedded platforms.
- if (Str == "word")
- DestWidth = S.Context.getTargetInfo().getRegisterWidth();
- else if (Str == "byte")
- DestWidth = S.Context.getTargetInfo().getCharWidth();
- break;
- case 7:
- if (Str == "pointer")
- DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
- break;
- case 11:
- if (Str == "unwind_word")
- DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
- break;
- }
- }
- /// handleModeAttr - This attribute modifies the width of a decl with primitive
- /// type.
- ///
- /// Despite what would be logical, the mode attribute is a decl attribute, not a
- /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
- /// HImode, not an intermediate pointer.
- static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // This attribute isn't documented, but glibc uses it. It changes
- // the width of an int or unsigned int to the specified size.
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
- IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident;
- S.AddModeAttr(AL.getRange(), D, Name, AL.getAttributeSpellingListIndex());
- }
- void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
- unsigned SpellingListIndex, bool InInstantiation) {
- StringRef Str = Name->getName();
- normalizeName(Str);
- SourceLocation AttrLoc = AttrRange.getBegin();
- unsigned DestWidth = 0;
- bool IntegerMode = true;
- bool ComplexMode = false;
- llvm::APInt VectorSize(64, 0);
- if (Str.size() >= 4 && Str[0] == 'V') {
- // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
- size_t StrSize = Str.size();
- size_t VectorStringLength = 0;
- while ((VectorStringLength + 1) < StrSize &&
- isdigit(Str[VectorStringLength + 1]))
- ++VectorStringLength;
- if (VectorStringLength &&
- !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
- VectorSize.isPowerOf2()) {
- parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
- IntegerMode, ComplexMode);
- // Avoid duplicate warning from template instantiation.
- if (!InInstantiation)
- Diag(AttrLoc, diag::warn_vector_mode_deprecated);
- } else {
- VectorSize = 0;
- }
- }
- if (!VectorSize)
- parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
- // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
- // and friends, at least with glibc.
- // FIXME: Make sure floating-point mappings are accurate
- // FIXME: Support XF and TF types
- if (!DestWidth) {
- Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
- return;
- }
- QualType OldTy;
- if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
- OldTy = TD->getUnderlyingType();
- else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
- // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
- // Try to get type from enum declaration, default to int.
- OldTy = ED->getIntegerType();
- if (OldTy.isNull())
- OldTy = Context.IntTy;
- } else
- OldTy = cast<ValueDecl>(D)->getType();
- if (OldTy->isDependentType()) {
- D->addAttr(::new (Context)
- ModeAttr(AttrRange, Context, Name, SpellingListIndex));
- return;
- }
- // Base type can also be a vector type (see PR17453).
- // Distinguish between base type and base element type.
- QualType OldElemTy = OldTy;
- if (const auto *VT = OldTy->getAs<VectorType>())
- OldElemTy = VT->getElementType();
- // GCC allows 'mode' attribute on enumeration types (even incomplete), except
- // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete
- // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected.
- if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) &&
- VectorSize.getBoolValue()) {
- Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << AttrRange;
- return;
- }
- bool IntegralOrAnyEnumType =
- OldElemTy->isIntegralOrEnumerationType() || OldElemTy->getAs<EnumType>();
- if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
- !IntegralOrAnyEnumType)
- Diag(AttrLoc, diag::err_mode_not_primitive);
- else if (IntegerMode) {
- if (!IntegralOrAnyEnumType)
- Diag(AttrLoc, diag::err_mode_wrong_type);
- } else if (ComplexMode) {
- if (!OldElemTy->isComplexType())
- Diag(AttrLoc, diag::err_mode_wrong_type);
- } else {
- if (!OldElemTy->isFloatingType())
- Diag(AttrLoc, diag::err_mode_wrong_type);
- }
- QualType NewElemTy;
- if (IntegerMode)
- NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
- OldElemTy->isSignedIntegerType());
- else
- NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
- if (NewElemTy.isNull()) {
- Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
- return;
- }
- if (ComplexMode) {
- NewElemTy = Context.getComplexType(NewElemTy);
- }
- QualType NewTy = NewElemTy;
- if (VectorSize.getBoolValue()) {
- NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
- VectorType::GenericVector);
- } else if (const auto *OldVT = OldTy->getAs<VectorType>()) {
- // Complex machine mode does not support base vector types.
- if (ComplexMode) {
- Diag(AttrLoc, diag::err_complex_mode_vector_type);
- return;
- }
- unsigned NumElements = Context.getTypeSize(OldElemTy) *
- OldVT->getNumElements() /
- Context.getTypeSize(NewElemTy);
- NewTy =
- Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
- }
- if (NewTy.isNull()) {
- Diag(AttrLoc, diag::err_mode_wrong_type);
- return;
- }
- // Install the new type.
- if (auto *TD = dyn_cast<TypedefNameDecl>(D))
- TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
- else if (auto *ED = dyn_cast<EnumDecl>(D))
- ED->setIntegerType(NewTy);
- else
- cast<ValueDecl>(D)->setType(NewTy);
- D->addAttr(::new (Context)
- ModeAttr(AttrRange, Context, Name, SpellingListIndex));
- }
- static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- D->addAttr(::new (S.Context)
- NoDebugAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
- IdentifierInfo *Ident,
- unsigned AttrSpellingListIndex) {
- if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << Ident;
- Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
- return nullptr;
- }
- if (D->hasAttr<AlwaysInlineAttr>())
- return nullptr;
- return ::new (Context) AlwaysInlineAttr(Range, Context,
- AttrSpellingListIndex);
- }
- CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL))
- return nullptr;
- return ::new (Context)
- CommonAttr(AL.getRange(), Context, AL.getAttributeSpellingListIndex());
- }
- CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) {
- if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL))
- return nullptr;
- return ::new (Context)
- CommonAttr(AL.getRange(), Context, AL.getSpellingListIndex());
- }
- InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D,
- const ParsedAttr &AL) {
- if (const auto *VD = dyn_cast<VarDecl>(D)) {
- // Attribute applies to Var but not any subclass of it (like ParmVar,
- // ImplicitParm or VarTemplateSpecialization).
- if (VD->getKind() != Decl::Var) {
- Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
- : ExpectedVariableOrFunction);
- return nullptr;
- }
- // Attribute does not apply to non-static local variables.
- if (VD->hasLocalStorage()) {
- Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
- return nullptr;
- }
- }
- if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL))
- return nullptr;
- return ::new (Context) InternalLinkageAttr(
- AL.getRange(), Context, AL.getAttributeSpellingListIndex());
- }
- InternalLinkageAttr *
- Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) {
- if (const auto *VD = dyn_cast<VarDecl>(D)) {
- // Attribute applies to Var but not any subclass of it (like ParmVar,
- // ImplicitParm or VarTemplateSpecialization).
- if (VD->getKind() != Decl::Var) {
- Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type)
- << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
- : ExpectedVariableOrFunction);
- return nullptr;
- }
- // Attribute does not apply to non-static local variables.
- if (VD->hasLocalStorage()) {
- Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
- return nullptr;
- }
- }
- if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL))
- return nullptr;
- return ::new (Context)
- InternalLinkageAttr(AL.getRange(), Context, AL.getSpellingListIndex());
- }
- MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'minsize'";
- Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
- return nullptr;
- }
- if (D->hasAttr<MinSizeAttr>())
- return nullptr;
- return ::new (Context) MinSizeAttr(Range, Context, AttrSpellingListIndex);
- }
- NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr(
- Decl *D, const NoSpeculativeLoadHardeningAttr &AL) {
- if (checkAttrMutualExclusion<SpeculativeLoadHardeningAttr>(*this, D, AL))
- return nullptr;
- return ::new (Context) NoSpeculativeLoadHardeningAttr(
- AL.getRange(), Context, AL.getSpellingListIndex());
- }
- OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
- Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline;
- Diag(Range.getBegin(), diag::note_conflicting_attribute);
- D->dropAttr<AlwaysInlineAttr>();
- }
- if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) {
- Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize;
- Diag(Range.getBegin(), diag::note_conflicting_attribute);
- D->dropAttr<MinSizeAttr>();
- }
- if (D->hasAttr<OptimizeNoneAttr>())
- return nullptr;
- return ::new (Context) OptimizeNoneAttr(Range, Context,
- AttrSpellingListIndex);
- }
- SpeculativeLoadHardeningAttr *Sema::mergeSpeculativeLoadHardeningAttr(
- Decl *D, const SpeculativeLoadHardeningAttr &AL) {
- if (checkAttrMutualExclusion<NoSpeculativeLoadHardeningAttr>(*this, D, AL))
- return nullptr;
- return ::new (Context) SpeculativeLoadHardeningAttr(
- AL.getRange(), Context, AL.getSpellingListIndex());
- }
- static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL))
- return;
- if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
- D, AL.getRange(), AL.getName(),
- AL.getAttributeSpellingListIndex()))
- D->addAttr(Inline);
- }
- static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(
- D, AL.getRange(), AL.getAttributeSpellingListIndex()))
- D->addAttr(MinSize);
- }
- static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(
- D, AL.getRange(), AL.getAttributeSpellingListIndex()))
- D->addAttr(Optnone);
- }
- static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL))
- return;
- const auto *VD = cast<VarDecl>(D);
- if (!VD->hasGlobalStorage()) {
- S.Diag(AL.getLoc(), diag::err_cuda_nonglobal_constant);
- return;
- }
- D->addAttr(::new (S.Context) CUDAConstantAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL))
- return;
- const auto *VD = cast<VarDecl>(D);
- // extern __shared__ is only allowed on arrays with no length (e.g.
- // "int x[]").
- if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() &&
- !isa<IncompleteArrayType>(VD->getType())) {
- S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD;
- return;
- }
- if (S.getLangOpts().CUDA && VD->hasLocalStorage() &&
- S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared)
- << S.CurrentCUDATarget())
- return;
- D->addAttr(::new (S.Context) CUDASharedAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) ||
- checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) {
- return;
- }
- const auto *FD = cast<FunctionDecl>(D);
- if (!FD->getReturnType()->isVoidType()) {
- SourceRange RTRange = FD->getReturnTypeSourceRange();
- S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
- << FD->getType()
- << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
- : FixItHint());
- return;
- }
- if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
- if (Method->isInstance()) {
- S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method)
- << Method;
- return;
- }
- S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method;
- }
- // Only warn for "inline" when compiling for host, to cut down on noise.
- if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice)
- S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD;
- D->addAttr(::new (S.Context)
- CUDAGlobalAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- const auto *Fn = cast<FunctionDecl>(D);
- if (!Fn->isInlineSpecified()) {
- S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
- return;
- }
- D->addAttr(::new (S.Context)
- GNUInlineAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (hasDeclarator(D)) return;
- // Diagnostic is emitted elsewhere: here we store the (valid) AL
- // in the Decl node for syntactic reasoning, e.g., pretty-printing.
- CallingConv CC;
- if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr))
- return;
- if (!isa<ObjCMethodDecl>(D)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionOrMethod;
- return;
- }
- switch (AL.getKind()) {
- case ParsedAttr::AT_FastCall:
- D->addAttr(::new (S.Context)
- FastCallAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_StdCall:
- D->addAttr(::new (S.Context)
- StdCallAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_ThisCall:
- D->addAttr(::new (S.Context)
- ThisCallAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_CDecl:
- D->addAttr(::new (S.Context)
- CDeclAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_Pascal:
- D->addAttr(::new (S.Context)
- PascalAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_SwiftCall:
- D->addAttr(::new (S.Context)
- SwiftCallAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_VectorCall:
- D->addAttr(::new (S.Context)
- VectorCallAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_MSABI:
- D->addAttr(::new (S.Context)
- MSABIAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_SysVABI:
- D->addAttr(::new (S.Context)
- SysVABIAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_RegCall:
- D->addAttr(::new (S.Context) RegCallAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_Pcs: {
- PcsAttr::PCSType PCS;
- switch (CC) {
- case CC_AAPCS:
- PCS = PcsAttr::AAPCS;
- break;
- case CC_AAPCS_VFP:
- PCS = PcsAttr::AAPCS_VFP;
- break;
- default:
- llvm_unreachable("unexpected calling convention in pcs attribute");
- }
- D->addAttr(::new (S.Context)
- PcsAttr(AL.getRange(), S.Context, PCS,
- AL.getAttributeSpellingListIndex()));
- return;
- }
- case ParsedAttr::AT_AArch64VectorPcs:
- D->addAttr(::new(S.Context)
- AArch64VectorPcsAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_IntelOclBicc:
- D->addAttr(::new (S.Context)
- IntelOclBiccAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_PreserveMost:
- D->addAttr(::new (S.Context) PreserveMostAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- return;
- case ParsedAttr::AT_PreserveAll:
- D->addAttr(::new (S.Context) PreserveAllAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- return;
- default:
- llvm_unreachable("unexpected attribute kind");
- }
- }
- static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- std::vector<StringRef> DiagnosticIdentifiers;
- for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
- StringRef RuleName;
- if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr))
- return;
- // FIXME: Warn if the rule name is unknown. This is tricky because only
- // clang-tidy knows about available rules.
- DiagnosticIdentifiers.push_back(RuleName);
- }
- D->addAttr(::new (S.Context) SuppressAttr(
- AL.getRange(), S.Context, DiagnosticIdentifiers.data(),
- DiagnosticIdentifiers.size(), AL.getAttributeSpellingListIndex()));
- }
- bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
- const FunctionDecl *FD) {
- if (Attrs.isInvalid())
- return true;
- if (Attrs.hasProcessingCache()) {
- CC = (CallingConv) Attrs.getProcessingCache();
- return false;
- }
- unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
- if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) {
- Attrs.setInvalid();
- return true;
- }
- // TODO: diagnose uses of these conventions on the wrong target.
- switch (Attrs.getKind()) {
- case ParsedAttr::AT_CDecl:
- CC = CC_C;
- break;
- case ParsedAttr::AT_FastCall:
- CC = CC_X86FastCall;
- break;
- case ParsedAttr::AT_StdCall:
- CC = CC_X86StdCall;
- break;
- case ParsedAttr::AT_ThisCall:
- CC = CC_X86ThisCall;
- break;
- case ParsedAttr::AT_Pascal:
- CC = CC_X86Pascal;
- break;
- case ParsedAttr::AT_SwiftCall:
- CC = CC_Swift;
- break;
- case ParsedAttr::AT_VectorCall:
- CC = CC_X86VectorCall;
- break;
- case ParsedAttr::AT_AArch64VectorPcs:
- CC = CC_AArch64VectorCall;
- break;
- case ParsedAttr::AT_RegCall:
- CC = CC_X86RegCall;
- break;
- case ParsedAttr::AT_MSABI:
- CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
- CC_Win64;
- break;
- case ParsedAttr::AT_SysVABI:
- CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
- CC_C;
- break;
- case ParsedAttr::AT_Pcs: {
- StringRef StrRef;
- if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) {
- Attrs.setInvalid();
- return true;
- }
- if (StrRef == "aapcs") {
- CC = CC_AAPCS;
- break;
- } else if (StrRef == "aapcs-vfp") {
- CC = CC_AAPCS_VFP;
- break;
- }
- Attrs.setInvalid();
- Diag(Attrs.getLoc(), diag::err_invalid_pcs);
- return true;
- }
- case ParsedAttr::AT_IntelOclBicc:
- CC = CC_IntelOclBicc;
- break;
- case ParsedAttr::AT_PreserveMost:
- CC = CC_PreserveMost;
- break;
- case ParsedAttr::AT_PreserveAll:
- CC = CC_PreserveAll;
- break;
- default: llvm_unreachable("unexpected attribute kind");
- }
- TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK;
- const TargetInfo &TI = Context.getTargetInfo();
- // CUDA functions may have host and/or device attributes which indicate
- // their targeted execution environment, therefore the calling convention
- // of functions in CUDA should be checked against the target deduced based
- // on their host/device attributes.
- if (LangOpts.CUDA) {
- auto *Aux = Context.getAuxTargetInfo();
- auto CudaTarget = IdentifyCUDATarget(FD);
- bool CheckHost = false, CheckDevice = false;
- switch (CudaTarget) {
- case CFT_HostDevice:
- CheckHost = true;
- CheckDevice = true;
- break;
- case CFT_Host:
- CheckHost = true;
- break;
- case CFT_Device:
- case CFT_Global:
- CheckDevice = true;
- break;
- case CFT_InvalidTarget:
- llvm_unreachable("unexpected cuda target");
- }
- auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI;
- auto *DeviceTI = LangOpts.CUDAIsDevice ? &TI : Aux;
- if (CheckHost && HostTI)
- A = HostTI->checkCallingConvention(CC);
- if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
- A = DeviceTI->checkCallingConvention(CC);
- } else {
- A = TI.checkCallingConvention(CC);
- }
- if (A != TargetInfo::CCCR_OK) {
- if (A == TargetInfo::CCCR_Warning)
- Diag(Attrs.getLoc(), diag::warn_cconv_ignored) << Attrs;
- // This convention is not valid for the target. Use the default function or
- // method calling convention.
- bool IsCXXMethod = false, IsVariadic = false;
- if (FD) {
- IsCXXMethod = FD->isCXXInstanceMember();
- IsVariadic = FD->isVariadic();
- }
- CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod);
- }
- Attrs.setProcessingCache((unsigned) CC);
- return false;
- }
- /// Pointer-like types in the default address space.
- static bool isValidSwiftContextType(QualType Ty) {
- if (!Ty->hasPointerRepresentation())
- return Ty->isDependentType();
- return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
- }
- /// Pointers and references in the default address space.
- static bool isValidSwiftIndirectResultType(QualType Ty) {
- if (const auto *PtrType = Ty->getAs<PointerType>()) {
- Ty = PtrType->getPointeeType();
- } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
- Ty = RefType->getPointeeType();
- } else {
- return Ty->isDependentType();
- }
- return Ty.getAddressSpace() == LangAS::Default;
- }
- /// Pointers and references to pointers in the default address space.
- static bool isValidSwiftErrorResultType(QualType Ty) {
- if (const auto *PtrType = Ty->getAs<PointerType>()) {
- Ty = PtrType->getPointeeType();
- } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
- Ty = RefType->getPointeeType();
- } else {
- return Ty->isDependentType();
- }
- if (!Ty.getQualifiers().empty())
- return false;
- return isValidSwiftContextType(Ty);
- }
- static void handleParameterABIAttr(Sema &S, Decl *D, const ParsedAttr &Attrs,
- ParameterABI Abi) {
- S.AddParameterABIAttr(Attrs.getRange(), D, Abi,
- Attrs.getAttributeSpellingListIndex());
- }
- void Sema::AddParameterABIAttr(SourceRange range, Decl *D, ParameterABI abi,
- unsigned spellingIndex) {
- QualType type = cast<ParmVarDecl>(D)->getType();
- if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
- if (existingAttr->getABI() != abi) {
- Diag(range.getBegin(), diag::err_attributes_are_not_compatible)
- << getParameterABISpelling(abi) << existingAttr;
- Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
- return;
- }
- }
- switch (abi) {
- case ParameterABI::Ordinary:
- llvm_unreachable("explicit attribute for ordinary parameter ABI?");
- case ParameterABI::SwiftContext:
- if (!isValidSwiftContextType(type)) {
- Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type)
- << getParameterABISpelling(abi)
- << /*pointer to pointer */ 0 << type;
- }
- D->addAttr(::new (Context)
- SwiftContextAttr(range, Context, spellingIndex));
- return;
- case ParameterABI::SwiftErrorResult:
- if (!isValidSwiftErrorResultType(type)) {
- Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type)
- << getParameterABISpelling(abi)
- << /*pointer to pointer */ 1 << type;
- }
- D->addAttr(::new (Context)
- SwiftErrorResultAttr(range, Context, spellingIndex));
- return;
- case ParameterABI::SwiftIndirectResult:
- if (!isValidSwiftIndirectResultType(type)) {
- Diag(range.getBegin(), diag::err_swift_abi_parameter_wrong_type)
- << getParameterABISpelling(abi)
- << /*pointer*/ 0 << type;
- }
- D->addAttr(::new (Context)
- SwiftIndirectResultAttr(range, Context, spellingIndex));
- return;
- }
- llvm_unreachable("bad parameter ABI attribute");
- }
- /// Checks a regparm attribute, returning true if it is ill-formed and
- /// otherwise setting numParams to the appropriate value.
- bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) {
- if (AL.isInvalid())
- return true;
- if (!checkAttributeNumArgs(*this, AL, 1)) {
- AL.setInvalid();
- return true;
- }
- uint32_t NP;
- Expr *NumParamsExpr = AL.getArgAsExpr(0);
- if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) {
- AL.setInvalid();
- return true;
- }
- if (Context.getTargetInfo().getRegParmMax() == 0) {
- Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform)
- << NumParamsExpr->getSourceRange();
- AL.setInvalid();
- return true;
- }
- numParams = NP;
- if (numParams > Context.getTargetInfo().getRegParmMax()) {
- Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number)
- << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
- AL.setInvalid();
- return true;
- }
- return false;
- }
- // Checks whether an argument of launch_bounds attribute is
- // acceptable, performs implicit conversion to Rvalue, and returns
- // non-nullptr Expr result on success. Otherwise, it returns nullptr
- // and may output an error.
- static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
- const CUDALaunchBoundsAttr &AL,
- const unsigned Idx) {
- if (S.DiagnoseUnexpandedParameterPack(E))
- return nullptr;
- // Accept template arguments for now as they depend on something else.
- // We'll get to check them when they eventually get instantiated.
- if (E->isValueDependent())
- return E;
- llvm::APSInt I(64);
- if (!E->isIntegerConstantExpr(I, S.Context)) {
- S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
- << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
- return nullptr;
- }
- // Make sure we can fit it in 32 bits.
- if (!I.isIntN(32)) {
- S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false)
- << 32 << /* Unsigned */ 1;
- return nullptr;
- }
- if (I < 0)
- S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
- << &AL << Idx << E->getSourceRange();
- // We may need to perform implicit conversion of the argument.
- InitializedEntity Entity = InitializedEntity::InitializeParameter(
- S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false);
- ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E);
- assert(!ValArg.isInvalid() &&
- "Unexpected PerformCopyInitialization() failure.");
- return ValArg.getAs<Expr>();
- }
- void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
- Expr *MinBlocks, unsigned SpellingListIndex) {
- CUDALaunchBoundsAttr TmpAttr(AttrRange, Context, MaxThreads, MinBlocks,
- SpellingListIndex);
- MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0);
- if (MaxThreads == nullptr)
- return;
- if (MinBlocks) {
- MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1);
- if (MinBlocks == nullptr)
- return;
- }
- D->addAttr(::new (Context) CUDALaunchBoundsAttr(
- AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex));
- }
- static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
- !checkAttributeAtMostNumArgs(S, AL, 2))
- return;
- S.AddLaunchBoundsAttr(AL.getRange(), D, AL.getArgAsExpr(0),
- AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr,
- AL.getAttributeSpellingListIndex());
- }
- static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier;
- return;
- }
- ParamIdx ArgumentIdx;
- if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1),
- ArgumentIdx))
- return;
- ParamIdx TypeTagIdx;
- if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2),
- TypeTagIdx))
- return;
- bool IsPointer = AL.getName()->getName() == "pointer_with_type_tag";
- if (IsPointer) {
- // Ensure that buffer has a pointer type.
- unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();
- if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) ||
- !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType())
- S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0;
- }
- D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
- AL.getRange(), S.Context, AL.getArgAsIdent(0)->Ident, ArgumentIdx,
- TypeTagIdx, IsPointer, AL.getAttributeSpellingListIndex()));
- }
- static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (!AL.isArgIdent(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
- << AL << 1 << AANT_ArgumentIdentifier;
- return;
- }
- if (!checkAttributeNumArgs(S, AL, 1))
- return;
- if (!isa<VarDecl>(D)) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedVariable;
- return;
- }
- IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident;
- TypeSourceInfo *MatchingCTypeLoc = nullptr;
- S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc);
- assert(MatchingCTypeLoc && "no type source info for attribute argument");
- D->addAttr(::new (S.Context)
- TypeTagForDatatypeAttr(AL.getRange(), S.Context, PointerKind,
- MatchingCTypeLoc,
- AL.getLayoutCompatible(),
- AL.getMustBeNull(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- ParamIdx ArgCount;
- if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0),
- ArgCount,
- true /* CanIndexImplicitThis */))
- return;
- // ArgCount isn't a parameter index [0;n), it's a count [1;n]
- D->addAttr(::new (S.Context) XRayLogArgsAttr(
- AL.getRange(), S.Context, ArgCount.getSourceIndex(),
- AL.getAttributeSpellingListIndex()));
- }
- //===----------------------------------------------------------------------===//
- // Checker-specific attribute handlers.
- //===----------------------------------------------------------------------===//
- static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
- return QT->isDependentType() || QT->isObjCRetainableType();
- }
- static bool isValidSubjectOfNSAttribute(QualType QT) {
- return QT->isDependentType() || QT->isObjCObjectPointerType() ||
- QT->isObjCNSObjectType();
- }
- static bool isValidSubjectOfCFAttribute(QualType QT) {
- return QT->isDependentType() || QT->isPointerType() ||
- isValidSubjectOfNSAttribute(QT);
- }
- static bool isValidSubjectOfOSAttribute(QualType QT) {
- if (QT->isDependentType())
- return true;
- QualType PT = QT->getPointeeType();
- return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;
- }
- void Sema::AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex,
- RetainOwnershipKind K,
- bool IsTemplateInstantiation) {
- ValueDecl *VD = cast<ValueDecl>(D);
- switch (K) {
- case RetainOwnershipKind::OS:
- handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
- *this, VD, SR, SpellingIndex, isValidSubjectOfOSAttribute(VD->getType()),
- diag::warn_ns_attribute_wrong_parameter_type,
- /*ExtraArgs=*/SR, "os_consumed", /*pointers*/ 1);
- return;
- case RetainOwnershipKind::NS:
- handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
- *this, VD, SR, SpellingIndex, isValidSubjectOfNSAttribute(VD->getType()),
- // These attributes are normally just advisory, but in ARC, ns_consumed
- // is significant. Allow non-dependent code to contain inappropriate
- // attributes even in ARC, but require template instantiations to be
- // set up correctly.
- ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)
- ? diag::err_ns_attribute_wrong_parameter_type
- : diag::warn_ns_attribute_wrong_parameter_type),
- /*ExtraArgs=*/SR, "ns_consumed", /*objc pointers*/ 0);
- return;
- case RetainOwnershipKind::CF:
- handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
- *this, VD, SR, SpellingIndex,
- isValidSubjectOfCFAttribute(VD->getType()),
- diag::warn_ns_attribute_wrong_parameter_type,
- /*ExtraArgs=*/SR, "cf_consumed", /*pointers*/1);
- return;
- }
- }
- static Sema::RetainOwnershipKind
- parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
- switch (AL.getKind()) {
- case ParsedAttr::AT_CFConsumed:
- case ParsedAttr::AT_CFReturnsRetained:
- case ParsedAttr::AT_CFReturnsNotRetained:
- return Sema::RetainOwnershipKind::CF;
- case ParsedAttr::AT_OSConsumesThis:
- case ParsedAttr::AT_OSConsumed:
- case ParsedAttr::AT_OSReturnsRetained:
- case ParsedAttr::AT_OSReturnsNotRetained:
- case ParsedAttr::AT_OSReturnsRetainedOnZero:
- case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
- return Sema::RetainOwnershipKind::OS;
- case ParsedAttr::AT_NSConsumesSelf:
- case ParsedAttr::AT_NSConsumed:
- case ParsedAttr::AT_NSReturnsRetained:
- case ParsedAttr::AT_NSReturnsNotRetained:
- case ParsedAttr::AT_NSReturnsAutoreleased:
- return Sema::RetainOwnershipKind::NS;
- default:
- llvm_unreachable("Wrong argument supplied");
- }
- }
- bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
- if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
- return false;
- Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
- << "'ns_returns_retained'" << 0 << 0;
- return true;
- }
- /// \return whether the parameter is a pointer to OSObject pointer.
- static bool isValidOSObjectOutParameter(const Decl *D) {
- const auto *PVD = dyn_cast<ParmVarDecl>(D);
- if (!PVD)
- return false;
- QualType QT = PVD->getType();
- QualType PT = QT->getPointeeType();
- return !PT.isNull() && isValidSubjectOfOSAttribute(PT);
- }
- static void handleXReturnsXRetainedAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- QualType ReturnType;
- Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
- ReturnType = MD->getReturnType();
- } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
- (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {
- return; // ignore: was handled as a type attribute
- } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
- ReturnType = PD->getType();
- } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- ReturnType = FD->getReturnType();
- } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
- // Attributes on parameters are used for out-parameters,
- // passed as pointers-to-pointers.
- unsigned DiagID = K == Sema::RetainOwnershipKind::CF
- ? /*pointer-to-CF-pointer*/2
- : /*pointer-to-OSObject-pointer*/3;
- ReturnType = Param->getType()->getPointeeType();
- if (ReturnType.isNull()) {
- S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
- << AL << DiagID << AL.getRange();
- return;
- }
- } else if (AL.isUsedAsTypeAttr()) {
- return;
- } else {
- AttributeDeclKind ExpectedDeclKind;
- switch (AL.getKind()) {
- default: llvm_unreachable("invalid ownership attribute");
- case ParsedAttr::AT_NSReturnsRetained:
- case ParsedAttr::AT_NSReturnsAutoreleased:
- case ParsedAttr::AT_NSReturnsNotRetained:
- ExpectedDeclKind = ExpectedFunctionOrMethod;
- break;
- case ParsedAttr::AT_OSReturnsRetained:
- case ParsedAttr::AT_OSReturnsNotRetained:
- case ParsedAttr::AT_CFReturnsRetained:
- case ParsedAttr::AT_CFReturnsNotRetained:
- ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
- break;
- }
- S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
- << AL.getRange() << AL << ExpectedDeclKind;
- return;
- }
- bool TypeOK;
- bool Cf;
- unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
- switch (AL.getKind()) {
- default: llvm_unreachable("invalid ownership attribute");
- case ParsedAttr::AT_NSReturnsRetained:
- TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
- Cf = false;
- break;
- case ParsedAttr::AT_NSReturnsAutoreleased:
- case ParsedAttr::AT_NSReturnsNotRetained:
- TypeOK = isValidSubjectOfNSAttribute(ReturnType);
- Cf = false;
- break;
- case ParsedAttr::AT_CFReturnsRetained:
- case ParsedAttr::AT_CFReturnsNotRetained:
- TypeOK = isValidSubjectOfCFAttribute(ReturnType);
- Cf = true;
- break;
- case ParsedAttr::AT_OSReturnsRetained:
- case ParsedAttr::AT_OSReturnsNotRetained:
- TypeOK = isValidSubjectOfOSAttribute(ReturnType);
- Cf = true;
- ParmDiagID = 3; // Pointer-to-OSObject-pointer
- break;
- }
- if (!TypeOK) {
- if (AL.isUsedAsTypeAttr())
- return;
- if (isa<ParmVarDecl>(D)) {
- S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
- << AL << ParmDiagID << AL.getRange();
- } else {
- // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
- enum : unsigned {
- Function,
- Method,
- Property
- } SubjectKind = Function;
- if (isa<ObjCMethodDecl>(D))
- SubjectKind = Method;
- else if (isa<ObjCPropertyDecl>(D))
- SubjectKind = Property;
- S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
- << AL << SubjectKind << Cf << AL.getRange();
- }
- return;
- }
- switch (AL.getKind()) {
- default:
- llvm_unreachable("invalid ownership attribute");
- case ParsedAttr::AT_NSReturnsAutoreleased:
- handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL);
- return;
- case ParsedAttr::AT_CFReturnsNotRetained:
- handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL);
- return;
- case ParsedAttr::AT_NSReturnsNotRetained:
- handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL);
- return;
- case ParsedAttr::AT_CFReturnsRetained:
- handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL);
- return;
- case ParsedAttr::AT_NSReturnsRetained:
- handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL);
- return;
- case ParsedAttr::AT_OSReturnsRetained:
- handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL);
- return;
- case ParsedAttr::AT_OSReturnsNotRetained:
- handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL);
- return;
- };
- }
- static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
- const ParsedAttr &Attrs) {
- const int EP_ObjCMethod = 1;
- const int EP_ObjCProperty = 2;
- SourceLocation loc = Attrs.getLoc();
- QualType resultType;
- if (isa<ObjCMethodDecl>(D))
- resultType = cast<ObjCMethodDecl>(D)->getReturnType();
- else
- resultType = cast<ObjCPropertyDecl>(D)->getType();
- if (!resultType->isReferenceType() &&
- (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
- S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
- << SourceRange(loc) << Attrs
- << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
- << /*non-retainable pointer*/ 2;
- // Drop the attribute.
- return;
- }
- D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(
- Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
- }
- static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
- const ParsedAttr &Attrs) {
- const auto *Method = cast<ObjCMethodDecl>(D);
- const DeclContext *DC = Method->getDeclContext();
- if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
- S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
- << 0;
- S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
- return;
- }
- if (Method->getMethodFamily() == OMF_dealloc) {
- S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
- << 1;
- return;
- }
- D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(
- Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex()));
- }
- static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
- if (!Parm) {
- S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
- return;
- }
- // Typedefs only allow objc_bridge(id) and have some additional checking.
- if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
- if (!Parm->Ident->isStr("id")) {
- S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;
- return;
- }
- // Only allow 'cv void *'.
- QualType T = TD->getUnderlyingType();
- if (!T->isVoidPointerType()) {
- S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
- return;
- }
- }
- D->addAttr(::new (S.Context)
- ObjCBridgeAttr(AL.getRange(), S.Context, Parm->Ident,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCBridgeMutableAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
- if (!Parm) {
- S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
- return;
- }
- D->addAttr(::new (S.Context)
- ObjCBridgeMutableAttr(AL.getRange(), S.Context, Parm->Ident,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- IdentifierInfo *RelatedClass =
- AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
- if (!RelatedClass) {
- S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
- return;
- }
- IdentifierInfo *ClassMethod =
- AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
- IdentifierInfo *InstanceMethod =
- AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
- D->addAttr(::new (S.Context)
- ObjCBridgeRelatedAttr(AL.getRange(), S.Context, RelatedClass,
- ClassMethod, InstanceMethod,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- DeclContext *Ctx = D->getDeclContext();
- // This attribute can only be applied to methods in interfaces or class
- // extensions.
- if (!isa<ObjCInterfaceDecl>(Ctx) &&
- !(isa<ObjCCategoryDecl>(Ctx) &&
- cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
- S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
- return;
- }
- ObjCInterfaceDecl *IFace;
- if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
- IFace = CatDecl->getClassInterface();
- else
- IFace = cast<ObjCInterfaceDecl>(Ctx);
- if (!IFace)
- return;
- IFace->setHasDesignatedInitializers();
- D->addAttr(::new (S.Context)
- ObjCDesignatedInitializerAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef MetaDataName;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
- return;
- D->addAttr(::new (S.Context)
- ObjCRuntimeNameAttr(AL.getRange(), S.Context,
- MetaDataName,
- AL.getAttributeSpellingListIndex()));
- }
- // When a user wants to use objc_boxable with a union or struct
- // but they don't have access to the declaration (legacy/third-party code)
- // then they can 'enable' this feature with a typedef:
- // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
- static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) {
- bool notify = false;
- auto *RD = dyn_cast<RecordDecl>(D);
- if (RD && RD->getDefinition()) {
- RD = RD->getDefinition();
- notify = true;
- }
- if (RD) {
- ObjCBoxableAttr *BoxableAttr = ::new (S.Context)
- ObjCBoxableAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex());
- RD->addAttr(BoxableAttr);
- if (notify) {
- // we need to notify ASTReader/ASTWriter about
- // modification of existing declaration
- if (ASTMutationListener *L = S.getASTMutationListener())
- L->AddedAttributeToRecord(BoxableAttr, RD);
- }
- }
- }
- static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (hasDeclarator(D)) return;
- S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
- << AL.getRange() << AL << ExpectedVariable;
- }
- static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- const auto *VD = cast<ValueDecl>(D);
- QualType QT = VD->getType();
- if (!QT->isDependentType() &&
- !QT->isObjCLifetimeType()) {
- S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type)
- << QT;
- return;
- }
- Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();
- // If we have no lifetime yet, check the lifetime we're presumably
- // going to infer.
- if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
- Lifetime = QT->getObjCARCImplicitLifetime();
- switch (Lifetime) {
- case Qualifiers::OCL_None:
- assert(QT->isDependentType() &&
- "didn't infer lifetime for non-dependent type?");
- break;
- case Qualifiers::OCL_Weak: // meaningful
- case Qualifiers::OCL_Strong: // meaningful
- break;
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
- << (Lifetime == Qualifiers::OCL_Autoreleasing);
- break;
- }
- D->addAttr(::new (S.Context)
- ObjCPreciseLifetimeAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- //===----------------------------------------------------------------------===//
- // Microsoft specific attribute handlers.
- //===----------------------------------------------------------------------===//
- UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex, StringRef Uuid) {
- if (const auto *UA = D->getAttr<UuidAttr>()) {
- if (UA->getGuid().equals_lower(Uuid))
- return nullptr;
- Diag(UA->getLocation(), diag::err_mismatched_uuid);
- Diag(Range.getBegin(), diag::note_previous_uuid);
- D->dropAttr<UuidAttr>();
- }
- return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex);
- }
- static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!S.LangOpts.CPlusPlus) {
- S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
- << AL << AttributeLangSupport::C;
- return;
- }
- StringRef StrRef;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, StrRef, &LiteralLoc))
- return;
- // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
- // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former.
- if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}')
- StrRef = StrRef.drop_front().drop_back();
- // Validate GUID length.
- if (StrRef.size() != 36) {
- S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
- return;
- }
- for (unsigned i = 0; i < 36; ++i) {
- if (i == 8 || i == 13 || i == 18 || i == 23) {
- if (StrRef[i] != '-') {
- S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
- return;
- }
- } else if (!isHexDigit(StrRef[i])) {
- S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
- return;
- }
- }
- // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's
- // the only thing in the [] list, the [] too), and add an insertion of
- // __declspec(uuid(...)). But sadly, neither the SourceLocs of the commas
- // separating attributes nor of the [ and the ] are in the AST.
- // Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc"
- // on cfe-dev.
- if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
- S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated);
- UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(),
- AL.getAttributeSpellingListIndex(), StrRef);
- if (UA)
- D->addAttr(UA);
- }
- static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!S.LangOpts.CPlusPlus) {
- S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
- << AL << AttributeLangSupport::C;
- return;
- }
- MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
- D, AL.getRange(), /*BestCase=*/true,
- AL.getAttributeSpellingListIndex(),
- (MSInheritanceAttr::Spelling)AL.getSemanticSpelling());
- if (IA) {
- D->addAttr(IA);
- S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D));
- }
- }
- static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- const auto *VD = cast<VarDecl>(D);
- if (!S.Context.getTargetInfo().isTLSSupported()) {
- S.Diag(AL.getLoc(), diag::err_thread_unsupported);
- return;
- }
- if (VD->getTSCSpec() != TSCS_unspecified) {
- S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable);
- return;
- }
- if (VD->hasLocalStorage()) {
- S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
- return;
- }
- D->addAttr(::new (S.Context) ThreadAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<StringRef, 4> Tags;
- for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
- StringRef Tag;
- if (!S.checkStringLiteralArgumentAttr(AL, I, Tag))
- return;
- Tags.push_back(Tag);
- }
- if (const auto *NS = dyn_cast<NamespaceDecl>(D)) {
- if (!NS->isInline()) {
- S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
- return;
- }
- if (NS->isAnonymousNamespace()) {
- S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
- return;
- }
- if (AL.getNumArgs() == 0)
- Tags.push_back(NS->getName());
- } else if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- // Store tags sorted and without duplicates.
- llvm::sort(Tags);
- Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
- D->addAttr(::new (S.Context)
- AbiTagAttr(AL.getRange(), S.Context, Tags.data(), Tags.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Check the attribute arguments.
- if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
- return;
- }
- StringRef Str;
- SourceLocation ArgLoc;
- if (AL.getNumArgs() == 0)
- Str = "";
- else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
- return;
- ARMInterruptAttr::InterruptType Kind;
- if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
- << ArgLoc;
- return;
- }
- unsigned Index = AL.getAttributeSpellingListIndex();
- D->addAttr(::new (S.Context)
- ARMInterruptAttr(AL.getLoc(), S.Context, Kind, Index));
- }
- static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // MSP430 'interrupt' attribute is applied to
- // a function with no parameters and void return type.
- if (!isFunctionOrMethod(D)) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunctionOrMethod;
- return;
- }
- if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
- S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
- << /*MSP430*/ 1 << 0;
- return;
- }
- if (!getFunctionOrMethodResultType(D)->isVoidType()) {
- S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
- << /*MSP430*/ 1 << 1;
- return;
- }
- // The attribute takes one integer argument.
- if (!checkAttributeNumArgs(S, AL, 1))
- return;
- if (!AL.isArgExpr(0)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIntegerConstant;
- return;
- }
- Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
- llvm::APSInt NumParams(32);
- if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIntegerConstant
- << NumParamsExpr->getSourceRange();
- return;
- }
- // The argument should be in range 0..63.
- unsigned Num = NumParams.getLimitedValue(255);
- if (Num > 63) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << (int)NumParams.getSExtValue()
- << NumParamsExpr->getSourceRange();
- return;
- }
- D->addAttr(::new (S.Context)
- MSP430InterruptAttr(AL.getLoc(), S.Context, Num,
- AL.getAttributeSpellingListIndex()));
- D->addAttr(UsedAttr::CreateImplicit(S.Context));
- }
- static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Only one optional argument permitted.
- if (AL.getNumArgs() > 1) {
- S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
- return;
- }
- StringRef Str;
- SourceLocation ArgLoc;
- if (AL.getNumArgs() == 0)
- Str = "";
- else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
- return;
- // Semantic checks for a function with the 'interrupt' attribute for MIPS:
- // a) Must be a function.
- // b) Must have no parameters.
- // c) Must have the 'void' return type.
- // d) Cannot have the 'mips16' attribute, as that instruction set
- // lacks the 'eret' instruction.
- // e) The attribute itself must either have no argument or one of the
- // valid interrupt types, see [MipsInterruptDocs].
- if (!isFunctionOrMethod(D)) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunctionOrMethod;
- return;
- }
- if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
- S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
- << /*MIPS*/ 0 << 0;
- return;
- }
- if (!getFunctionOrMethodResultType(D)->isVoidType()) {
- S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
- << /*MIPS*/ 0 << 1;
- return;
- }
- if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL))
- return;
- MipsInterruptAttr::InterruptType Kind;
- if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
- << AL << "'" + std::string(Str) + "'";
- return;
- }
- D->addAttr(::new (S.Context) MipsInterruptAttr(
- AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
- }
- static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Semantic checks for a function with the 'interrupt' attribute.
- // a) Must be a function.
- // b) Must have the 'void' return type.
- // c) Must take 1 or 2 arguments.
- // d) The 1st argument must be a pointer.
- // e) The 2nd argument (if any) must be an unsigned integer.
- if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) ||
- CXXMethodDecl::isStaticOverloadedOperator(
- cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunctionWithProtoType;
- return;
- }
- // Interrupt handler must have void return type.
- if (!getFunctionOrMethodResultType(D)->isVoidType()) {
- S.Diag(getFunctionOrMethodResultSourceRange(D).getBegin(),
- diag::err_anyx86_interrupt_attribute)
- << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
- ? 0
- : 1)
- << 0;
- return;
- }
- // Interrupt handler must have 1 or 2 parameters.
- unsigned NumParams = getFunctionOrMethodNumParams(D);
- if (NumParams < 1 || NumParams > 2) {
- S.Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute)
- << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
- ? 0
- : 1)
- << 1;
- return;
- }
- // The first argument must be a pointer.
- if (!getFunctionOrMethodParamType(D, 0)->isPointerType()) {
- S.Diag(getFunctionOrMethodParamRange(D, 0).getBegin(),
- diag::err_anyx86_interrupt_attribute)
- << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
- ? 0
- : 1)
- << 2;
- return;
- }
- // The second argument, if present, must be an unsigned integer.
- unsigned TypeSize =
- S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64
- ? 64
- : 32;
- if (NumParams == 2 &&
- (!getFunctionOrMethodParamType(D, 1)->isUnsignedIntegerType() ||
- S.Context.getTypeSize(getFunctionOrMethodParamType(D, 1)) != TypeSize)) {
- S.Diag(getFunctionOrMethodParamRange(D, 1).getBegin(),
- diag::err_anyx86_interrupt_attribute)
- << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
- ? 0
- : 1)
- << 3 << S.Context.getIntTypeForBitwidth(TypeSize, /*Signed=*/false);
- return;
- }
- D->addAttr(::new (S.Context) AnyX86InterruptAttr(
- AL.getLoc(), S.Context, AL.getAttributeSpellingListIndex()));
- D->addAttr(UsedAttr::CreateImplicit(S.Context));
- }
- static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!isFunctionOrMethod(D)) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunction;
- return;
- }
- if (!checkAttributeNumArgs(S, AL, 0))
- return;
- handleSimpleAttribute<AVRInterruptAttr>(S, D, AL);
- }
- static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!isFunctionOrMethod(D)) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'signal'" << ExpectedFunction;
- return;
- }
- if (!checkAttributeNumArgs(S, AL, 0))
- return;
- handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
- }
- static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!isFunctionOrMethod(D)) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'import_module'" << ExpectedFunction;
- return;
- }
- auto *FD = cast<FunctionDecl>(D);
- if (FD->isThisDeclarationADefinition()) {
- S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
- return;
- }
- StringRef Str;
- SourceLocation ArgLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
- return;
- FD->addAttr(::new (S.Context) WebAssemblyImportModuleAttr(
- AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!isFunctionOrMethod(D)) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'import_name'" << ExpectedFunction;
- return;
- }
- auto *FD = cast<FunctionDecl>(D);
- if (FD->isThisDeclarationADefinition()) {
- S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
- return;
- }
- StringRef Str;
- SourceLocation ArgLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
- return;
- FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(
- AL.getRange(), S.Context, Str,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleRISCVInterruptAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- // Warn about repeated attributes.
- if (const auto *A = D->getAttr<RISCVInterruptAttr>()) {
- S.Diag(AL.getRange().getBegin(),
- diag::warn_riscv_repeated_interrupt_attribute);
- S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
- return;
- }
- // Check the attribute argument. Argument is optional.
- if (!checkAttributeAtMostNumArgs(S, AL, 1))
- return;
- StringRef Str;
- SourceLocation ArgLoc;
- // 'machine'is the default interrupt mode.
- if (AL.getNumArgs() == 0)
- Str = "machine";
- else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
- return;
- // Semantic checks for a function with the 'interrupt' attribute:
- // - Must be a function.
- // - Must have no parameters.
- // - Must have the 'void' return type.
- // - The attribute itself must either have no argument or one of the
- // valid interrupt types, see [RISCVInterruptDocs].
- if (D->getFunctionType() == nullptr) {
- S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
- << "'interrupt'" << ExpectedFunction;
- return;
- }
- if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
- S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
- << /*RISC-V*/ 2 << 0;
- return;
- }
- if (!getFunctionOrMethodResultType(D)->isVoidType()) {
- S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
- << /*RISC-V*/ 2 << 1;
- return;
- }
- RISCVInterruptAttr::InterruptType Kind;
- if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
- << ArgLoc;
- return;
- }
- D->addAttr(::new (S.Context) RISCVInterruptAttr(
- AL.getLoc(), S.Context, Kind, AL.getAttributeSpellingListIndex()));
- }
- static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Dispatch the interrupt attribute based on the current target.
- switch (S.Context.getTargetInfo().getTriple().getArch()) {
- case llvm::Triple::msp430:
- handleMSP430InterruptAttr(S, D, AL);
- break;
- case llvm::Triple::mipsel:
- case llvm::Triple::mips:
- handleMipsInterruptAttr(S, D, AL);
- break;
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- handleAnyX86InterruptAttr(S, D, AL);
- break;
- case llvm::Triple::avr:
- handleAVRInterruptAttr(S, D, AL);
- break;
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- handleRISCVInterruptAttr(S, D, AL);
- break;
- default:
- handleARMInterruptAttr(S, D, AL);
- break;
- }
- }
- static bool
- checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr,
- const AMDGPUFlatWorkGroupSizeAttr &Attr) {
- // Accept template arguments for now as they depend on something else.
- // We'll get to check them when they eventually get instantiated.
- if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
- return false;
- uint32_t Min = 0;
- if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
- return true;
- uint32_t Max = 0;
- if (!checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
- return true;
- if (Min == 0 && Max != 0) {
- S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
- << &Attr << 0;
- return true;
- }
- if (Min > Max) {
- S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
- << &Attr << 1;
- return true;
- }
- return false;
- }
- void Sema::addAMDGPUFlatWorkGroupSizeAttr(SourceRange AttrRange, Decl *D,
- Expr *MinExpr, Expr *MaxExpr,
- unsigned SpellingListIndex) {
- AMDGPUFlatWorkGroupSizeAttr TmpAttr(AttrRange, Context, MinExpr, MaxExpr,
- SpellingListIndex);
- if (checkAMDGPUFlatWorkGroupSizeArguments(*this, MinExpr, MaxExpr, TmpAttr))
- return;
- D->addAttr(::new (Context) AMDGPUFlatWorkGroupSizeAttr(
- AttrRange, Context, MinExpr, MaxExpr, SpellingListIndex));
- }
- static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- Expr *MinExpr = AL.getArgAsExpr(0);
- Expr *MaxExpr = AL.getArgAsExpr(1);
- S.addAMDGPUFlatWorkGroupSizeAttr(AL.getRange(), D, MinExpr, MaxExpr,
- AL.getAttributeSpellingListIndex());
- }
- static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
- Expr *MaxExpr,
- const AMDGPUWavesPerEUAttr &Attr) {
- if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
- (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
- return true;
- // Accept template arguments for now as they depend on something else.
- // We'll get to check them when they eventually get instantiated.
- if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
- return false;
- uint32_t Min = 0;
- if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
- return true;
- uint32_t Max = 0;
- if (MaxExpr && !checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
- return true;
- if (Min == 0 && Max != 0) {
- S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
- << &Attr << 0;
- return true;
- }
- if (Max != 0 && Min > Max) {
- S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
- << &Attr << 1;
- return true;
- }
- return false;
- }
- void Sema::addAMDGPUWavesPerEUAttr(SourceRange AttrRange, Decl *D,
- Expr *MinExpr, Expr *MaxExpr,
- unsigned SpellingListIndex) {
- AMDGPUWavesPerEUAttr TmpAttr(AttrRange, Context, MinExpr, MaxExpr,
- SpellingListIndex);
- if (checkAMDGPUWavesPerEUArguments(*this, MinExpr, MaxExpr, TmpAttr))
- return;
- D->addAttr(::new (Context) AMDGPUWavesPerEUAttr(AttrRange, Context, MinExpr,
- MaxExpr, SpellingListIndex));
- }
- static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
- !checkAttributeAtMostNumArgs(S, AL, 2))
- return;
- Expr *MinExpr = AL.getArgAsExpr(0);
- Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
- S.addAMDGPUWavesPerEUAttr(AL.getRange(), D, MinExpr, MaxExpr,
- AL.getAttributeSpellingListIndex());
- }
- static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t NumSGPR = 0;
- Expr *NumSGPRExpr = AL.getArgAsExpr(0);
- if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR))
- return;
- D->addAttr(::new (S.Context)
- AMDGPUNumSGPRAttr(AL.getLoc(), S.Context, NumSGPR,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t NumVGPR = 0;
- Expr *NumVGPRExpr = AL.getArgAsExpr(0);
- if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR))
- return;
- D->addAttr(::new (S.Context)
- AMDGPUNumVGPRAttr(AL.getLoc(), S.Context, NumVGPR,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- // If we try to apply it to a function pointer, don't warn, but don't
- // do anything, either. It doesn't matter anyway, because there's nothing
- // special about calling a force_align_arg_pointer function.
- const auto *VD = dyn_cast<ValueDecl>(D);
- if (VD && VD->getType()->isFunctionPointerType())
- return;
- // Also don't warn on function pointer typedefs.
- const auto *TD = dyn_cast<TypedefNameDecl>(D);
- if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
- TD->getUnderlyingType()->isFunctionType()))
- return;
- // Attribute can only be applied to function types.
- if (!isa<FunctionDecl>(D)) {
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
- << AL << ExpectedFunction;
- return;
- }
- D->addAttr(::new (S.Context)
- X86ForceAlignArgPointerAttr(AL.getRange(), S.Context,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) {
- uint32_t Version;
- Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
- if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version))
- return;
- // TODO: Investigate what happens with the next major version of MSVC.
- if (Version != LangOptions::MSVC2015 / 100) {
- S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
- << AL << Version << VersionExpr->getSourceRange();
- return;
- }
- // The attribute expects a "major" version number like 19, but new versions of
- // MSVC have moved to updating the "minor", or less significant numbers, so we
- // have to multiply by 100 now.
- Version *= 100;
- D->addAttr(::new (S.Context)
- LayoutVersionAttr(AL.getRange(), S.Context, Version,
- AL.getAttributeSpellingListIndex()));
- }
- DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (D->hasAttr<DLLExportAttr>()) {
- Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'";
- return nullptr;
- }
- if (D->hasAttr<DLLImportAttr>())
- return nullptr;
- return ::new (Context) DLLImportAttr(Range, Context, AttrSpellingListIndex);
- }
- DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
- unsigned AttrSpellingListIndex) {
- if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
- Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
- D->dropAttr<DLLImportAttr>();
- }
- if (D->hasAttr<DLLExportAttr>())
- return nullptr;
- return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
- }
- static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
- if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
- S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A;
- return;
- }
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
- !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- // MinGW doesn't allow dllimport on inline functions.
- S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
- << A;
- return;
- }
- }
- if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- MD->getParent()->isLambda()) {
- S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A;
- return;
- }
- }
- unsigned Index = A.getAttributeSpellingListIndex();
- Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport
- ? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
- : (Attr *)S.mergeDLLImportAttr(D, A.getRange(), Index);
- if (NewAttr)
- D->addAttr(NewAttr);
- }
- MSInheritanceAttr *
- Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
- unsigned AttrSpellingListIndex,
- MSInheritanceAttr::Spelling SemanticSpelling) {
- if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
- if (IA->getSemanticSpelling() == SemanticSpelling)
- return nullptr;
- Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
- << 1 /*previous declaration*/;
- Diag(Range.getBegin(), diag::note_previous_ms_inheritance);
- D->dropAttr<MSInheritanceAttr>();
- }
- auto *RD = cast<CXXRecordDecl>(D);
- if (RD->hasDefinition()) {
- if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
- SemanticSpelling)) {
- return nullptr;
- }
- } else {
- if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
- Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
- << 1 /*partial specialization*/;
- return nullptr;
- }
- if (RD->getDescribedClassTemplate()) {
- Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
- << 0 /*primary template*/;
- return nullptr;
- }
- }
- return ::new (Context)
- MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
- }
- static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // The capability attributes take a single string parameter for the name of
- // the capability they represent. The lockable attribute does not take any
- // parameters. However, semantically, both attributes represent the same
- // concept, and so they use the same semantic attribute. Eventually, the
- // lockable attribute will be removed.
- //
- // For backward compatibility, any capability which has no specified string
- // literal will be considered a "mutex."
- StringRef N("mutex");
- SourceLocation LiteralLoc;
- if (AL.getKind() == ParsedAttr::AT_Capability &&
- !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc))
- return;
- // Currently, there are only two names allowed for a capability: role and
- // mutex (case insensitive). Diagnose other capability names.
- if (!N.equals_lower("mutex") && !N.equals_lower("role"))
- S.Diag(LiteralLoc, diag::warn_invalid_capability_name) << N;
- D->addAttr(::new (S.Context) CapabilityAttr(AL.getRange(), S.Context, N,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, AL, Args))
- return;
- D->addAttr(::new (S.Context) AssertCapabilityAttr(AL.getRange(), S.Context,
- Args.data(), Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, AL, Args))
- return;
- D->addAttr(::new (S.Context) AcquireCapabilityAttr(AL.getRange(),
- S.Context,
- Args.data(), Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, AL, Args))
- return;
- D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(AL.getRange(),
- S.Context,
- AL.getArgAsExpr(0),
- Args.data(),
- Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- // Check that all arguments are lockable objects.
- SmallVector<Expr *, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true);
- D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
- AL.getRange(), S.Context, Args.data(), Args.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- // check that all arguments are lockable objects
- SmallVector<Expr*, 1> Args;
- checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
- if (Args.empty())
- return;
- RequiresCapabilityAttr *RCA = ::new (S.Context)
- RequiresCapabilityAttr(AL.getRange(), S.Context, Args.data(),
- Args.size(), AL.getAttributeSpellingListIndex());
- D->addAttr(RCA);
- }
- static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) {
- if (NSD->isAnonymousNamespace()) {
- S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace);
- // Do not want to attach the attribute to the namespace because that will
- // cause confusing diagnostic reports for uses of declarations within the
- // namespace.
- return;
- }
- }
- // Handle the cases where the attribute has a text message.
- StringRef Str, Replacement;
- if (AL.isArgExpr(0) && AL.getArgAsExpr(0) &&
- !S.checkStringLiteralArgumentAttr(AL, 0, Str))
- return;
- // Only support a single optional message for Declspec and CXX11.
- if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
- checkAttributeAtMostNumArgs(S, AL, 1);
- else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
- !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
- return;
- if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope())
- S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
- D->addAttr(::new (S.Context)
- DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
- AL.getAttributeSpellingListIndex()));
- }
- static bool isGlobalVar(const Decl *D) {
- if (const auto *S = dyn_cast<VarDecl>(D))
- return S->hasGlobalStorage();
- return false;
- }
- static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
- return;
- std::vector<StringRef> Sanitizers;
- for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
- StringRef SanitizerName;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc))
- return;
- if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) ==
- SanitizerMask())
- S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
- else if (isGlobalVar(D) && SanitizerName != "address")
- S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedFunctionOrMethod;
- Sanitizers.push_back(SanitizerName);
- }
- D->addAttr(::new (S.Context) NoSanitizeAttr(
- AL.getRange(), S.Context, Sanitizers.data(), Sanitizers.size(),
- AL.getAttributeSpellingListIndex()));
- }
- static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- StringRef AttrName = AL.getName()->getName();
- normalizeName(AttrName);
- StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName)
- .Case("no_address_safety_analysis", "address")
- .Case("no_sanitize_address", "address")
- .Case("no_sanitize_thread", "thread")
- .Case("no_sanitize_memory", "memory");
- if (isGlobalVar(D) && SanitizerName != "address")
- S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << AL << ExpectedFunction;
- D->addAttr(::new (S.Context)
- NoSanitizeAttr(AL.getRange(), S.Context, &SanitizerName, 1,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL))
- D->addAttr(Internal);
- }
- static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (S.LangOpts.OpenCLVersion != 200)
- S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
- << AL << "2.0" << 0;
- else
- S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL
- << "2.0";
- }
- /// Handles semantic checking for features that are common to all attributes,
- /// such as checking whether a parameter was properly specified, or the correct
- /// number of arguments were passed, etc.
- static bool handleCommonAttributeFeatures(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- // Several attributes carry different semantics than the parsing requires, so
- // those are opted out of the common argument checks.
- //
- // We also bail on unknown and ignored attributes because those are handled
- // as part of the target-specific handling logic.
- if (AL.getKind() == ParsedAttr::UnknownAttribute)
- return false;
- // Check whether the attribute requires specific language extensions to be
- // enabled.
- if (!AL.diagnoseLangOpts(S))
- return true;
- // Check whether the attribute appertains to the given subject.
- if (!AL.diagnoseAppertainsTo(S, D))
- return true;
- if (AL.hasCustomParsing())
- return false;
- if (AL.getMinArgs() == AL.getMaxArgs()) {
- // If there are no optional arguments, then checking for the argument count
- // is trivial.
- if (!checkAttributeNumArgs(S, AL, AL.getMinArgs()))
- return true;
- } else {
- // There are optional arguments, so checking is slightly more involved.
- if (AL.getMinArgs() &&
- !checkAttributeAtLeastNumArgs(S, AL, AL.getMinArgs()))
- return true;
- else if (!AL.hasVariadicArg() && AL.getMaxArgs() &&
- !checkAttributeAtMostNumArgs(S, AL, AL.getMaxArgs()))
- return true;
- }
- if (S.CheckAttrTarget(AL))
- return true;
- return false;
- }
- static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (D->isInvalidDecl())
- return;
- // Check if there is only one access qualifier.
- if (D->hasAttr<OpenCLAccessAttr>()) {
- if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
- AL.getSemanticSpelling()) {
- S.Diag(AL.getLoc(), diag::warn_duplicate_declspec)
- << AL.getName()->getName() << AL.getRange();
- } else {
- S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
- << D->getSourceRange();
- D->setInvalidDecl(true);
- return;
- }
- }
- // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
- // image object can be read and written.
- // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
- // object. Using the read_write (or __read_write) qualifier with the pipe
- // qualifier is a compilation error.
- if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
- const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
- if (AL.getName()->getName().find("read_write") != StringRef::npos) {
- if ((!S.getLangOpts().OpenCLCPlusPlus &&
- S.getLangOpts().OpenCLVersion < 200) ||
- DeclTy->isPipeType()) {
- S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
- << AL << PDecl->getType() << DeclTy->isImageType();
- D->setInvalidDecl(true);
- return;
- }
- }
- }
- D->addAttr(::new (S.Context) OpenCLAccessAttr(
- AL.getRange(), S.Context, AL.getAttributeSpellingListIndex()));
- }
- static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) {
- if (!cast<VarDecl>(D)->hasGlobalStorage()) {
- S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var)
- << (A.getKind() == ParsedAttr::AT_AlwaysDestroy);
- return;
- }
- if (A.getKind() == ParsedAttr::AT_AlwaysDestroy)
- handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A);
- else
- handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A);
- }
- static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic &&
- "uninitialized is only valid on automatic duration variables");
- unsigned Index = AL.getAttributeSpellingListIndex();
- D->addAttr(::new (S.Context)
- UninitializedAttr(AL.getLoc(), S.Context, Index));
- }
- static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
- bool DiagnoseFailure) {
- QualType Ty = VD->getType();
- if (!Ty->isObjCRetainableType()) {
- if (DiagnoseFailure) {
- S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
- << 0;
- }
- return false;
- }
- Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();
- // Sema::inferObjCARCLifetime must run after processing decl attributes
- // (because __block lowers to an attribute), so if the lifetime hasn't been
- // explicitly specified, infer it locally now.
- if (LifetimeQual == Qualifiers::OCL_None)
- LifetimeQual = Ty->getObjCARCImplicitLifetime();
- // The attributes only really makes sense for __strong variables; ignore any
- // attempts to annotate a parameter with any other lifetime qualifier.
- if (LifetimeQual != Qualifiers::OCL_Strong) {
- if (DiagnoseFailure) {
- S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
- << 1;
- }
- return false;
- }
- // Tampering with the type of a VarDecl here is a bit of a hack, but we need
- // to ensure that the variable is 'const' so that we can error on
- // modification, which can otherwise over-release.
- VD->setType(Ty.withConst());
- VD->setARCPseudoStrong(true);
- return true;
- }
- static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (auto *VD = dyn_cast<VarDecl>(D)) {
- assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");
- if (!VD->hasLocalStorage()) {
- S.Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
- << 0;
- return;
- }
- if (!tryMakeVariablePseudoStrong(S, VD, /*DiagnoseFailure=*/true))
- return;
- handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
- return;
- }
- // If D is a function-like declaration (method, block, or function), then we
- // make every parameter psuedo-strong.
- for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
- auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));
- QualType Ty = PVD->getType();
- // If a user wrote a parameter with __strong explicitly, then assume they
- // want "real" strong semantics for that parameter. This works because if
- // the parameter was written with __strong, then the strong qualifier will
- // be non-local.
- if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
- Qualifiers::OCL_Strong)
- continue;
- tryMakeVariablePseudoStrong(S, PVD, /*DiagnoseFailure=*/false);
- }
- handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
- }
- static void handleFortifyStdLib(Sema &S, Decl *D, const ParsedAttr &AL) {
- auto *FD = cast<FunctionDecl>(D);
- unsigned VariantID = Builtin::getFortifiedVariantFunction(FD->getBuiltinID());
- if (VariantID == 0) {
- S.Diag(D->getLocation(), diag::err_fortify_std_lib_bad_decl);
- return;
- }
- uint32_t BOSType, Flag;
- if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), BOSType, 0, true) ||
- !checkUInt32Argument(S, AL, AL.getArgAsExpr(1), Flag, 1, true))
- return;
- if (BOSType > 3) {
- S.Diag(AL.getArgAsExpr(0)->getBeginLoc(),
- diag::err_attribute_argument_out_of_range)
- << AL << 0 << 3;
- return;
- }
- D->addAttr(::new (S.getASTContext()) FortifyStdLibAttr(
- AL.getLoc(), S.getASTContext(), BOSType, Flag,
- AL.getAttributeSpellingListIndex()));
- }
- static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- // Check that the return type is a `typedef int kern_return_t` or a typedef
- // around it, because otherwise MIG convention checks make no sense.
- // BlockDecl doesn't store a return type, so it's annoying to check,
- // so let's skip it for now.
- if (!isa<BlockDecl>(D)) {
- QualType T = getFunctionOrMethodResultType(D);
- bool IsKernReturnT = false;
- while (const auto *TT = T->getAs<TypedefType>()) {
- IsKernReturnT = (TT->getDecl()->getName() == "kern_return_t");
- T = TT->desugar();
- }
- if (!IsKernReturnT || T.getCanonicalType() != S.getASTContext().IntTy) {
- S.Diag(D->getBeginLoc(),
- diag::warn_mig_server_routine_does_not_return_kern_return_t);
- return;
- }
- }
- handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL);
- }
- //===----------------------------------------------------------------------===//
- // Top Level Sema Entry Points
- //===----------------------------------------------------------------------===//
- /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
- /// the attribute applies to decls. If the attribute is a type attribute, just
- /// silently ignore it if a GNU attribute.
- static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
- const ParsedAttr &AL,
- bool IncludeCXX11Attributes) {
- if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
- return;
- // Ignore C++11 attributes on declarator chunks: they appertain to the type
- // instead.
- if (AL.isCXX11Attribute() && !IncludeCXX11Attributes)
- return;
- // Unknown attributes are automatically warned on. Target-specific attributes
- // which do not apply to the current target architecture are treated as
- // though they were unknown attributes.
- if (AL.getKind() == ParsedAttr::UnknownAttribute ||
- !AL.existsInTarget(S.Context.getTargetInfo())) {
- S.Diag(AL.getLoc(),
- AL.isDeclspecAttribute()
- ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
- : (unsigned)diag::warn_unknown_attribute_ignored)
- << AL;
- return;
- }
- if (handleCommonAttributeFeatures(S, D, AL))
- return;
- switch (AL.getKind()) {
- default:
- if (!AL.isStmtAttr()) {
- // Type attributes are handled elsewhere; silently move on.
- assert(AL.isTypeAttr() && "Non-type attribute not handled");
- break;
- }
- S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
- << AL << D->getLocation();
- break;
- case ParsedAttr::AT_Interrupt:
- handleInterruptAttr(S, D, AL);
- break;
- case ParsedAttr::AT_X86ForceAlignArgPointer:
- handleX86ForceAlignArgPointerAttr(S, D, AL);
- break;
- case ParsedAttr::AT_DLLExport:
- case ParsedAttr::AT_DLLImport:
- handleDLLAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Mips16:
- handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr,
- MipsInterruptAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoMips16:
- handleSimpleAttribute<NoMips16Attr>(S, D, AL);
- break;
- case ParsedAttr::AT_MicroMips:
- handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoMicroMips:
- handleSimpleAttribute<NoMicroMipsAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MipsLongCall:
- handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
- S, D, AL);
- break;
- case ParsedAttr::AT_MipsShortCall:
- handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>(
- S, D, AL);
- break;
- case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
- handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AMDGPUWavesPerEU:
- handleAMDGPUWavesPerEUAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AMDGPUNumSGPR:
- handleAMDGPUNumSGPRAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AMDGPUNumVGPR:
- handleAMDGPUNumVGPRAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AVRSignal:
- handleAVRSignalAttr(S, D, AL);
- break;
- case ParsedAttr::AT_WebAssemblyImportModule:
- handleWebAssemblyImportModuleAttr(S, D, AL);
- break;
- case ParsedAttr::AT_WebAssemblyImportName:
- handleWebAssemblyImportNameAttr(S, D, AL);
- break;
- case ParsedAttr::AT_IBAction:
- handleSimpleAttribute<IBActionAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_IBOutlet:
- handleIBOutlet(S, D, AL);
- break;
- case ParsedAttr::AT_IBOutletCollection:
- handleIBOutletCollection(S, D, AL);
- break;
- case ParsedAttr::AT_IFunc:
- handleIFuncAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Alias:
- handleAliasAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Aligned:
- handleAlignedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AlignValue:
- handleAlignValueAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AllocSize:
- handleAllocSizeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AlwaysInline:
- handleAlwaysInlineAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Artificial:
- handleSimpleAttribute<ArtificialAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_AnalyzerNoReturn:
- handleAnalyzerNoReturnAttr(S, D, AL);
- break;
- case ParsedAttr::AT_TLSModel:
- handleTLSModelAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Annotate:
- handleAnnotateAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Availability:
- handleAvailabilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_CarriesDependency:
- handleDependencyAttr(S, scope, D, AL);
- break;
- case ParsedAttr::AT_CPUDispatch:
- case ParsedAttr::AT_CPUSpecific:
- handleCPUSpecificAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Common:
- handleCommonAttr(S, D, AL);
- break;
- case ParsedAttr::AT_CUDAConstant:
- handleConstantAttr(S, D, AL);
- break;
- case ParsedAttr::AT_PassObjectSize:
- handlePassObjectSizeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Constructor:
- handleConstructorAttr(S, D, AL);
- break;
- case ParsedAttr::AT_CXX11NoReturn:
- handleSimpleAttribute<CXX11NoReturnAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Deprecated:
- handleDeprecatedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Destructor:
- handleDestructorAttr(S, D, AL);
- break;
- case ParsedAttr::AT_EnableIf:
- handleEnableIfAttr(S, D, AL);
- break;
- case ParsedAttr::AT_DiagnoseIf:
- handleDiagnoseIfAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ExtVectorType:
- handleExtVectorTypeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ExternalSourceSymbol:
- handleExternalSourceSymbolAttr(S, D, AL);
- break;
- case ParsedAttr::AT_MinSize:
- handleMinSizeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_OptimizeNone:
- handleOptimizeNoneAttr(S, D, AL);
- break;
- case ParsedAttr::AT_FlagEnum:
- handleSimpleAttribute<FlagEnumAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_EnumExtensibility:
- handleEnumExtensibilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Flatten:
- handleSimpleAttribute<FlattenAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Format:
- handleFormatAttr(S, D, AL);
- break;
- case ParsedAttr::AT_FormatArg:
- handleFormatArgAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Callback:
- handleCallbackAttr(S, D, AL);
- break;
- case ParsedAttr::AT_CUDAGlobal:
- handleGlobalAttr(S, D, AL);
- break;
- case ParsedAttr::AT_CUDADevice:
- handleSimpleAttributeWithExclusions<CUDADeviceAttr, CUDAGlobalAttr>(S, D,
- AL);
- break;
- case ParsedAttr::AT_CUDAHost:
- handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_GNUInline:
- handleGNUInlineAttr(S, D, AL);
- break;
- case ParsedAttr::AT_CUDALaunchBounds:
- handleLaunchBoundsAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Restrict:
- handleRestrictAttr(S, D, AL);
- break;
- case ParsedAttr::AT_LifetimeBound:
- handleSimpleAttribute<LifetimeBoundAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MayAlias:
- handleSimpleAttribute<MayAliasAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Mode:
- handleModeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoAlias:
- handleSimpleAttribute<NoAliasAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoCommon:
- handleSimpleAttribute<NoCommonAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoSplitStack:
- handleSimpleAttribute<NoSplitStackAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NonNull:
- if (auto *PVD = dyn_cast<ParmVarDecl>(D))
- handleNonNullAttrParameter(S, PVD, AL);
- else
- handleNonNullAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ReturnsNonNull:
- handleReturnsNonNullAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoEscape:
- handleNoEscapeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AssumeAligned:
- handleAssumeAlignedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AllocAlign:
- handleAllocAlignAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Overloadable:
- handleSimpleAttribute<OverloadableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Ownership:
- handleOwnershipAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Cold:
- handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Hot:
- handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Naked:
- handleNakedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoReturn:
- handleNoReturnAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AnyX86NoCfCheck:
- handleNoCfCheckAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoThrow:
- handleSimpleAttribute<NoThrowAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CUDAShared:
- handleSharedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_VecReturn:
- handleVecReturnAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCOwnership:
- handleObjCOwnershipAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCPreciseLifetime:
- handleObjCPreciseLifetimeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCReturnsInnerPointer:
- handleObjCReturnsInnerPointerAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCRequiresSuper:
- handleObjCRequiresSuperAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCBridge:
- handleObjCBridgeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCBridgeMutable:
- handleObjCBridgeMutableAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCBridgeRelated:
- handleObjCBridgeRelatedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCDesignatedInitializer:
- handleObjCDesignatedInitializer(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCRuntimeName:
- handleObjCRuntimeName(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCRuntimeVisible:
- handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCBoxable:
- handleObjCBoxable(S, D, AL);
- break;
- case ParsedAttr::AT_CFAuditedTransfer:
- handleSimpleAttributeWithExclusions<CFAuditedTransferAttr,
- CFUnknownTransferAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CFUnknownTransfer:
- handleSimpleAttributeWithExclusions<CFUnknownTransferAttr,
- CFAuditedTransferAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CFConsumed:
- case ParsedAttr::AT_NSConsumed:
- case ParsedAttr::AT_OSConsumed:
- S.AddXConsumedAttr(D, AL.getRange(), AL.getAttributeSpellingListIndex(),
- parsedAttrToRetainOwnershipKind(AL),
- /*IsTemplateInstantiation=*/false);
- break;
- case ParsedAttr::AT_NSConsumesSelf:
- handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_OSConsumesThis:
- handleSimpleAttribute<OSConsumesThisAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_OSReturnsRetainedOnZero:
- handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>(
- S, D, AL, isValidOSObjectOutParameter(D),
- diag::warn_ns_attribute_wrong_parameter_type,
- /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange());
- break;
- case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
- handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>(
- S, D, AL, isValidOSObjectOutParameter(D),
- diag::warn_ns_attribute_wrong_parameter_type,
- /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange());
- break;
- case ParsedAttr::AT_NSReturnsAutoreleased:
- case ParsedAttr::AT_NSReturnsNotRetained:
- case ParsedAttr::AT_NSReturnsRetained:
- case ParsedAttr::AT_CFReturnsNotRetained:
- case ParsedAttr::AT_CFReturnsRetained:
- case ParsedAttr::AT_OSReturnsNotRetained:
- case ParsedAttr::AT_OSReturnsRetained:
- handleXReturnsXRetainedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_WorkGroupSizeHint:
- handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ReqdWorkGroupSize:
- handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize:
- handleSubGroupSize(S, D, AL);
- break;
- case ParsedAttr::AT_VecTypeHint:
- handleVecTypeHint(S, D, AL);
- break;
- case ParsedAttr::AT_RequireConstantInit:
- handleSimpleAttribute<RequireConstantInitAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_InitPriority:
- handleInitPriorityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Packed:
- handlePackedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Section:
- handleSectionAttr(S, D, AL);
- break;
- case ParsedAttr::AT_SpeculativeLoadHardening:
- handleSimpleAttributeWithExclusions<SpeculativeLoadHardeningAttr,
- NoSpeculativeLoadHardeningAttr>(S, D,
- AL);
- break;
- case ParsedAttr::AT_NoSpeculativeLoadHardening:
- handleSimpleAttributeWithExclusions<NoSpeculativeLoadHardeningAttr,
- SpeculativeLoadHardeningAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CodeSeg:
- handleCodeSegAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Target:
- handleTargetAttr(S, D, AL);
- break;
- case ParsedAttr::AT_MinVectorWidth:
- handleMinVectorWidthAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Unavailable:
- handleAttrWithMessage<UnavailableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ArcWeakrefUnavailable:
- handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCRootClass:
- handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCNonLazyClass:
- handleSimpleAttribute<ObjCNonLazyClassAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCSubclassingRestricted:
- handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCExplicitProtocolImpl:
- handleObjCSuppresProtocolAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCRequiresPropertyDefs:
- handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Unused:
- handleUnusedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ReturnsTwice:
- handleSimpleAttribute<ReturnsTwiceAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NotTailCalled:
- handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>(
- S, D, AL);
- break;
- case ParsedAttr::AT_DisableTailCalls:
- handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
- AL);
- break;
- case ParsedAttr::AT_Used:
- handleSimpleAttribute<UsedAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Visibility:
- handleVisibilityAttr(S, D, AL, false);
- break;
- case ParsedAttr::AT_TypeVisibility:
- handleVisibilityAttr(S, D, AL, true);
- break;
- case ParsedAttr::AT_WarnUnused:
- handleSimpleAttribute<WarnUnusedAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_WarnUnusedResult:
- handleWarnUnusedResult(S, D, AL);
- break;
- case ParsedAttr::AT_Weak:
- handleSimpleAttribute<WeakAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_WeakRef:
- handleWeakRefAttr(S, D, AL);
- break;
- case ParsedAttr::AT_WeakImport:
- handleWeakImportAttr(S, D, AL);
- break;
- case ParsedAttr::AT_TransparentUnion:
- handleTransparentUnionAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCException:
- handleSimpleAttribute<ObjCExceptionAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCMethodFamily:
- handleObjCMethodFamilyAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCNSObject:
- handleObjCNSObject(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCIndependentClass:
- handleObjCIndependentClass(S, D, AL);
- break;
- case ParsedAttr::AT_Blocks:
- handleBlocksAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Sentinel:
- handleSentinelAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Const:
- handleSimpleAttribute<ConstAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Pure:
- handleSimpleAttribute<PureAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Cleanup:
- handleCleanupAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoDebug:
- handleNoDebugAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoDuplicate:
- handleSimpleAttribute<NoDuplicateAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Convergent:
- handleSimpleAttribute<ConvergentAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoInline:
- handleSimpleAttribute<NoInlineAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoInstrumentFunction: // Interacts with -pg.
- handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoStackProtector:
- // Interacts with -fstack-protector options.
- handleSimpleAttribute<NoStackProtectorAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_StdCall:
- case ParsedAttr::AT_CDecl:
- case ParsedAttr::AT_FastCall:
- case ParsedAttr::AT_ThisCall:
- case ParsedAttr::AT_Pascal:
- case ParsedAttr::AT_RegCall:
- case ParsedAttr::AT_SwiftCall:
- case ParsedAttr::AT_VectorCall:
- case ParsedAttr::AT_MSABI:
- case ParsedAttr::AT_SysVABI:
- case ParsedAttr::AT_Pcs:
- case ParsedAttr::AT_IntelOclBicc:
- case ParsedAttr::AT_PreserveMost:
- case ParsedAttr::AT_PreserveAll:
- case ParsedAttr::AT_AArch64VectorPcs:
- handleCallConvAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Suppress:
- handleSuppressAttr(S, D, AL);
- break;
- case ParsedAttr::AT_OpenCLKernel:
- handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_OpenCLAccess:
- handleOpenCLAccessAttr(S, D, AL);
- break;
- case ParsedAttr::AT_OpenCLNoSVM:
- handleOpenCLNoSVMAttr(S, D, AL);
- break;
- case ParsedAttr::AT_SwiftContext:
- handleParameterABIAttr(S, D, AL, ParameterABI::SwiftContext);
- break;
- case ParsedAttr::AT_SwiftErrorResult:
- handleParameterABIAttr(S, D, AL, ParameterABI::SwiftErrorResult);
- break;
- case ParsedAttr::AT_SwiftIndirectResult:
- handleParameterABIAttr(S, D, AL, ParameterABI::SwiftIndirectResult);
- break;
- case ParsedAttr::AT_InternalLinkage:
- handleInternalLinkageAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ExcludeFromExplicitInstantiation:
- handleSimpleAttribute<ExcludeFromExplicitInstantiationAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_LTOVisibilityPublic:
- handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);
- break;
- // Microsoft attributes:
- case ParsedAttr::AT_EmptyBases:
- handleSimpleAttribute<EmptyBasesAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_LayoutVersion:
- handleLayoutVersion(S, D, AL);
- break;
- case ParsedAttr::AT_TrivialABI:
- handleSimpleAttribute<TrivialABIAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MSNoVTable:
- handleSimpleAttribute<MSNoVTableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MSStruct:
- handleSimpleAttribute<MSStructAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Uuid:
- handleUuidAttr(S, D, AL);
- break;
- case ParsedAttr::AT_MSInheritance:
- handleMSInheritanceAttr(S, D, AL);
- break;
- case ParsedAttr::AT_SelectAny:
- handleSimpleAttribute<SelectAnyAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Thread:
- handleDeclspecThreadAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AbiTag:
- handleAbiTagAttr(S, D, AL);
- break;
- // Thread safety attributes:
- case ParsedAttr::AT_AssertExclusiveLock:
- handleAssertExclusiveLockAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AssertSharedLock:
- handleAssertSharedLockAttr(S, D, AL);
- break;
- case ParsedAttr::AT_GuardedVar:
- handleSimpleAttribute<GuardedVarAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_PtGuardedVar:
- handlePtGuardedVarAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ScopedLockable:
- handleSimpleAttribute<ScopedLockableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoSanitize:
- handleNoSanitizeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoSanitizeSpecific:
- handleNoSanitizeSpecificAttr(S, D, AL);
- break;
- case ParsedAttr::AT_NoThreadSafetyAnalysis:
- handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_GuardedBy:
- handleGuardedByAttr(S, D, AL);
- break;
- case ParsedAttr::AT_PtGuardedBy:
- handlePtGuardedByAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ExclusiveTrylockFunction:
- handleExclusiveTrylockFunctionAttr(S, D, AL);
- break;
- case ParsedAttr::AT_LockReturned:
- handleLockReturnedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_LocksExcluded:
- handleLocksExcludedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_SharedTrylockFunction:
- handleSharedTrylockFunctionAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AcquiredBefore:
- handleAcquiredBeforeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AcquiredAfter:
- handleAcquiredAfterAttr(S, D, AL);
- break;
- // Capability analysis attributes.
- case ParsedAttr::AT_Capability:
- case ParsedAttr::AT_Lockable:
- handleCapabilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_RequiresCapability:
- handleRequiresCapabilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AssertCapability:
- handleAssertCapabilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AcquireCapability:
- handleAcquireCapabilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ReleaseCapability:
- handleReleaseCapabilityAttr(S, D, AL);
- break;
- case ParsedAttr::AT_TryAcquireCapability:
- handleTryAcquireCapabilityAttr(S, D, AL);
- break;
- // Consumed analysis attributes.
- case ParsedAttr::AT_Consumable:
- handleConsumableAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ConsumableAutoCast:
- handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ConsumableSetOnRead:
- handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CallableWhen:
- handleCallableWhenAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ParamTypestate:
- handleParamTypestateAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ReturnTypestate:
- handleReturnTypestateAttr(S, D, AL);
- break;
- case ParsedAttr::AT_SetTypestate:
- handleSetTypestateAttr(S, D, AL);
- break;
- case ParsedAttr::AT_TestTypestate:
- handleTestTypestateAttr(S, D, AL);
- break;
- // Type safety attributes.
- case ParsedAttr::AT_ArgumentWithTypeTag:
- handleArgumentWithTypeTagAttr(S, D, AL);
- break;
- case ParsedAttr::AT_TypeTagForDatatype:
- handleTypeTagForDatatypeAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:
- handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_RenderScriptKernel:
- handleSimpleAttribute<RenderScriptKernelAttr>(S, D, AL);
- break;
- // XRay attributes.
- case ParsedAttr::AT_XRayInstrument:
- handleSimpleAttribute<XRayInstrumentAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_XRayLogArgs:
- handleXRayLogArgsAttr(S, D, AL);
- break;
- // Move semantics attribute.
- case ParsedAttr::AT_Reinitializes:
- handleSimpleAttribute<ReinitializesAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_AlwaysDestroy:
- case ParsedAttr::AT_NoDestroy:
- handleDestroyAttr(S, D, AL);
- break;
- case ParsedAttr::AT_Uninitialized:
- handleUninitializedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCExternallyRetained:
- handleObjCExternallyRetainedAttr(S, D, AL);
- break;
- case ParsedAttr::AT_FortifyStdLib:
- handleFortifyStdLib(S, D, AL);
- break;
- case ParsedAttr::AT_MIGServerRoutine:
- handleMIGServerRoutineAttr(S, D, AL);
- break;
- }
- }
- /// ProcessDeclAttributeList - Apply all the decl attributes in the specified
- /// attribute list to the specified decl, ignoring any type attributes.
- void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
- const ParsedAttributesView &AttrList,
- bool IncludeCXX11Attributes) {
- if (AttrList.empty())
- return;
- for (const ParsedAttr &AL : AttrList)
- ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes);
- // FIXME: We should be able to handle these cases in TableGen.
- // GCC accepts
- // static int a9 __attribute__((weakref));
- // but that looks really pointless. We reject it.
- if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
- Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias)
- << cast<NamedDecl>(D);
- D->dropAttr<WeakRefAttr>();
- return;
- }
- // FIXME: We should be able to handle this in TableGen as well. It would be
- // good to have a way to specify "these attributes must appear as a group",
- // for these. Additionally, it would be good to have a way to specify "these
- // attribute must never appear as a group" for attributes like cold and hot.
- if (!D->hasAttr<OpenCLKernelAttr>()) {
- // These attributes cannot be applied to a non-kernel function.
- if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
- // FIXME: This emits a different error message than
- // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
- Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
- D->setInvalidDecl();
- } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) {
- Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
- D->setInvalidDecl();
- } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
- Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
- D->setInvalidDecl();
- } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
- Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
- D->setInvalidDecl();
- } else if (!D->hasAttr<CUDAGlobalAttr>()) {
- if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
- Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
- << A << ExpectedKernelFunction;
- D->setInvalidDecl();
- }
- }
- }
- // Do this check after processing D's attributes because the attribute
- // objc_method_family can change whether the given method is in the init
- // family, and it can be applied after objc_designated_initializer. This is a
- // bit of a hack, but we need it to be compatible with versions of clang that
- // processed the attribute list in the wrong order.
- if (D->hasAttr<ObjCDesignatedInitializerAttr>() &&
- cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) {
- Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
- D->dropAttr<ObjCDesignatedInitializerAttr>();
- }
- }
- // Helper for delayed processing TransparentUnion attribute.
- void Sema::ProcessDeclAttributeDelayed(Decl *D,
- const ParsedAttributesView &AttrList) {
- for (const ParsedAttr &AL : AttrList)
- if (AL.getKind() == ParsedAttr::AT_TransparentUnion) {
- handleTransparentUnionAttr(*this, D, AL);
- break;
- }
- }
- // Annotation attributes are the only attributes allowed after an access
- // specifier.
- bool Sema::ProcessAccessDeclAttributeList(
- AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) {
- for (const ParsedAttr &AL : AttrList) {
- if (AL.getKind() == ParsedAttr::AT_Annotate) {
- ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute());
- } else {
- Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec);
- return true;
- }
- }
- return false;
- }
- /// checkUnusedDeclAttributes - Check a list of attributes to see if it
- /// contains any decl attributes that we should warn about.
- static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) {
- for (const ParsedAttr &AL : A) {
- // Only warn if the attribute is an unignored, non-type attribute.
- if (AL.isUsedAsTypeAttr() || AL.isInvalid())
- continue;
- if (AL.getKind() == ParsedAttr::IgnoredAttribute)
- continue;
- if (AL.getKind() == ParsedAttr::UnknownAttribute) {
- S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
- << AL << AL.getRange();
- } else {
- S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL
- << AL.getRange();
- }
- }
- }
- /// checkUnusedDeclAttributes - Given a declarator which is not being
- /// used to build a declaration, complain about any decl attributes
- /// which might be lying around on it.
- void Sema::checkUnusedDeclAttributes(Declarator &D) {
- ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes());
- ::checkUnusedDeclAttributes(*this, D.getAttributes());
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
- ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
- }
- /// DeclClonePragmaWeak - clone existing decl (maybe definition),
- /// \#pragma weak needs a non-definition decl and source may not have one.
- NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
- SourceLocation Loc) {
- assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
- NamedDecl *NewD = nullptr;
- if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
- FunctionDecl *NewFD;
- // FIXME: Missing call to CheckFunctionDeclaration().
- // FIXME: Mangling?
- // FIXME: Is the qualifier info correct?
- // FIXME: Is the DeclContext correct?
- NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
- Loc, Loc, DeclarationName(II),
- FD->getType(), FD->getTypeSourceInfo(),
- SC_None, false/*isInlineSpecified*/,
- FD->hasPrototype(),
- false/*isConstexprSpecified*/);
- NewD = NewFD;
- if (FD->getQualifier())
- NewFD->setQualifierInfo(FD->getQualifierLoc());
- // Fake up parameter variables; they are declared as if this were
- // a typedef.
- QualType FDTy = FD->getType();
- if (const auto *FT = FDTy->getAs<FunctionProtoType>()) {
- SmallVector<ParmVarDecl*, 16> Params;
- for (const auto &AI : FT->param_types()) {
- ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
- Param->setScopeInfo(0, Params.size());
- Params.push_back(Param);
- }
- NewFD->setParams(Params);
- }
- } else if (auto *VD = dyn_cast<VarDecl>(ND)) {
- NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
- VD->getInnerLocStart(), VD->getLocation(), II,
- VD->getType(), VD->getTypeSourceInfo(),
- VD->getStorageClass());
- if (VD->getQualifier())
- cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc());
- }
- return NewD;
- }
- /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak
- /// applied to it, possibly with an alias.
- void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
- if (W.getUsed()) return; // only do this once
- W.setUsed(true);
- if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
- IdentifierInfo *NDId = ND->getIdentifier();
- NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
- NewD->addAttr(AliasAttr::CreateImplicit(Context, NDId->getName(),
- W.getLocation()));
- NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
- WeakTopLevelDecl.push_back(NewD);
- // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
- // to insert Decl at TU scope, sorry.
- DeclContext *SavedContext = CurContext;
- CurContext = Context.getTranslationUnitDecl();
- NewD->setDeclContext(CurContext);
- NewD->setLexicalDeclContext(CurContext);
- PushOnScopeChains(NewD, S);
- CurContext = SavedContext;
- } else { // just add weak to existing
- ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
- }
- }
- void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
- // It's valid to "forward-declare" #pragma weak, in which case we
- // have to do this.
- LoadExternalWeakUndeclaredIdentifiers();
- if (!WeakUndeclaredIdentifiers.empty()) {
- NamedDecl *ND = nullptr;
- if (auto *VD = dyn_cast<VarDecl>(D))
- if (VD->isExternC())
- ND = VD;
- if (auto *FD = dyn_cast<FunctionDecl>(D))
- if (FD->isExternC())
- ND = FD;
- if (ND) {
- if (IdentifierInfo *Id = ND->getIdentifier()) {
- auto I = WeakUndeclaredIdentifiers.find(Id);
- if (I != WeakUndeclaredIdentifiers.end()) {
- WeakInfo W = I->second;
- DeclApplyPragmaWeak(S, ND, W);
- WeakUndeclaredIdentifiers[Id] = W;
- }
- }
- }
- }
- }
- /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
- /// it, apply them to D. This is a bit tricky because PD can have attributes
- /// specified in many different places, and we need to find and apply them all.
- void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
- // Apply decl attributes from the DeclSpec if present.
- if (!PD.getDeclSpec().getAttributes().empty())
- ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes());
- // Walk the declarator structure, applying decl attributes that were in a type
- // position to the decl itself. This handles cases like:
- // int *__attr__(x)** D;
- // when X is a decl attribute.
- for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
- ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(),
- /*IncludeCXX11Attributes=*/false);
- // Finally, apply any attributes on the decl itself.
- ProcessDeclAttributeList(S, D, PD.getAttributes());
- // Apply additional attributes specified by '#pragma clang attribute'.
- AddPragmaAttributes(S, D);
- }
- /// Is the given declaration allowed to use a forbidden type?
- /// If so, it'll still be annotated with an attribute that makes it
- /// illegal to actually use.
- static bool isForbiddenTypeAllowed(Sema &S, Decl *D,
- const DelayedDiagnostic &diag,
- UnavailableAttr::ImplicitReason &reason) {
- // Private ivars are always okay. Unfortunately, people don't
- // always properly make their ivars private, even in system headers.
- // Plus we need to make fields okay, too.
- if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) &&
- !isa<FunctionDecl>(D))
- return false;
- // Silently accept unsupported uses of __weak in both user and system
- // declarations when it's been disabled, for ease of integration with
- // -fno-objc-arc files. We do have to take some care against attempts
- // to define such things; for now, we've only done that for ivars
- // and properties.
- if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) {
- if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
- diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
- reason = UnavailableAttr::IR_ForbiddenWeak;
- return true;
- }
- }
- // Allow all sorts of things in system headers.
- if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) {
- // Currently, all the failures dealt with this way are due to ARC
- // restrictions.
- reason = UnavailableAttr::IR_ARCForbiddenType;
- return true;
- }
- return false;
- }
- /// Handle a delayed forbidden-type diagnostic.
- static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD,
- Decl *D) {
- auto Reason = UnavailableAttr::IR_None;
- if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) {
- assert(Reason && "didn't set reason?");
- D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc));
- return;
- }
- if (S.getLangOpts().ObjCAutoRefCount)
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- // FIXME: we may want to suppress diagnostics for all
- // kind of forbidden type messages on unavailable functions.
- if (FD->hasAttr<UnavailableAttr>() &&
- DD.getForbiddenTypeDiagnostic() ==
- diag::err_arc_array_param_no_ownership) {
- DD.Triggered = true;
- return;
- }
- }
- S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic())
- << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument();
- DD.Triggered = true;
- }
- static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
- const Decl *D) {
- // Check each AvailabilityAttr to find the one for this platform.
- for (const auto *A : D->attrs()) {
- if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
- // FIXME: this is copied from CheckAvailability. We should try to
- // de-duplicate.
- // Check if this is an App Extension "platform", and if so chop off
- // the suffix for matching with the actual platform.
- StringRef ActualPlatform = Avail->getPlatform()->getName();
- StringRef RealizedPlatform = ActualPlatform;
- if (Context.getLangOpts().AppExt) {
- size_t suffix = RealizedPlatform.rfind("_app_extension");
- if (suffix != StringRef::npos)
- RealizedPlatform = RealizedPlatform.slice(0, suffix);
- }
- StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
- // Match the platform name.
- if (RealizedPlatform == TargetPlatform)
- return Avail;
- }
- }
- return nullptr;
- }
- /// The diagnostic we should emit for \c D, and the declaration that
- /// originated it, or \c AR_Available.
- ///
- /// \param D The declaration to check.
- /// \param Message If non-null, this will be populated with the message from
- /// the availability attribute that is selected.
- /// \param ClassReceiver If we're checking the the method of a class message
- /// send, the class. Otherwise nullptr.
- static std::pair<AvailabilityResult, const NamedDecl *>
- ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D,
- std::string *Message,
- ObjCInterfaceDecl *ClassReceiver) {
- AvailabilityResult Result = D->getAvailability(Message);
- // For typedefs, if the typedef declaration appears available look
- // to the underlying type to see if it is more restrictive.
- while (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
- if (Result == AR_Available) {
- if (const auto *TT = TD->getUnderlyingType()->getAs<TagType>()) {
- D = TT->getDecl();
- Result = D->getAvailability(Message);
- continue;
- }
- }
- break;
- }
- // Forward class declarations get their attributes from their definition.
- if (const auto *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
- if (IDecl->getDefinition()) {
- D = IDecl->getDefinition();
- Result = D->getAvailability(Message);
- }
- }
- if (const auto *ECD = dyn_cast<EnumConstantDecl>(D))
- if (Result == AR_Available) {
- const DeclContext *DC = ECD->getDeclContext();
- if (const auto *TheEnumDecl = dyn_cast<EnumDecl>(DC)) {
- Result = TheEnumDecl->getAvailability(Message);
- D = TheEnumDecl;
- }
- }
- // For +new, infer availability from -init.
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (S.NSAPIObj && ClassReceiver) {
- ObjCMethodDecl *Init = ClassReceiver->lookupInstanceMethod(
- S.NSAPIObj->getInitSelector());
- if (Init && Result == AR_Available && MD->isClassMethod() &&
- MD->getSelector() == S.NSAPIObj->getNewSelector() &&
- MD->definedInNSObject(S.getASTContext())) {
- Result = Init->getAvailability(Message);
- D = Init;
- }
- }
- }
- return {Result, D};
- }
- /// whether we should emit a diagnostic for \c K and \c DeclVersion in
- /// the context of \c Ctx. For example, we should emit an unavailable diagnostic
- /// in a deprecated context, but not the other way around.
- static bool
- ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
- VersionTuple DeclVersion, Decl *Ctx,
- const NamedDecl *OffendingDecl) {
- assert(K != AR_Available && "Expected an unavailable declaration here!");
- // Checks if we should emit the availability diagnostic in the context of C.
- auto CheckContext = [&](const Decl *C) {
- if (K == AR_NotYetIntroduced) {
- if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C))
- if (AA->getIntroduced() >= DeclVersion)
- return true;
- } else if (K == AR_Deprecated) {
- if (C->isDeprecated())
- return true;
- } else if (K == AR_Unavailable) {
- // It is perfectly fine to refer to an 'unavailable' Objective-C method
- // when it is referenced from within the @implementation itself. In this
- // context, we interpret unavailable as a form of access control.
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(OffendingDecl)) {
- if (const auto *Impl = dyn_cast<ObjCImplDecl>(C)) {
- if (MD->getClassInterface() == Impl->getClassInterface())
- return true;
- }
- }
- }
- if (C->isUnavailable())
- return true;
- return false;
- };
- do {
- if (CheckContext(Ctx))
- return false;
- // An implementation implicitly has the availability of the interface.
- // Unless it is "+load" method.
- if (const auto *MethodD = dyn_cast<ObjCMethodDecl>(Ctx))
- if (MethodD->isClassMethod() &&
- MethodD->getSelector().getAsString() == "load")
- return true;
- if (const auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) {
- if (const ObjCInterfaceDecl *Interface = CatOrImpl->getClassInterface())
- if (CheckContext(Interface))
- return false;
- }
- // A category implicitly has the availability of the interface.
- else if (const auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx))
- if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
- if (CheckContext(Interface))
- return false;
- } while ((Ctx = cast_or_null<Decl>(Ctx->getDeclContext())));
- return true;
- }
- static bool
- shouldDiagnoseAvailabilityByDefault(const ASTContext &Context,
- const VersionTuple &DeploymentVersion,
- const VersionTuple &DeclVersion) {
- const auto &Triple = Context.getTargetInfo().getTriple();
- VersionTuple ForceAvailabilityFromVersion;
- switch (Triple.getOS()) {
- case llvm::Triple::IOS:
- case llvm::Triple::TvOS:
- ForceAvailabilityFromVersion = VersionTuple(/*Major=*/11);
- break;
- case llvm::Triple::WatchOS:
- ForceAvailabilityFromVersion = VersionTuple(/*Major=*/4);
- break;
- case llvm::Triple::Darwin:
- case llvm::Triple::MacOSX:
- ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13);
- break;
- default:
- // New targets should always warn about availability.
- return Triple.getVendor() == llvm::Triple::Apple;
- }
- return DeploymentVersion >= ForceAvailabilityFromVersion ||
- DeclVersion >= ForceAvailabilityFromVersion;
- }
- static NamedDecl *findEnclosingDeclToAnnotate(Decl *OrigCtx) {
- for (Decl *Ctx = OrigCtx; Ctx;
- Ctx = cast_or_null<Decl>(Ctx->getDeclContext())) {
- if (isa<TagDecl>(Ctx) || isa<FunctionDecl>(Ctx) || isa<ObjCMethodDecl>(Ctx))
- return cast<NamedDecl>(Ctx);
- if (auto *CD = dyn_cast<ObjCContainerDecl>(Ctx)) {
- if (auto *Imp = dyn_cast<ObjCImplDecl>(Ctx))
- return Imp->getClassInterface();
- return CD;
- }
- }
- return dyn_cast<NamedDecl>(OrigCtx);
- }
- namespace {
- struct AttributeInsertion {
- StringRef Prefix;
- SourceLocation Loc;
- StringRef Suffix;
- static AttributeInsertion createInsertionAfter(const NamedDecl *D) {
- return {" ", D->getEndLoc(), ""};
- }
- static AttributeInsertion createInsertionAfter(SourceLocation Loc) {
- return {" ", Loc, ""};
- }
- static AttributeInsertion createInsertionBefore(const NamedDecl *D) {
- return {"", D->getBeginLoc(), "\n"};
- }
- };
- } // end anonymous namespace
- /// Tries to parse a string as ObjC method name.
- ///
- /// \param Name The string to parse. Expected to originate from availability
- /// attribute argument.
- /// \param SlotNames The vector that will be populated with slot names. In case
- /// of unsuccessful parsing can contain invalid data.
- /// \returns A number of method parameters if parsing was successful, None
- /// otherwise.
- static Optional<unsigned>
- tryParseObjCMethodName(StringRef Name, SmallVectorImpl<StringRef> &SlotNames,
- const LangOptions &LangOpts) {
- // Accept replacements starting with - or + as valid ObjC method names.
- if (!Name.empty() && (Name.front() == '-' || Name.front() == '+'))
- Name = Name.drop_front(1);
- if (Name.empty())
- return None;
- Name.split(SlotNames, ':');
- unsigned NumParams;
- if (Name.back() == ':') {
- // Remove an empty string at the end that doesn't represent any slot.
- SlotNames.pop_back();
- NumParams = SlotNames.size();
- } else {
- if (SlotNames.size() != 1)
- // Not a valid method name, just a colon-separated string.
- return None;
- NumParams = 0;
- }
- // Verify all slot names are valid.
- bool AllowDollar = LangOpts.DollarIdents;
- for (StringRef S : SlotNames) {
- if (S.empty())
- continue;
- if (!isValidIdentifier(S, AllowDollar))
- return None;
- }
- return NumParams;
- }
- /// Returns a source location in which it's appropriate to insert a new
- /// attribute for the given declaration \D.
- static Optional<AttributeInsertion>
- createAttributeInsertion(const NamedDecl *D, const SourceManager &SM,
- const LangOptions &LangOpts) {
- if (isa<ObjCPropertyDecl>(D))
- return AttributeInsertion::createInsertionAfter(D);
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (MD->hasBody())
- return None;
- return AttributeInsertion::createInsertionAfter(D);
- }
- if (const auto *TD = dyn_cast<TagDecl>(D)) {
- SourceLocation Loc =
- Lexer::getLocForEndOfToken(TD->getInnerLocStart(), 0, SM, LangOpts);
- if (Loc.isInvalid())
- return None;
- // Insert after the 'struct'/whatever keyword.
- return AttributeInsertion::createInsertionAfter(Loc);
- }
- return AttributeInsertion::createInsertionBefore(D);
- }
- /// Actually emit an availability diagnostic for a reference to an unavailable
- /// decl.
- ///
- /// \param Ctx The context that the reference occurred in
- /// \param ReferringDecl The exact declaration that was referenced.
- /// \param OffendingDecl A related decl to \c ReferringDecl that has an
- /// availability attribute corresponding to \c K attached to it. Note that this
- /// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated and
- /// we refer to a member EnumConstantDecl, ReferringDecl is the EnumConstantDecl
- /// and OffendingDecl is the EnumDecl.
- static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
- Decl *Ctx, const NamedDecl *ReferringDecl,
- const NamedDecl *OffendingDecl,
- StringRef Message,
- ArrayRef<SourceLocation> Locs,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty,
- bool ObjCPropertyAccess) {
- // Diagnostics for deprecated or unavailable.
- unsigned diag, diag_message, diag_fwdclass_message;
- unsigned diag_available_here = diag::note_availability_specified_here;
- SourceLocation NoteLocation = OffendingDecl->getLocation();
- // Matches 'diag::note_property_attribute' options.
- unsigned property_note_select;
- // Matches diag::note_availability_specified_here.
- unsigned available_here_select_kind;
- VersionTuple DeclVersion;
- if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl))
- DeclVersion = AA->getIntroduced();
- if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx,
- OffendingDecl))
- return;
- SourceLocation Loc = Locs.front();
- // The declaration can have multiple availability attributes, we are looking
- // at one of them.
- const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
- if (A && A->isInherited()) {
- for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl;
- Redecl = Redecl->getPreviousDecl()) {
- const AvailabilityAttr *AForRedecl =
- getAttrForPlatform(S.Context, Redecl);
- if (AForRedecl && !AForRedecl->isInherited()) {
- // If D is a declaration with inherited attributes, the note should
- // point to the declaration with actual attributes.
- NoteLocation = Redecl->getLocation();
- break;
- }
- }
- }
- switch (K) {
- case AR_NotYetIntroduced: {
- // We would like to emit the diagnostic even if -Wunguarded-availability is
- // not specified for deployment targets >= to iOS 11 or equivalent or
- // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
- // later.
- const AvailabilityAttr *AA =
- getAttrForPlatform(S.getASTContext(), OffendingDecl);
- VersionTuple Introduced = AA->getIntroduced();
- bool UseNewWarning = shouldDiagnoseAvailabilityByDefault(
- S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
- Introduced);
- unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new
- : diag::warn_unguarded_availability;
- std::string PlatformName = AvailabilityAttr::getPrettyPlatformName(
- S.getASTContext().getTargetInfo().getPlatformName());
- S.Diag(Loc, Warning) << OffendingDecl << PlatformName
- << Introduced.getAsString();
- S.Diag(OffendingDecl->getLocation(),
- diag::note_partial_availability_specified_here)
- << OffendingDecl << PlatformName << Introduced.getAsString()
- << S.Context.getTargetInfo().getPlatformMinVersion().getAsString();
- if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
- if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
- if (TD->getDeclName().isEmpty()) {
- S.Diag(TD->getLocation(),
- diag::note_decl_unguarded_availability_silence)
- << /*Anonymous*/ 1 << TD->getKindName();
- return;
- }
- auto FixitNoteDiag =
- S.Diag(Enclosing->getLocation(),
- diag::note_decl_unguarded_availability_silence)
- << /*Named*/ 0 << Enclosing;
- // Don't offer a fixit for declarations with availability attributes.
- if (Enclosing->hasAttr<AvailabilityAttr>())
- return;
- if (!S.getPreprocessor().isMacroDefined("API_AVAILABLE"))
- return;
- Optional<AttributeInsertion> Insertion = createAttributeInsertion(
- Enclosing, S.getSourceManager(), S.getLangOpts());
- if (!Insertion)
- return;
- std::string PlatformName =
- AvailabilityAttr::getPlatformNameSourceSpelling(
- S.getASTContext().getTargetInfo().getPlatformName())
- .lower();
- std::string Introduced =
- OffendingDecl->getVersionIntroduced().getAsString();
- FixitNoteDiag << FixItHint::CreateInsertion(
- Insertion->Loc,
- (llvm::Twine(Insertion->Prefix) + "API_AVAILABLE(" + PlatformName +
- "(" + Introduced + "))" + Insertion->Suffix)
- .str());
- }
- return;
- }
- case AR_Deprecated:
- diag = !ObjCPropertyAccess ? diag::warn_deprecated
- : diag::warn_property_method_deprecated;
- diag_message = diag::warn_deprecated_message;
- diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
- property_note_select = /* deprecated */ 0;
- available_here_select_kind = /* deprecated */ 2;
- if (const auto *AL = OffendingDecl->getAttr<DeprecatedAttr>())
- NoteLocation = AL->getLocation();
- break;
- case AR_Unavailable:
- diag = !ObjCPropertyAccess ? diag::err_unavailable
- : diag::err_property_method_unavailable;
- diag_message = diag::err_unavailable_message;
- diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
- property_note_select = /* unavailable */ 1;
- available_here_select_kind = /* unavailable */ 0;
- if (auto AL = OffendingDecl->getAttr<UnavailableAttr>()) {
- if (AL->isImplicit() && AL->getImplicitReason()) {
- // Most of these failures are due to extra restrictions in ARC;
- // reflect that in the primary diagnostic when applicable.
- auto flagARCError = [&] {
- if (S.getLangOpts().ObjCAutoRefCount &&
- S.getSourceManager().isInSystemHeader(
- OffendingDecl->getLocation()))
- diag = diag::err_unavailable_in_arc;
- };
- switch (AL->getImplicitReason()) {
- case UnavailableAttr::IR_None: break;
- case UnavailableAttr::IR_ARCForbiddenType:
- flagARCError();
- diag_available_here = diag::note_arc_forbidden_type;
- break;
- case UnavailableAttr::IR_ForbiddenWeak:
- if (S.getLangOpts().ObjCWeakRuntime)
- diag_available_here = diag::note_arc_weak_disabled;
- else
- diag_available_here = diag::note_arc_weak_no_runtime;
- break;
- case UnavailableAttr::IR_ARCForbiddenConversion:
- flagARCError();
- diag_available_here = diag::note_performs_forbidden_arc_conversion;
- break;
- case UnavailableAttr::IR_ARCInitReturnsUnrelated:
- flagARCError();
- diag_available_here = diag::note_arc_init_returns_unrelated;
- break;
- case UnavailableAttr::IR_ARCFieldWithOwnership:
- flagARCError();
- diag_available_here = diag::note_arc_field_with_ownership;
- break;
- }
- }
- }
- break;
- case AR_Available:
- llvm_unreachable("Warning for availability of available declaration?");
- }
- SmallVector<FixItHint, 12> FixIts;
- if (K == AR_Deprecated) {
- StringRef Replacement;
- if (auto AL = OffendingDecl->getAttr<DeprecatedAttr>())
- Replacement = AL->getReplacement();
- if (auto AL = getAttrForPlatform(S.Context, OffendingDecl))
- Replacement = AL->getReplacement();
- CharSourceRange UseRange;
- if (!Replacement.empty())
- UseRange =
- CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
- if (UseRange.isValid()) {
- if (const auto *MethodDecl = dyn_cast<ObjCMethodDecl>(ReferringDecl)) {
- Selector Sel = MethodDecl->getSelector();
- SmallVector<StringRef, 12> SelectorSlotNames;
- Optional<unsigned> NumParams = tryParseObjCMethodName(
- Replacement, SelectorSlotNames, S.getLangOpts());
- if (NumParams && NumParams.getValue() == Sel.getNumArgs()) {
- assert(SelectorSlotNames.size() == Locs.size());
- for (unsigned I = 0; I < Locs.size(); ++I) {
- if (!Sel.getNameForSlot(I).empty()) {
- CharSourceRange NameRange = CharSourceRange::getCharRange(
- Locs[I], S.getLocForEndOfToken(Locs[I]));
- FixIts.push_back(FixItHint::CreateReplacement(
- NameRange, SelectorSlotNames[I]));
- } else
- FixIts.push_back(
- FixItHint::CreateInsertion(Locs[I], SelectorSlotNames[I]));
- }
- } else
- FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
- } else
- FixIts.push_back(FixItHint::CreateReplacement(UseRange, Replacement));
- }
- }
- if (!Message.empty()) {
- S.Diag(Loc, diag_message) << ReferringDecl << Message << FixIts;
- if (ObjCProperty)
- S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
- << ObjCProperty->getDeclName() << property_note_select;
- } else if (!UnknownObjCClass) {
- S.Diag(Loc, diag) << ReferringDecl << FixIts;
- if (ObjCProperty)
- S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
- << ObjCProperty->getDeclName() << property_note_select;
- } else {
- S.Diag(Loc, diag_fwdclass_message) << ReferringDecl << FixIts;
- S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
- }
- S.Diag(NoteLocation, diag_available_here)
- << OffendingDecl << available_here_select_kind;
- }
- static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
- Decl *Ctx) {
- assert(DD.Kind == DelayedDiagnostic::Availability &&
- "Expected an availability diagnostic here");
- DD.Triggered = true;
- DoEmitAvailabilityWarning(
- S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl(),
- DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(),
- DD.getAvailabilitySelectorLocs(), DD.getUnknownObjCClass(),
- DD.getObjCProperty(), false);
- }
- void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
- assert(DelayedDiagnostics.getCurrentPool());
- DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool();
- DelayedDiagnostics.popWithoutEmitting(state);
- // When delaying diagnostics to run in the context of a parsed
- // declaration, we only want to actually emit anything if parsing
- // succeeds.
- if (!decl) return;
- // We emit all the active diagnostics in this pool or any of its
- // parents. In general, we'll get one pool for the decl spec
- // and a child pool for each declarator; in a decl group like:
- // deprecated_typedef foo, *bar, baz();
- // only the declarator pops will be passed decls. This is correct;
- // we really do need to consider delayed diagnostics from the decl spec
- // for each of the different declarations.
- const DelayedDiagnosticPool *pool = &poppedPool;
- do {
- bool AnyAccessFailures = false;
- for (DelayedDiagnosticPool::pool_iterator
- i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
- // This const_cast is a bit lame. Really, Triggered should be mutable.
- DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
- if (diag.Triggered)
- continue;
- switch (diag.Kind) {
- case DelayedDiagnostic::Availability:
- // Don't bother giving deprecation/unavailable diagnostics if
- // the decl is invalid.
- if (!decl->isInvalidDecl())
- handleDelayedAvailabilityCheck(*this, diag, decl);
- break;
- case DelayedDiagnostic::Access:
- // Only produce one access control diagnostic for a structured binding
- // declaration: we don't need to tell the user that all the fields are
- // inaccessible one at a time.
- if (AnyAccessFailures && isa<DecompositionDecl>(decl))
- continue;
- HandleDelayedAccessCheck(diag, decl);
- if (diag.Triggered)
- AnyAccessFailures = true;
- break;
- case DelayedDiagnostic::ForbiddenType:
- handleDelayedForbiddenType(*this, diag, decl);
- break;
- }
- }
- } while ((pool = pool->getParent()));
- }
- /// Given a set of delayed diagnostics, re-emit them as if they had
- /// been delayed in the current context instead of in the given pool.
- /// Essentially, this just moves them to the current pool.
- void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
- DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool();
- assert(curPool && "re-emitting in undelayed context not supported");
- curPool->steal(pool);
- }
- static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR,
- const NamedDecl *ReferringDecl,
- const NamedDecl *OffendingDecl,
- StringRef Message,
- ArrayRef<SourceLocation> Locs,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty,
- bool ObjCPropertyAccess) {
- // Delay if we're currently parsing a declaration.
- if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
- S.DelayedDiagnostics.add(
- DelayedDiagnostic::makeAvailability(
- AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass,
- ObjCProperty, Message, ObjCPropertyAccess));
- return;
- }
- Decl *Ctx = cast<Decl>(S.getCurLexicalContext());
- DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl,
- Message, Locs, UnknownObjCClass, ObjCProperty,
- ObjCPropertyAccess);
- }
- namespace {
- /// Returns true if the given statement can be a body-like child of \p Parent.
- bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) {
- switch (Parent->getStmtClass()) {
- case Stmt::IfStmtClass:
- return cast<IfStmt>(Parent)->getThen() == S ||
- cast<IfStmt>(Parent)->getElse() == S;
- case Stmt::WhileStmtClass:
- return cast<WhileStmt>(Parent)->getBody() == S;
- case Stmt::DoStmtClass:
- return cast<DoStmt>(Parent)->getBody() == S;
- case Stmt::ForStmtClass:
- return cast<ForStmt>(Parent)->getBody() == S;
- case Stmt::CXXForRangeStmtClass:
- return cast<CXXForRangeStmt>(Parent)->getBody() == S;
- case Stmt::ObjCForCollectionStmtClass:
- return cast<ObjCForCollectionStmt>(Parent)->getBody() == S;
- case Stmt::CaseStmtClass:
- case Stmt::DefaultStmtClass:
- return cast<SwitchCase>(Parent)->getSubStmt() == S;
- default:
- return false;
- }
- }
- class StmtUSEFinder : public RecursiveASTVisitor<StmtUSEFinder> {
- const Stmt *Target;
- public:
- bool VisitStmt(Stmt *S) { return S != Target; }
- /// Returns true if the given statement is present in the given declaration.
- static bool isContained(const Stmt *Target, const Decl *D) {
- StmtUSEFinder Visitor;
- Visitor.Target = Target;
- return !Visitor.TraverseDecl(const_cast<Decl *>(D));
- }
- };
- /// Traverses the AST and finds the last statement that used a given
- /// declaration.
- class LastDeclUSEFinder : public RecursiveASTVisitor<LastDeclUSEFinder> {
- const Decl *D;
- public:
- bool VisitDeclRefExpr(DeclRefExpr *DRE) {
- if (DRE->getDecl() == D)
- return false;
- return true;
- }
- static const Stmt *findLastStmtThatUsesDecl(const Decl *D,
- const CompoundStmt *Scope) {
- LastDeclUSEFinder Visitor;
- Visitor.D = D;
- for (auto I = Scope->body_rbegin(), E = Scope->body_rend(); I != E; ++I) {
- const Stmt *S = *I;
- if (!Visitor.TraverseStmt(const_cast<Stmt *>(S)))
- return S;
- }
- return nullptr;
- }
- };
- /// This class implements -Wunguarded-availability.
- ///
- /// This is done with a traversal of the AST of a function that makes reference
- /// to a partially available declaration. Whenever we encounter an \c if of the
- /// form: \c if(@available(...)), we use the version from the condition to visit
- /// the then statement.
- class DiagnoseUnguardedAvailability
- : public RecursiveASTVisitor<DiagnoseUnguardedAvailability> {
- typedef RecursiveASTVisitor<DiagnoseUnguardedAvailability> Base;
- Sema &SemaRef;
- Decl *Ctx;
- /// Stack of potentially nested 'if (@available(...))'s.
- SmallVector<VersionTuple, 8> AvailabilityStack;
- SmallVector<const Stmt *, 16> StmtStack;
- void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range,
- ObjCInterfaceDecl *ClassReceiver = nullptr);
- public:
- DiagnoseUnguardedAvailability(Sema &SemaRef, Decl *Ctx)
- : SemaRef(SemaRef), Ctx(Ctx) {
- AvailabilityStack.push_back(
- SemaRef.Context.getTargetInfo().getPlatformMinVersion());
- }
- bool TraverseDecl(Decl *D) {
- // Avoid visiting nested functions to prevent duplicate warnings.
- if (!D || isa<FunctionDecl>(D))
- return true;
- return Base::TraverseDecl(D);
- }
- bool TraverseStmt(Stmt *S) {
- if (!S)
- return true;
- StmtStack.push_back(S);
- bool Result = Base::TraverseStmt(S);
- StmtStack.pop_back();
- return Result;
- }
- void IssueDiagnostics(Stmt *S) { TraverseStmt(S); }
- bool TraverseIfStmt(IfStmt *If);
- bool TraverseLambdaExpr(LambdaExpr *E) { return true; }
- // for 'case X:' statements, don't bother looking at the 'X'; it can't lead
- // to any useful diagnostics.
- bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); }
- bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) {
- if (PRE->isClassReceiver())
- DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation());
- return true;
- }
- bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
- if (ObjCMethodDecl *D = Msg->getMethodDecl()) {
- ObjCInterfaceDecl *ID = nullptr;
- QualType ReceiverTy = Msg->getClassReceiver();
- if (!ReceiverTy.isNull() && ReceiverTy->getAsObjCInterfaceType())
- ID = ReceiverTy->getAsObjCInterfaceType()->getInterface();
- DiagnoseDeclAvailability(
- D, SourceRange(Msg->getSelectorStartLoc(), Msg->getEndLoc()), ID);
- }
- return true;
- }
- bool VisitDeclRefExpr(DeclRefExpr *DRE) {
- DiagnoseDeclAvailability(DRE->getDecl(),
- SourceRange(DRE->getBeginLoc(), DRE->getEndLoc()));
- return true;
- }
- bool VisitMemberExpr(MemberExpr *ME) {
- DiagnoseDeclAvailability(ME->getMemberDecl(),
- SourceRange(ME->getBeginLoc(), ME->getEndLoc()));
- return true;
- }
- bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) {
- SemaRef.Diag(E->getBeginLoc(), diag::warn_at_available_unchecked_use)
- << (!SemaRef.getLangOpts().ObjC);
- return true;
- }
- bool VisitTypeLoc(TypeLoc Ty);
- };
- void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
- NamedDecl *D, SourceRange Range, ObjCInterfaceDecl *ReceiverClass) {
- AvailabilityResult Result;
- const NamedDecl *OffendingDecl;
- std::tie(Result, OffendingDecl) =
- ShouldDiagnoseAvailabilityOfDecl(SemaRef, D, nullptr, ReceiverClass);
- if (Result != AR_Available) {
- // All other diagnostic kinds have already been handled in
- // DiagnoseAvailabilityOfDecl.
- if (Result != AR_NotYetIntroduced)
- return;
- const AvailabilityAttr *AA =
- getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
- VersionTuple Introduced = AA->getIntroduced();
- if (AvailabilityStack.back() >= Introduced)
- return;
- // If the context of this function is less available than D, we should not
- // emit a diagnostic.
- if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx,
- OffendingDecl))
- return;
- // We would like to emit the diagnostic even if -Wunguarded-availability is
- // not specified for deployment targets >= to iOS 11 or equivalent or
- // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
- // later.
- unsigned DiagKind =
- shouldDiagnoseAvailabilityByDefault(
- SemaRef.Context,
- SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced)
- ? diag::warn_unguarded_availability_new
- : diag::warn_unguarded_availability;
- std::string PlatformName = AvailabilityAttr::getPrettyPlatformName(
- SemaRef.getASTContext().getTargetInfo().getPlatformName());
- SemaRef.Diag(Range.getBegin(), DiagKind)
- << Range << D << PlatformName << Introduced.getAsString();
- SemaRef.Diag(OffendingDecl->getLocation(),
- diag::note_partial_availability_specified_here)
- << OffendingDecl << PlatformName << Introduced.getAsString()
- << SemaRef.Context.getTargetInfo()
- .getPlatformMinVersion()
- .getAsString();
- auto FixitDiag =
- SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
- << Range << D
- << (SemaRef.getLangOpts().ObjC ? /*@available*/ 0
- : /*__builtin_available*/ 1);
- // Find the statement which should be enclosed in the if @available check.
- if (StmtStack.empty())
- return;
- const Stmt *StmtOfUse = StmtStack.back();
- const CompoundStmt *Scope = nullptr;
- for (const Stmt *S : llvm::reverse(StmtStack)) {
- if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
- Scope = CS;
- break;
- }
- if (isBodyLikeChildStmt(StmtOfUse, S)) {
- // The declaration won't be seen outside of the statement, so we don't
- // have to wrap the uses of any declared variables in if (@available).
- // Therefore we can avoid setting Scope here.
- break;
- }
- StmtOfUse = S;
- }
- const Stmt *LastStmtOfUse = nullptr;
- if (isa<DeclStmt>(StmtOfUse) && Scope) {
- for (const Decl *D : cast<DeclStmt>(StmtOfUse)->decls()) {
- if (StmtUSEFinder::isContained(StmtStack.back(), D)) {
- LastStmtOfUse = LastDeclUSEFinder::findLastStmtThatUsesDecl(D, Scope);
- break;
- }
- }
- }
- const SourceManager &SM = SemaRef.getSourceManager();
- SourceLocation IfInsertionLoc =
- SM.getExpansionLoc(StmtOfUse->getBeginLoc());
- SourceLocation StmtEndLoc =
- SM.getExpansionRange(
- (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getEndLoc())
- .getEnd();
- if (SM.getFileID(IfInsertionLoc) != SM.getFileID(StmtEndLoc))
- return;
- StringRef Indentation = Lexer::getIndentationForLine(IfInsertionLoc, SM);
- const char *ExtraIndentation = " ";
- std::string FixItString;
- llvm::raw_string_ostream FixItOS(FixItString);
- FixItOS << "if (" << (SemaRef.getLangOpts().ObjC ? "@available"
- : "__builtin_available")
- << "("
- << AvailabilityAttr::getPlatformNameSourceSpelling(
- SemaRef.getASTContext().getTargetInfo().getPlatformName())
- << " " << Introduced.getAsString() << ", *)) {\n"
- << Indentation << ExtraIndentation;
- FixitDiag << FixItHint::CreateInsertion(IfInsertionLoc, FixItOS.str());
- SourceLocation ElseInsertionLoc = Lexer::findLocationAfterToken(
- StmtEndLoc, tok::semi, SM, SemaRef.getLangOpts(),
- /*SkipTrailingWhitespaceAndNewLine=*/false);
- if (ElseInsertionLoc.isInvalid())
- ElseInsertionLoc =
- Lexer::getLocForEndOfToken(StmtEndLoc, 0, SM, SemaRef.getLangOpts());
- FixItOS.str().clear();
- FixItOS << "\n"
- << Indentation << "} else {\n"
- << Indentation << ExtraIndentation
- << "// Fallback on earlier versions\n"
- << Indentation << "}";
- FixitDiag << FixItHint::CreateInsertion(ElseInsertionLoc, FixItOS.str());
- }
- }
- bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) {
- const Type *TyPtr = Ty.getTypePtr();
- SourceRange Range{Ty.getBeginLoc(), Ty.getEndLoc()};
- if (Range.isInvalid())
- return true;
- if (const auto *TT = dyn_cast<TagType>(TyPtr)) {
- TagDecl *TD = TT->getDecl();
- DiagnoseDeclAvailability(TD, Range);
- } else if (const auto *TD = dyn_cast<TypedefType>(TyPtr)) {
- TypedefNameDecl *D = TD->getDecl();
- DiagnoseDeclAvailability(D, Range);
- } else if (const auto *ObjCO = dyn_cast<ObjCObjectType>(TyPtr)) {
- if (NamedDecl *D = ObjCO->getInterface())
- DiagnoseDeclAvailability(D, Range);
- }
- return true;
- }
- bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) {
- VersionTuple CondVersion;
- if (auto *E = dyn_cast<ObjCAvailabilityCheckExpr>(If->getCond())) {
- CondVersion = E->getVersion();
- // If we're using the '*' case here or if this check is redundant, then we
- // use the enclosing version to check both branches.
- if (CondVersion.empty() || CondVersion <= AvailabilityStack.back())
- return TraverseStmt(If->getThen()) && TraverseStmt(If->getElse());
- } else {
- // This isn't an availability checking 'if', we can just continue.
- return Base::TraverseIfStmt(If);
- }
- AvailabilityStack.push_back(CondVersion);
- bool ShouldContinue = TraverseStmt(If->getThen());
- AvailabilityStack.pop_back();
- return ShouldContinue && TraverseStmt(If->getElse());
- }
- } // end anonymous namespace
- void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) {
- Stmt *Body = nullptr;
- if (auto *FD = D->getAsFunction()) {
- // FIXME: We only examine the pattern decl for availability violations now,
- // but we should also examine instantiated templates.
- if (FD->isTemplateInstantiation())
- return;
- Body = FD->getBody();
- } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
- Body = MD->getBody();
- else if (auto *BD = dyn_cast<BlockDecl>(D))
- Body = BD->getBody();
- assert(Body && "Need a body here!");
- DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body);
- }
- void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
- ArrayRef<SourceLocation> Locs,
- const ObjCInterfaceDecl *UnknownObjCClass,
- bool ObjCPropertyAccess,
- bool AvoidPartialAvailabilityChecks,
- ObjCInterfaceDecl *ClassReceiver) {
- std::string Message;
- AvailabilityResult Result;
- const NamedDecl* OffendingDecl;
- // See if this declaration is unavailable, deprecated, or partial.
- std::tie(Result, OffendingDecl) =
- ShouldDiagnoseAvailabilityOfDecl(*this, D, &Message, ClassReceiver);
- if (Result == AR_Available)
- return;
- if (Result == AR_NotYetIntroduced) {
- if (AvoidPartialAvailabilityChecks)
- return;
- // We need to know the @available context in the current function to
- // diagnose this use, let DiagnoseUnguardedAvailabilityViolations do that
- // when we're done parsing the current function.
- if (getCurFunctionOrMethodDecl()) {
- getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
- return;
- } else if (getCurBlock() || getCurLambda()) {
- getCurFunction()->HasPotentialAvailabilityViolations = true;
- return;
- }
- }
- const ObjCPropertyDecl *ObjCPDecl = nullptr;
- if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
- AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
- if (PDeclResult == Result)
- ObjCPDecl = PD;
- }
- }
- EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Locs,
- UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess);
- }
|