12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003 |
- //===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements type-related semantic analysis.
- //
- //===----------------------------------------------------------------------===//
- #include "TypeLocBuilder.h"
- #include "clang/AST/ASTConsumer.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/ASTMutationListener.h"
- #include "clang/AST/ASTStructuralEquivalence.h"
- #include "clang/AST/CXXInheritance.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/Expr.h"
- #include "clang/AST/TypeLoc.h"
- #include "clang/AST/TypeLocVisitor.h"
- #include "clang/Basic/PartialDiagnostic.h"
- #include "clang/Basic/TargetInfo.h"
- #include "clang/Lex/Preprocessor.h"
- #include "clang/Sema/DeclSpec.h"
- #include "clang/Sema/DelayedDiagnostic.h"
- #include "clang/Sema/Lookup.h"
- #include "clang/Sema/ScopeInfo.h"
- #include "clang/Sema/SemaInternal.h"
- #include "clang/Sema/Template.h"
- #include "clang/Sema/TemplateInstCallback.h"
- #include "llvm/ADT/SmallPtrSet.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/StringSwitch.h"
- #include "llvm/Support/ErrorHandling.h"
- using namespace clang;
- enum TypeDiagSelector {
- TDS_Function,
- TDS_Pointer,
- TDS_ObjCObjOrBlock
- };
- /// isOmittedBlockReturnType - Return true if this declarator is missing a
- /// return type because this is a omitted return type on a block literal.
- static bool isOmittedBlockReturnType(const Declarator &D) {
- if (D.getContext() != DeclaratorContext::BlockLiteralContext ||
- D.getDeclSpec().hasTypeSpecifier())
- return false;
- if (D.getNumTypeObjects() == 0)
- return true; // ^{ ... }
- if (D.getNumTypeObjects() == 1 &&
- D.getTypeObject(0).Kind == DeclaratorChunk::Function)
- return true; // ^(int X, float Y) { ... }
- return false;
- }
- /// diagnoseBadTypeAttribute - Diagnoses a type attribute which
- /// doesn't apply to the given type.
- static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
- QualType type) {
- TypeDiagSelector WhichType;
- bool useExpansionLoc = true;
- switch (attr.getKind()) {
- case AttributeList::AT_ObjCGC: WhichType = TDS_Pointer; break;
- case AttributeList::AT_ObjCOwnership: WhichType = TDS_ObjCObjOrBlock; break;
- default:
- // Assume everything else was a function attribute.
- WhichType = TDS_Function;
- useExpansionLoc = false;
- break;
- }
- SourceLocation loc = attr.getLoc();
- StringRef name = attr.getName()->getName();
- // The GC attributes are usually written with macros; special-case them.
- IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident
- : nullptr;
- if (useExpansionLoc && loc.isMacroID() && II) {
- if (II->isStr("strong")) {
- if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
- } else if (II->isStr("weak")) {
- if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
- }
- }
- S.Diag(loc, diag::warn_type_attribute_wrong_type) << name << WhichType
- << type;
- }
- // objc_gc applies to Objective-C pointers or, otherwise, to the
- // smallest available pointer type (i.e. 'void*' in 'void**').
- #define OBJC_POINTER_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_ObjCGC: \
- case AttributeList::AT_ObjCOwnership
- // Calling convention attributes.
- #define CALLING_CONV_ATTRS_CASELIST \
- case AttributeList::AT_CDecl: \
- case AttributeList::AT_FastCall: \
- case AttributeList::AT_StdCall: \
- case AttributeList::AT_ThisCall: \
- case AttributeList::AT_RegCall: \
- case AttributeList::AT_Pascal: \
- case AttributeList::AT_SwiftCall: \
- case AttributeList::AT_VectorCall: \
- case AttributeList::AT_MSABI: \
- case AttributeList::AT_SysVABI: \
- case AttributeList::AT_Pcs: \
- case AttributeList::AT_IntelOclBicc: \
- case AttributeList::AT_PreserveMost: \
- case AttributeList::AT_PreserveAll
- // Function type attributes.
- #define FUNCTION_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_NSReturnsRetained: \
- case AttributeList::AT_NoReturn: \
- case AttributeList::AT_Regparm: \
- case AttributeList::AT_AnyX86NoCallerSavedRegisters: \
- CALLING_CONV_ATTRS_CASELIST
- // Microsoft-specific type qualifiers.
- #define MS_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_Ptr32: \
- case AttributeList::AT_Ptr64: \
- case AttributeList::AT_SPtr: \
- case AttributeList::AT_UPtr
- // Nullability qualifiers.
- #define NULLABILITY_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_TypeNonNull: \
- case AttributeList::AT_TypeNullable: \
- case AttributeList::AT_TypeNullUnspecified
- namespace {
- /// An object which stores processing state for the entire
- /// GetTypeForDeclarator process.
- class TypeProcessingState {
- Sema &sema;
- /// The declarator being processed.
- Declarator &declarator;
- /// The index of the declarator chunk we're currently processing.
- /// May be the total number of valid chunks, indicating the
- /// DeclSpec.
- unsigned chunkIndex;
- /// Whether there are non-trivial modifications to the decl spec.
- bool trivial;
- /// Whether we saved the attributes in the decl spec.
- bool hasSavedAttrs;
- /// The original set of attributes on the DeclSpec.
- SmallVector<AttributeList*, 2> savedAttrs;
- /// A list of attributes to diagnose the uselessness of when the
- /// processing is complete.
- SmallVector<AttributeList*, 2> ignoredTypeAttrs;
- public:
- TypeProcessingState(Sema &sema, Declarator &declarator)
- : sema(sema), declarator(declarator),
- chunkIndex(declarator.getNumTypeObjects()),
- trivial(true), hasSavedAttrs(false) {}
- Sema &getSema() const {
- return sema;
- }
- Declarator &getDeclarator() const {
- return declarator;
- }
- bool isProcessingDeclSpec() const {
- return chunkIndex == declarator.getNumTypeObjects();
- }
- unsigned getCurrentChunkIndex() const {
- return chunkIndex;
- }
- void setCurrentChunkIndex(unsigned idx) {
- assert(idx <= declarator.getNumTypeObjects());
- chunkIndex = idx;
- }
- AttributeList *&getCurrentAttrListRef() const {
- if (isProcessingDeclSpec())
- return getMutableDeclSpec().getAttributes().getListRef();
- return declarator.getTypeObject(chunkIndex).getAttrListRef();
- }
- /// Save the current set of attributes on the DeclSpec.
- void saveDeclSpecAttrs() {
- // Don't try to save them multiple times.
- if (hasSavedAttrs) return;
- DeclSpec &spec = getMutableDeclSpec();
- for (AttributeList *attr = spec.getAttributes().getList(); attr;
- attr = attr->getNext())
- savedAttrs.push_back(attr);
- trivial &= savedAttrs.empty();
- hasSavedAttrs = true;
- }
- /// Record that we had nowhere to put the given type attribute.
- /// We will diagnose such attributes later.
- void addIgnoredTypeAttr(AttributeList &attr) {
- ignoredTypeAttrs.push_back(&attr);
- }
- /// Diagnose all the ignored type attributes, given that the
- /// declarator worked out to the given type.
- void diagnoseIgnoredTypeAttrs(QualType type) const {
- for (auto *Attr : ignoredTypeAttrs)
- diagnoseBadTypeAttribute(getSema(), *Attr, type);
- }
- ~TypeProcessingState() {
- if (trivial) return;
- restoreDeclSpecAttrs();
- }
- private:
- DeclSpec &getMutableDeclSpec() const {
- return const_cast<DeclSpec&>(declarator.getDeclSpec());
- }
- void restoreDeclSpecAttrs() {
- assert(hasSavedAttrs);
- if (savedAttrs.empty()) {
- getMutableDeclSpec().getAttributes().set(nullptr);
- return;
- }
- getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
- for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
- savedAttrs[i]->setNext(savedAttrs[i+1]);
- savedAttrs.back()->setNext(nullptr);
- }
- };
- } // end anonymous namespace
- static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
- attr.setNext(head);
- head = &attr;
- }
- static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
- if (head == &attr) {
- head = attr.getNext();
- return;
- }
- AttributeList *cur = head;
- while (true) {
- assert(cur && cur->getNext() && "ran out of attrs?");
- if (cur->getNext() == &attr) {
- cur->setNext(attr.getNext());
- return;
- }
- cur = cur->getNext();
- }
- }
- static void moveAttrFromListToList(AttributeList &attr,
- AttributeList *&fromList,
- AttributeList *&toList) {
- spliceAttrOutOfList(attr, fromList);
- spliceAttrIntoList(attr, toList);
- }
- /// The location of a type attribute.
- enum TypeAttrLocation {
- /// The attribute is in the decl-specifier-seq.
- TAL_DeclSpec,
- /// The attribute is part of a DeclaratorChunk.
- TAL_DeclChunk,
- /// The attribute is immediately after the declaration's name.
- TAL_DeclName
- };
- static void processTypeAttrs(TypeProcessingState &state,
- QualType &type, TypeAttrLocation TAL,
- AttributeList *attrs);
- static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type);
- static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type);
- static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
- static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
- static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type) {
- if (attr.getKind() == AttributeList::AT_ObjCGC)
- return handleObjCGCTypeAttr(state, attr, type);
- assert(attr.getKind() == AttributeList::AT_ObjCOwnership);
- return handleObjCOwnershipTypeAttr(state, attr, type);
- }
- /// Given the index of a declarator chunk, check whether that chunk
- /// directly specifies the return type of a function and, if so, find
- /// an appropriate place for it.
- ///
- /// \param i - a notional index which the search will start
- /// immediately inside
- ///
- /// \param onlyBlockPointers Whether we should only look into block
- /// pointer types (vs. all pointer types).
- static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
- unsigned i,
- bool onlyBlockPointers) {
- assert(i <= declarator.getNumTypeObjects());
- DeclaratorChunk *result = nullptr;
- // First, look inwards past parens for a function declarator.
- for (; i != 0; --i) {
- DeclaratorChunk &fnChunk = declarator.getTypeObject(i-1);
- switch (fnChunk.Kind) {
- case DeclaratorChunk::Paren:
- continue;
- // If we find anything except a function, bail out.
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- return result;
- // If we do find a function declarator, scan inwards from that,
- // looking for a (block-)pointer declarator.
- case DeclaratorChunk::Function:
- for (--i; i != 0; --i) {
- DeclaratorChunk &ptrChunk = declarator.getTypeObject(i-1);
- switch (ptrChunk.Kind) {
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Function:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Pipe:
- continue;
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pointer:
- if (onlyBlockPointers)
- continue;
- LLVM_FALLTHROUGH;
- case DeclaratorChunk::BlockPointer:
- result = &ptrChunk;
- goto continue_outer;
- }
- llvm_unreachable("bad declarator chunk kind");
- }
- // If we run out of declarators doing that, we're done.
- return result;
- }
- llvm_unreachable("bad declarator chunk kind");
- // Okay, reconsider from our new point.
- continue_outer: ;
- }
- // Ran out of chunks, bail out.
- return result;
- }
- /// Given that an objc_gc attribute was written somewhere on a
- /// declaration *other* than on the declarator itself (for which, use
- /// distributeObjCPointerTypeAttrFromDeclarator), and given that it
- /// didn't apply in whatever position it was written in, try to move
- /// it to a more appropriate position.
- static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
- Declarator &declarator = state.getDeclarator();
- // Move it to the outermost normal or block pointer declarator.
- for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
- switch (chunk.Kind) {
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer: {
- // But don't move an ARC ownership attribute to the return type
- // of a block.
- DeclaratorChunk *destChunk = nullptr;
- if (state.isProcessingDeclSpec() &&
- attr.getKind() == AttributeList::AT_ObjCOwnership)
- destChunk = maybeMovePastReturnType(declarator, i - 1,
- /*onlyBlockPointers=*/true);
- if (!destChunk) destChunk = &chunk;
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- destChunk->getAttrListRef());
- return;
- }
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Array:
- continue;
- // We may be starting at the return type of a block.
- case DeclaratorChunk::Function:
- if (state.isProcessingDeclSpec() &&
- attr.getKind() == AttributeList::AT_ObjCOwnership) {
- if (DeclaratorChunk *dest = maybeMovePastReturnType(
- declarator, i,
- /*onlyBlockPointers=*/true)) {
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- dest->getAttrListRef());
- return;
- }
- }
- goto error;
- // Don't walk through these.
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- goto error;
- }
- }
- error:
- diagnoseBadTypeAttribute(state.getSema(), attr, type);
- }
- /// Distribute an objc_gc type attribute that was written on the
- /// declarator.
- static void
- distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // objc_gc goes on the innermost pointer to something that's not a
- // pointer.
- unsigned innermost = -1U;
- bool considerDeclSpec = true;
- for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i);
- switch (chunk.Kind) {
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- innermost = i;
- continue;
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Pipe:
- continue;
- case DeclaratorChunk::Function:
- considerDeclSpec = false;
- goto done;
- }
- }
- done:
- // That might actually be the decl spec if we weren't blocked by
- // anything in the declarator.
- if (considerDeclSpec) {
- if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
- // Splice the attribute into the decl spec. Prevents the
- // attribute from being applied multiple times and gives
- // the source-location-filler something to work with.
- state.saveDeclSpecAttrs();
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getMutableDeclSpec().getAttributes().getListRef());
- return;
- }
- }
- // Otherwise, if we found an appropriate chunk, splice the attribute
- // into it.
- if (innermost != -1U) {
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getTypeObject(innermost).getAttrListRef());
- return;
- }
- // Otherwise, diagnose when we're done building the type.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
- state.addIgnoredTypeAttr(attr);
- }
- /// A function type attribute was written somewhere in a declaration
- /// *other* than on the declarator itself or in the decl spec. Given
- /// that it didn't apply in whatever position it was written in, try
- /// to move it to a more appropriate position.
- static void distributeFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
- Declarator &declarator = state.getDeclarator();
- // Try to push the attribute from the return type of a function to
- // the function itself.
- for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
- switch (chunk.Kind) {
- case DeclaratorChunk::Function:
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
- return;
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- continue;
- }
- }
- diagnoseBadTypeAttribute(state.getSema(), attr, type);
- }
- /// Try to distribute a function type attribute to the innermost
- /// function chunk or type. Returns true if the attribute was
- /// distributed, false if no location was found.
- static bool
- distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
- AttributeList &attr,
- AttributeList *&attrList,
- QualType &declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // Put it on the innermost function chunk, if there is one.
- for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i);
- if (chunk.Kind != DeclaratorChunk::Function) continue;
- moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
- return true;
- }
- return handleFunctionTypeAttr(state, attr, declSpecType);
- }
- /// A function type attribute was written in the decl spec. Try to
- /// apply it somewhere.
- static void
- distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
- state.saveDeclSpecAttrs();
- // C++11 attributes before the decl specifiers actually appertain to
- // the declarators. Move them straight there. We don't support the
- // 'put them wherever you like' semantics we allow for GNU attributes.
- if (attr.isCXX11Attribute()) {
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- state.getDeclarator().getAttrListRef());
- return;
- }
- // Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- state.getCurrentAttrListRef(),
- declSpecType))
- return;
- // If that failed, diagnose the bad attribute when the declarator is
- // fully built.
- state.addIgnoredTypeAttr(attr);
- }
- /// A function type attribute was written on the declarator. Try to
- /// apply it somewhere.
- static void
- distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- declarator.getAttrListRef(),
- declSpecType))
- return;
- // If that failed, diagnose the bad attribute when the declarator is
- // fully built.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
- state.addIgnoredTypeAttr(attr);
- }
- /// \brief Given that there are attributes written on the declarator
- /// itself, try to distribute any type attributes to the appropriate
- /// declarator chunk.
- ///
- /// These are attributes like the following:
- /// int f ATTR;
- /// int (f ATTR)();
- /// but not necessarily this:
- /// int f() ATTR;
- static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
- QualType &declSpecType) {
- // Collect all the type attributes from the declarator itself.
- assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
- AttributeList *attr = state.getDeclarator().getAttributes();
- AttributeList *next;
- do {
- next = attr->getNext();
- // Do not distribute C++11 attributes. They have strict rules for what
- // they appertain to.
- if (attr->isCXX11Attribute())
- continue;
- switch (attr->getKind()) {
- OBJC_POINTER_TYPE_ATTRS_CASELIST:
- distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
- break;
- FUNCTION_TYPE_ATTRS_CASELIST:
- distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
- break;
- MS_TYPE_ATTRS_CASELIST:
- // Microsoft type attributes cannot go after the declarator-id.
- continue;
- NULLABILITY_TYPE_ATTRS_CASELIST:
- // Nullability specifiers cannot go after the declarator-id.
- // Objective-C __kindof does not get distributed.
- case AttributeList::AT_ObjCKindOf:
- continue;
- default:
- break;
- }
- } while ((attr = next));
- }
- /// Add a synthetic '()' to a block-literal declarator if it is
- /// required, given the return type.
- static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
- QualType declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // First, check whether the declarator would produce a function,
- // i.e. whether the innermost semantic chunk is a function.
- if (declarator.isFunctionDeclarator()) {
- // If so, make that declarator a prototyped declarator.
- declarator.getFunctionTypeInfo().hasPrototype = true;
- return;
- }
- // If there are any type objects, the type as written won't name a
- // function, regardless of the decl spec type. This is because a
- // block signature declarator is always an abstract-declarator, and
- // abstract-declarators can't just be parentheses chunks. Therefore
- // we need to build a function chunk unless there are no type
- // objects and the decl spec type is a function.
- if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
- return;
- // Note that there *are* cases with invalid declarators where
- // declarators consist solely of parentheses. In general, these
- // occur only in failed efforts to make function declarators, so
- // faking up the function chunk is still the right thing to do.
- // Otherwise, we need to fake up a function declarator.
- SourceLocation loc = declarator.getLocStart();
- // ...and *prepend* it to the declarator.
- SourceLocation NoLoc;
- declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
- /*HasProto=*/true,
- /*IsAmbiguous=*/false,
- /*LParenLoc=*/NoLoc,
- /*ArgInfo=*/nullptr,
- /*NumArgs=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc, EST_None,
- /*ESpecRange=*/SourceRange(),
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- /*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- loc, loc, declarator));
- // For consistency, make sure the state still has us as processing
- // the decl spec.
- assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
- state.setCurrentChunkIndex(declarator.getNumTypeObjects());
- }
- static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
- unsigned &TypeQuals,
- QualType TypeSoFar,
- unsigned RemoveTQs,
- unsigned DiagID) {
- // If this occurs outside a template instantiation, warn the user about
- // it; they probably didn't mean to specify a redundant qualifier.
- typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
- for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
- QualLoc(DeclSpec::TQ_restrict, DS.getRestrictSpecLoc()),
- QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
- QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) {
- if (!(RemoveTQs & Qual.first))
- continue;
- if (!S.inTemplateInstantiation()) {
- if (TypeQuals & Qual.first)
- S.Diag(Qual.second, DiagID)
- << DeclSpec::getSpecifierName(Qual.first) << TypeSoFar
- << FixItHint::CreateRemoval(Qual.second);
- }
- TypeQuals &= ~Qual.first;
- }
- }
- /// Return true if this is omitted block return type. Also check type
- /// attributes and type qualifiers when returning true.
- static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
- QualType Result) {
- if (!isOmittedBlockReturnType(declarator))
- return false;
- // Warn if we see type attributes for omitted return type on a block literal.
- AttributeList *&attrs =
- declarator.getMutableDeclSpec().getAttributes().getListRef();
- AttributeList *prev = nullptr;
- for (AttributeList *cur = attrs; cur; cur = cur->getNext()) {
- AttributeList &attr = *cur;
- // Skip attributes that were marked to be invalid or non-type
- // attributes.
- if (attr.isInvalid() || !attr.isTypeAttr()) {
- prev = cur;
- continue;
- }
- S.Diag(attr.getLoc(),
- diag::warn_block_literal_attributes_on_omitted_return_type)
- << attr.getName();
- // Remove cur from the list.
- if (prev) {
- prev->setNext(cur->getNext());
- prev = cur;
- } else {
- attrs = cur->getNext();
- }
- }
- // Warn if we see type qualifiers for omitted return type on a block literal.
- const DeclSpec &DS = declarator.getDeclSpec();
- unsigned TypeQuals = DS.getTypeQualifiers();
- diagnoseAndRemoveTypeQualifiers(S, DS, TypeQuals, Result, (unsigned)-1,
- diag::warn_block_literal_qualifiers_on_omitted_return_type);
- declarator.getMutableDeclSpec().ClearTypeQualifiers();
- return true;
- }
- /// Apply Objective-C type arguments to the given type.
- static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
- ArrayRef<TypeSourceInfo *> typeArgs,
- SourceRange typeArgsRange,
- bool failOnError = false) {
- // We can only apply type arguments to an Objective-C class type.
- const auto *objcObjectType = type->getAs<ObjCObjectType>();
- if (!objcObjectType || !objcObjectType->getInterface()) {
- S.Diag(loc, diag::err_objc_type_args_non_class)
- << type
- << typeArgsRange;
- if (failOnError)
- return QualType();
- return type;
- }
- // The class type must be parameterized.
- ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
- ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
- if (!typeParams) {
- S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
- << objcClass->getDeclName()
- << FixItHint::CreateRemoval(typeArgsRange);
- if (failOnError)
- return QualType();
- return type;
- }
- // The type must not already be specialized.
- if (objcObjectType->isSpecialized()) {
- S.Diag(loc, diag::err_objc_type_args_specialized_class)
- << type
- << FixItHint::CreateRemoval(typeArgsRange);
- if (failOnError)
- return QualType();
- return type;
- }
- // Check the type arguments.
- SmallVector<QualType, 4> finalTypeArgs;
- unsigned numTypeParams = typeParams->size();
- bool anyPackExpansions = false;
- for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {
- TypeSourceInfo *typeArgInfo = typeArgs[i];
- QualType typeArg = typeArgInfo->getType();
- // Type arguments cannot have explicit qualifiers or nullability.
- // We ignore indirect sources of these, e.g. behind typedefs or
- // template arguments.
- if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {
- bool diagnosed = false;
- SourceRange rangeToRemove;
- if (auto attr = qual.getAs<AttributedTypeLoc>()) {
- rangeToRemove = attr.getLocalSourceRange();
- if (attr.getTypePtr()->getImmediateNullability()) {
- typeArg = attr.getTypePtr()->getModifiedType();
- S.Diag(attr.getLocStart(),
- diag::err_objc_type_arg_explicit_nullability)
- << typeArg << FixItHint::CreateRemoval(rangeToRemove);
- diagnosed = true;
- }
- }
- if (!diagnosed) {
- S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified)
- << typeArg << typeArg.getQualifiers().getAsString()
- << FixItHint::CreateRemoval(rangeToRemove);
- }
- }
- // Remove qualifiers even if they're non-local.
- typeArg = typeArg.getUnqualifiedType();
- finalTypeArgs.push_back(typeArg);
- if (typeArg->getAs<PackExpansionType>())
- anyPackExpansions = true;
- // Find the corresponding type parameter, if there is one.
- ObjCTypeParamDecl *typeParam = nullptr;
- if (!anyPackExpansions) {
- if (i < numTypeParams) {
- typeParam = typeParams->begin()[i];
- } else {
- // Too many arguments.
- S.Diag(loc, diag::err_objc_type_args_wrong_arity)
- << false
- << objcClass->getDeclName()
- << (unsigned)typeArgs.size()
- << numTypeParams;
- S.Diag(objcClass->getLocation(), diag::note_previous_decl)
- << objcClass;
- if (failOnError)
- return QualType();
- return type;
- }
- }
- // Objective-C object pointer types must be substitutable for the bounds.
- if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {
- // If we don't have a type parameter to match against, assume
- // everything is fine. There was a prior pack expansion that
- // means we won't be able to match anything.
- if (!typeParam) {
- assert(anyPackExpansions && "Too many arguments?");
- continue;
- }
- // Retrieve the bound.
- QualType bound = typeParam->getUnderlyingType();
- const auto *boundObjC = bound->getAs<ObjCObjectPointerType>();
- // Determine whether the type argument is substitutable for the bound.
- if (typeArgObjC->isObjCIdType()) {
- // When the type argument is 'id', the only acceptable type
- // parameter bound is 'id'.
- if (boundObjC->isObjCIdType())
- continue;
- } else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
- // Otherwise, we follow the assignability rules.
- continue;
- }
- // Diagnose the mismatch.
- S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
- diag::err_objc_type_arg_does_not_match_bound)
- << typeArg << bound << typeParam->getDeclName();
- S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
- << typeParam->getDeclName();
- if (failOnError)
- return QualType();
- return type;
- }
- // Block pointer types are permitted for unqualified 'id' bounds.
- if (typeArg->isBlockPointerType()) {
- // If we don't have a type parameter to match against, assume
- // everything is fine. There was a prior pack expansion that
- // means we won't be able to match anything.
- if (!typeParam) {
- assert(anyPackExpansions && "Too many arguments?");
- continue;
- }
- // Retrieve the bound.
- QualType bound = typeParam->getUnderlyingType();
- if (bound->isBlockCompatibleObjCPointerType(S.Context))
- continue;
- // Diagnose the mismatch.
- S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
- diag::err_objc_type_arg_does_not_match_bound)
- << typeArg << bound << typeParam->getDeclName();
- S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
- << typeParam->getDeclName();
- if (failOnError)
- return QualType();
- return type;
- }
- // Dependent types will be checked at instantiation time.
- if (typeArg->isDependentType()) {
- continue;
- }
- // Diagnose non-id-compatible type arguments.
- S.Diag(typeArgInfo->getTypeLoc().getLocStart(),
- diag::err_objc_type_arg_not_id_compatible)
- << typeArg
- << typeArgInfo->getTypeLoc().getSourceRange();
- if (failOnError)
- return QualType();
- return type;
- }
- // Make sure we didn't have the wrong number of arguments.
- if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) {
- S.Diag(loc, diag::err_objc_type_args_wrong_arity)
- << (typeArgs.size() < typeParams->size())
- << objcClass->getDeclName()
- << (unsigned)finalTypeArgs.size()
- << (unsigned)numTypeParams;
- S.Diag(objcClass->getLocation(), diag::note_previous_decl)
- << objcClass;
- if (failOnError)
- return QualType();
- return type;
- }
- // Success. Form the specialized type.
- return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false);
- }
- QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc,
- bool FailOnError) {
- QualType Result = QualType(Decl->getTypeForDecl(), 0);
- if (!Protocols.empty()) {
- bool HasError;
- Result = Context.applyObjCProtocolQualifiers(Result, Protocols,
- HasError);
- if (HasError) {
- Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers)
- << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
- if (FailOnError) Result = QualType();
- }
- if (FailOnError && Result.isNull())
- return QualType();
- }
- return Result;
- }
- QualType Sema::BuildObjCObjectType(QualType BaseType,
- SourceLocation Loc,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<TypeSourceInfo *> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc,
- bool FailOnError) {
- QualType Result = BaseType;
- if (!TypeArgs.empty()) {
- Result = applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
- SourceRange(TypeArgsLAngleLoc,
- TypeArgsRAngleLoc),
- FailOnError);
- if (FailOnError && Result.isNull())
- return QualType();
- }
- if (!Protocols.empty()) {
- bool HasError;
- Result = Context.applyObjCProtocolQualifiers(Result, Protocols,
- HasError);
- if (HasError) {
- Diag(Loc, diag::err_invalid_protocol_qualifiers)
- << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
- if (FailOnError) Result = QualType();
- }
- if (FailOnError && Result.isNull())
- return QualType();
- }
- return Result;
- }
- TypeResult Sema::actOnObjCProtocolQualifierType(
- SourceLocation lAngleLoc,
- ArrayRef<Decl *> protocols,
- ArrayRef<SourceLocation> protocolLocs,
- SourceLocation rAngleLoc) {
- // Form id<protocol-list>.
- QualType Result = Context.getObjCObjectType(
- Context.ObjCBuiltinIdTy, { },
- llvm::makeArrayRef(
- (ObjCProtocolDecl * const *)protocols.data(),
- protocols.size()),
- false);
- Result = Context.getObjCObjectPointerType(Result);
- TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
- TypeLoc ResultTL = ResultTInfo->getTypeLoc();
- auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>();
- ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit
- auto ObjCObjectTL = ObjCObjectPointerTL.getPointeeLoc()
- .castAs<ObjCObjectTypeLoc>();
- ObjCObjectTL.setHasBaseTypeAsWritten(false);
- ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation());
- // No type arguments.
- ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
- ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
- // Fill in protocol qualifiers.
- ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc);
- ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc);
- for (unsigned i = 0, n = protocols.size(); i != n; ++i)
- ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]);
- // We're done. Return the completed type to the parser.
- return CreateParsedType(Result, ResultTInfo);
- }
- TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
- Scope *S,
- SourceLocation Loc,
- ParsedType BaseType,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<ParsedType> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<Decl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc) {
- TypeSourceInfo *BaseTypeInfo = nullptr;
- QualType T = GetTypeFromParser(BaseType, &BaseTypeInfo);
- if (T.isNull())
- return true;
- // Handle missing type-source info.
- if (!BaseTypeInfo)
- BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc);
- // Extract type arguments.
- SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos;
- for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) {
- TypeSourceInfo *TypeArgInfo = nullptr;
- QualType TypeArg = GetTypeFromParser(TypeArgs[i], &TypeArgInfo);
- if (TypeArg.isNull()) {
- ActualTypeArgInfos.clear();
- break;
- }
- assert(TypeArgInfo && "No type source info?");
- ActualTypeArgInfos.push_back(TypeArgInfo);
- }
- // Build the object type.
- QualType Result = BuildObjCObjectType(
- T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
- TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
- ProtocolLAngleLoc,
- llvm::makeArrayRef((ObjCProtocolDecl * const *)Protocols.data(),
- Protocols.size()),
- ProtocolLocs, ProtocolRAngleLoc,
- /*FailOnError=*/false);
- if (Result == T)
- return BaseType;
- // Create source information for this type.
- TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
- TypeLoc ResultTL = ResultTInfo->getTypeLoc();
- // For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an
- // object pointer type. Fill in source information for it.
- if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) {
- // The '*' is implicit.
- ObjCObjectPointerTL.setStarLoc(SourceLocation());
- ResultTL = ObjCObjectPointerTL.getPointeeLoc();
- }
- if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {
- // Protocol qualifier information.
- if (OTPTL.getNumProtocols() > 0) {
- assert(OTPTL.getNumProtocols() == Protocols.size());
- OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
- OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
- for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
- OTPTL.setProtocolLoc(i, ProtocolLocs[i]);
- }
- // We're done. Return the completed type to the parser.
- return CreateParsedType(Result, ResultTInfo);
- }
- auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();
- // Type argument information.
- if (ObjCObjectTL.getNumTypeArgs() > 0) {
- assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size());
- ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc);
- ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc);
- for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i)
- ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]);
- } else {
- ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
- ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
- }
- // Protocol qualifier information.
- if (ObjCObjectTL.getNumProtocols() > 0) {
- assert(ObjCObjectTL.getNumProtocols() == Protocols.size());
- ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
- ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
- for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
- ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]);
- } else {
- ObjCObjectTL.setProtocolLAngleLoc(SourceLocation());
- ObjCObjectTL.setProtocolRAngleLoc(SourceLocation());
- }
- // Base type.
- ObjCObjectTL.setHasBaseTypeAsWritten(true);
- if (ObjCObjectTL.getType() == T)
- ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc());
- else
- ObjCObjectTL.getBaseLoc().initialize(Context, Loc);
- // We're done. Return the completed type to the parser.
- return CreateParsedType(Result, ResultTInfo);
- }
- static OpenCLAccessAttr::Spelling getImageAccess(const AttributeList *Attrs) {
- if (Attrs) {
- const AttributeList *Next = Attrs;
- do {
- const AttributeList &Attr = *Next;
- Next = Attr.getNext();
- if (Attr.getKind() == AttributeList::AT_OpenCLAccess) {
- return static_cast<OpenCLAccessAttr::Spelling>(
- Attr.getSemanticSpelling());
- }
- } while (Next);
- }
- return OpenCLAccessAttr::Keyword_read_only;
- }
- /// \brief Convert the specified declspec to the appropriate type
- /// object.
- /// \param state Specifies the declarator containing the declaration specifier
- /// to be converted, along with other associated processing state.
- /// \returns The type described by the declaration specifiers. This function
- /// never returns null.
- static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
- // FIXME: Should move the logic from DeclSpec::Finish to here for validity
- // checking.
- Sema &S = state.getSema();
- Declarator &declarator = state.getDeclarator();
- const DeclSpec &DS = declarator.getDeclSpec();
- SourceLocation DeclLoc = declarator.getIdentifierLoc();
- if (DeclLoc.isInvalid())
- DeclLoc = DS.getLocStart();
- ASTContext &Context = S.Context;
- QualType Result;
- switch (DS.getTypeSpecType()) {
- case DeclSpec::TST_void:
- Result = Context.VoidTy;
- break;
- case DeclSpec::TST_char:
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
- Result = Context.CharTy;
- else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
- Result = Context.SignedCharTy;
- else {
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
- "Unknown TSS value");
- Result = Context.UnsignedCharTy;
- }
- break;
- case DeclSpec::TST_wchar:
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
- Result = Context.WCharTy;
- else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
- S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType(),
- Context.getPrintingPolicy());
- Result = Context.getSignedWCharType();
- } else {
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
- "Unknown TSS value");
- S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType(),
- Context.getPrintingPolicy());
- Result = Context.getUnsignedWCharType();
- }
- break;
- case DeclSpec::TST_char16:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char16Ty;
- break;
- case DeclSpec::TST_char32:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char32Ty;
- break;
- case DeclSpec::TST_unspecified:
- // If this is a missing declspec in a block literal return context, then it
- // is inferred from the return statements inside the block.
- // The declspec is always missing in a lambda expr context; it is either
- // specified with a trailing return type or inferred.
- if (S.getLangOpts().CPlusPlus14 &&
- declarator.getContext() == DeclaratorContext::LambdaExprContext) {
- // In C++1y, a lambda's implicit return type is 'auto'.
- Result = Context.getAutoDeductType();
- break;
- } else if (declarator.getContext() ==
- DeclaratorContext::LambdaExprContext ||
- checkOmittedBlockReturnType(S, declarator,
- Context.DependentTy)) {
- Result = Context.DependentTy;
- break;
- }
- // Unspecified typespec defaults to int in C90. However, the C90 grammar
- // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
- // type-qualifier, or storage-class-specifier. If not, emit an extwarn.
- // Note that the one exception to this is function definitions, which are
- // allowed to be completely missing a declspec. This is handled in the
- // parser already though by it pretending to have seen an 'int' in this
- // case.
- if (S.getLangOpts().ImplicitInt) {
- // In C89 mode, we only warn if there is a completely missing declspec
- // when one is not allowed.
- if (DS.isEmpty()) {
- S.Diag(DeclLoc, diag::ext_missing_declspec)
- << DS.getSourceRange()
- << FixItHint::CreateInsertion(DS.getLocStart(), "int");
- }
- } else if (!DS.hasTypeSpecifier()) {
- // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says:
- // "At least one type specifier shall be given in the declaration
- // specifiers in each declaration, and in the specifier-qualifier list in
- // each struct declaration and type name."
- if (S.getLangOpts().CPlusPlus) {
- S.Diag(DeclLoc, diag::err_missing_type_specifier)
- << DS.getSourceRange();
- // When this occurs in C++ code, often something is very broken with the
- // value being declared, poison it as invalid so we don't get chains of
- // errors.
- declarator.setInvalidType(true);
- } else if (S.getLangOpts().OpenCLVersion >= 200 && DS.isTypeSpecPipe()){
- S.Diag(DeclLoc, diag::err_missing_actual_pipe_type)
- << DS.getSourceRange();
- declarator.setInvalidType(true);
- } else {
- S.Diag(DeclLoc, diag::ext_missing_type_specifier)
- << DS.getSourceRange();
- }
- }
- LLVM_FALLTHROUGH;
- case DeclSpec::TST_int: {
- if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
- switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
- case DeclSpec::TSW_short: Result = Context.ShortTy; break;
- case DeclSpec::TSW_long: Result = Context.LongTy; break;
- case DeclSpec::TSW_longlong:
- Result = Context.LongLongTy;
- // 'long long' is a C99 or C++11 feature.
- if (!S.getLangOpts().C99) {
- if (S.getLangOpts().CPlusPlus)
- S.Diag(DS.getTypeSpecWidthLoc(),
- S.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
- else
- S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
- }
- break;
- }
- } else {
- switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
- case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
- case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
- case DeclSpec::TSW_longlong:
- Result = Context.UnsignedLongLongTy;
- // 'long long' is a C99 or C++11 feature.
- if (!S.getLangOpts().C99) {
- if (S.getLangOpts().CPlusPlus)
- S.Diag(DS.getTypeSpecWidthLoc(),
- S.getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
- else
- S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
- }
- break;
- }
- }
- break;
- }
- case DeclSpec::TST_int128:
- if (!S.Context.getTargetInfo().hasInt128Type())
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
- << "__int128";
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
- Result = Context.UnsignedInt128Ty;
- else
- Result = Context.Int128Ty;
- break;
- case DeclSpec::TST_float16: Result = Context.Float16Ty; break;
- case DeclSpec::TST_half: Result = Context.HalfTy; break;
- case DeclSpec::TST_float: Result = Context.FloatTy; break;
- case DeclSpec::TST_double:
- if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
- Result = Context.LongDoubleTy;
- else
- Result = Context.DoubleTy;
- break;
- case DeclSpec::TST_float128:
- if (!S.Context.getTargetInfo().hasFloat128Type())
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
- << "__float128";
- Result = Context.Float128Ty;
- break;
- case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
- break;
- case DeclSpec::TST_decimal32: // _Decimal32
- case DeclSpec::TST_decimal64: // _Decimal64
- case DeclSpec::TST_decimal128: // _Decimal128
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- break;
- case DeclSpec::TST_class:
- case DeclSpec::TST_enum:
- case DeclSpec::TST_union:
- case DeclSpec::TST_struct:
- case DeclSpec::TST_interface: {
- TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
- if (!D) {
- // This can happen in C++ with ambiguous lookups.
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- break;
- }
- // If the type is deprecated or unavailable, diagnose it.
- S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
- assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
- // TypeQuals handled by caller.
- Result = Context.getTypeDeclType(D);
- // In both C and C++, make an ElaboratedType.
- ElaboratedTypeKeyword Keyword
- = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
- Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
- break;
- }
- case DeclSpec::TST_typename: {
- assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 &&
- "Can't handle qualifiers on typedef names yet!");
- Result = S.GetTypeFromParser(DS.getRepAsType());
- if (Result.isNull()) {
- declarator.setInvalidType(true);
- }
- // TypeQuals handled by caller.
- break;
- }
- case DeclSpec::TST_typeofType:
- // FIXME: Preserve type source info.
- Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for typeof?");
- if (!Result->isDependentType())
- if (const TagType *TT = Result->getAs<TagType>())
- S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
- // TypeQuals handled by caller.
- Result = Context.getTypeOfType(Result);
- break;
- case DeclSpec::TST_typeofExpr: {
- Expr *E = DS.getRepAsExpr();
- assert(E && "Didn't get an expression for typeof?");
- // TypeQuals handled by caller.
- Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- }
- case DeclSpec::TST_decltype: {
- Expr *E = DS.getRepAsExpr();
- assert(E && "Didn't get an expression for decltype?");
- // TypeQuals handled by caller.
- Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- }
- case DeclSpec::TST_underlyingType:
- Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
- Result = S.BuildUnaryTransformType(Result,
- UnaryTransformType::EnumUnderlyingType,
- DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- case DeclSpec::TST_auto:
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
- break;
- case DeclSpec::TST_auto_type:
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false);
- break;
- case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto,
- /*IsDependent*/ false);
- break;
- case DeclSpec::TST_unknown_anytype:
- Result = Context.UnknownAnyTy;
- break;
- case DeclSpec::TST_atomic:
- Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for _Atomic?");
- Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- #define GENERIC_IMAGE_TYPE(ImgType, Id) \
- case DeclSpec::TST_##ImgType##_t: \
- switch (getImageAccess(DS.getAttributes().getList())) { \
- case OpenCLAccessAttr::Keyword_write_only: \
- Result = Context.Id##WOTy; break; \
- case OpenCLAccessAttr::Keyword_read_write: \
- Result = Context.Id##RWTy; break; \
- case OpenCLAccessAttr::Keyword_read_only: \
- Result = Context.Id##ROTy; break; \
- } \
- break;
- #include "clang/Basic/OpenCLImageTypes.def"
- case DeclSpec::TST_error:
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- break;
- }
- if (S.getLangOpts().OpenCL &&
- S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
- declarator.setInvalidType(true);
- // Handle complex types.
- if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
- if (S.getLangOpts().Freestanding)
- S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
- Result = Context.getComplexType(Result);
- } else if (DS.isTypeAltiVecVector()) {
- unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
- assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
- VectorType::VectorKind VecKind = VectorType::AltiVecVector;
- if (DS.isTypeAltiVecPixel())
- VecKind = VectorType::AltiVecPixel;
- else if (DS.isTypeAltiVecBool())
- VecKind = VectorType::AltiVecBool;
- Result = Context.getVectorType(Result, 128/typeSize, VecKind);
- }
- // FIXME: Imaginary.
- if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
- S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
- // Before we process any type attributes, synthesize a block literal
- // function declarator if necessary.
- if (declarator.getContext() == DeclaratorContext::BlockLiteralContext)
- maybeSynthesizeBlockSignature(state, Result);
- // Apply any type attributes from the decl spec. This may cause the
- // list of type attributes to be temporarily saved while the type
- // attributes are pushed around.
- // pipe attributes will be handled later ( at GetFullTypeForDeclarator )
- if (!DS.isTypeSpecPipe())
- processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
- // Apply const/volatile/restrict qualifiers to T.
- if (unsigned TypeQuals = DS.getTypeQualifiers()) {
- // Warn about CV qualifiers on function types.
- // C99 6.7.3p8:
- // If the specification of a function type includes any type qualifiers,
- // the behavior is undefined.
- // C++11 [dcl.fct]p7:
- // The effect of a cv-qualifier-seq in a function declarator is not the
- // same as adding cv-qualification on top of the function type. In the
- // latter case, the cv-qualifiers are ignored.
- if (TypeQuals && Result->isFunctionType()) {
- diagnoseAndRemoveTypeQualifiers(
- S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
- S.getLangOpts().CPlusPlus
- ? diag::warn_typecheck_function_qualifiers_ignored
- : diag::warn_typecheck_function_qualifiers_unspecified);
- // No diagnostic for 'restrict' or '_Atomic' applied to a
- // function type; we'll diagnose those later, in BuildQualifiedType.
- }
- // C++11 [dcl.ref]p1:
- // Cv-qualified references are ill-formed except when the
- // cv-qualifiers are introduced through the use of a typedef-name
- // or decltype-specifier, in which case the cv-qualifiers are ignored.
- //
- // There don't appear to be any other contexts in which a cv-qualified
- // reference type could be formed, so the 'ill-formed' clause here appears
- // to never happen.
- if (TypeQuals && Result->isReferenceType()) {
- diagnoseAndRemoveTypeQualifiers(
- S, DS, TypeQuals, Result,
- DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic,
- diag::warn_typecheck_reference_qualifiers);
- }
- // C90 6.5.3 constraints: "The same type qualifier shall not appear more
- // than once in the same specifier-list or qualifier-list, either directly
- // or via one or more typedefs."
- if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus
- && TypeQuals & Result.getCVRQualifiers()) {
- if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) {
- S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec)
- << "const";
- }
- if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) {
- S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec)
- << "volatile";
- }
- // C90 doesn't have restrict nor _Atomic, so it doesn't force us to
- // produce a warning in this case.
- }
- QualType Qualified = S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS);
- // If adding qualifiers fails, just use the unqualified type.
- if (Qualified.isNull())
- declarator.setInvalidType(true);
- else
- Result = Qualified;
- }
- assert(!Result.isNull() && "This function should not return a null type");
- return Result;
- }
- static std::string getPrintableNameForEntity(DeclarationName Entity) {
- if (Entity)
- return Entity.getAsString();
- return "type name";
- }
- QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
- Qualifiers Qs, const DeclSpec *DS) {
- if (T.isNull())
- return QualType();
- // Ignore any attempt to form a cv-qualified reference.
- if (T->isReferenceType()) {
- Qs.removeConst();
- Qs.removeVolatile();
- }
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from
- // object or incomplete types shall not be restrict-qualified."
- if (Qs.hasRestrict()) {
- unsigned DiagID = 0;
- QualType ProblemTy;
- if (T->isAnyPointerType() || T->isReferenceType() ||
- T->isMemberPointerType()) {
- QualType EltTy;
- if (T->isObjCObjectPointerType())
- EltTy = T;
- else if (const MemberPointerType *PTy = T->getAs<MemberPointerType>())
- EltTy = PTy->getPointeeType();
- else
- EltTy = T->getPointeeType();
- // If we have a pointer or reference, the pointee must have an object
- // incomplete type.
- if (!EltTy->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = EltTy;
- }
- } else if (!T->isDependentType()) {
- DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
- ProblemTy = T;
- }
- if (DiagID) {
- Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy;
- Qs.removeRestrict();
- }
- }
- return Context.getQualifiedType(T, Qs);
- }
- QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
- unsigned CVRAU, const DeclSpec *DS) {
- if (T.isNull())
- return QualType();
- // Ignore any attempt to form a cv-qualified reference.
- if (T->isReferenceType())
- CVRAU &=
- ~(DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic);
- // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic and
- // TQ_unaligned;
- unsigned CVR = CVRAU & ~(DeclSpec::TQ_atomic | DeclSpec::TQ_unaligned);
- // C11 6.7.3/5:
- // If the same qualifier appears more than once in the same
- // specifier-qualifier-list, either directly or via one or more typedefs,
- // the behavior is the same as if it appeared only once.
- //
- // It's not specified what happens when the _Atomic qualifier is applied to
- // a type specified with the _Atomic specifier, but we assume that this
- // should be treated as if the _Atomic qualifier appeared multiple times.
- if (CVRAU & DeclSpec::TQ_atomic && !T->isAtomicType()) {
- // C11 6.7.3/5:
- // If other qualifiers appear along with the _Atomic qualifier in a
- // specifier-qualifier-list, the resulting type is the so-qualified
- // atomic type.
- //
- // Don't need to worry about array types here, since _Atomic can't be
- // applied to such types.
- SplitQualType Split = T.getSplitUnqualifiedType();
- T = BuildAtomicType(QualType(Split.Ty, 0),
- DS ? DS->getAtomicSpecLoc() : Loc);
- if (T.isNull())
- return T;
- Split.Quals.addCVRQualifiers(CVR);
- return BuildQualifiedType(T, Loc, Split.Quals);
- }
- Qualifiers Q = Qualifiers::fromCVRMask(CVR);
- Q.setUnaligned(CVRAU & DeclSpec::TQ_unaligned);
- return BuildQualifiedType(T, Loc, Q, DS);
- }
- /// \brief Build a paren type including \p T.
- QualType Sema::BuildParenType(QualType T) {
- return Context.getParenType(T);
- }
- /// Given that we're building a pointer or reference to the given
- static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
- SourceLocation loc,
- bool isReference) {
- // Bail out if retention is unrequired or already specified.
- if (!type->isObjCLifetimeType() ||
- type.getObjCLifetime() != Qualifiers::OCL_None)
- return type;
- Qualifiers::ObjCLifetime implicitLifetime = Qualifiers::OCL_None;
- // If the object type is const-qualified, we can safely use
- // __unsafe_unretained. This is safe (because there are no read
- // barriers), and it'll be safe to coerce anything but __weak* to
- // the resulting type.
- if (type.isConstQualified()) {
- implicitLifetime = Qualifiers::OCL_ExplicitNone;
- // Otherwise, check whether the static type does not require
- // retaining. This currently only triggers for Class (possibly
- // protocol-qualifed, and arrays thereof).
- } else if (type->isObjCARCImplicitlyUnretainedType()) {
- implicitLifetime = Qualifiers::OCL_ExplicitNone;
- // If we are in an unevaluated context, like sizeof, skip adding a
- // qualification.
- } else if (S.isUnevaluatedContext()) {
- return type;
- // If that failed, give an error and recover using __strong. __strong
- // is the option most likely to prevent spurious second-order diagnostics,
- // like when binding a reference to a field.
- } else {
- // These types can show up in private ivars in system headers, so
- // we need this to not be an error in those cases. Instead we
- // want to delay.
- if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
- S.DelayedDiagnostics.add(
- sema::DelayedDiagnostic::makeForbiddenType(loc,
- diag::err_arc_indirect_no_ownership, type, isReference));
- } else {
- S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
- }
- implicitLifetime = Qualifiers::OCL_Strong;
- }
- assert(implicitLifetime && "didn't infer any lifetime!");
- Qualifiers qs;
- qs.addObjCLifetime(implicitLifetime);
- return S.Context.getQualifiedType(type, qs);
- }
- static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
- std::string Quals =
- Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
- switch (FnTy->getRefQualifier()) {
- case RQ_None:
- break;
- case RQ_LValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += '&';
- break;
- case RQ_RValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += "&&";
- break;
- }
- return Quals;
- }
- namespace {
- /// Kinds of declarator that cannot contain a qualified function type.
- ///
- /// C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6:
- /// a function type with a cv-qualifier or a ref-qualifier can only appear
- /// at the topmost level of a type.
- ///
- /// Parens and member pointers are permitted. We don't diagnose array and
- /// function declarators, because they don't allow function types at all.
- ///
- /// The values of this enum are used in diagnostics.
- enum QualifiedFunctionKind { QFK_BlockPointer, QFK_Pointer, QFK_Reference };
- } // end anonymous namespace
- /// Check whether the type T is a qualified function type, and if it is,
- /// diagnose that it cannot be contained within the given kind of declarator.
- static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
- QualifiedFunctionKind QFK) {
- // Does T refer to a function type with a cv-qualifier or a ref-qualifier?
- const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
- if (!FPT || (FPT->getTypeQuals() == 0 && FPT->getRefQualifier() == RQ_None))
- return false;
- S.Diag(Loc, diag::err_compound_qualified_function_type)
- << QFK << isa<FunctionType>(T.IgnoreParens()) << T
- << getFunctionQualifiersAsString(FPT);
- return true;
- }
- /// \brief Build a pointer type.
- ///
- /// \param T The type to which we'll be building a pointer.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// pointer type or, if there is no such entity, the location of the
- /// type that will have pointer type.
- ///
- /// \param Entity The name of the entity that involves the pointer
- /// type, if known.
- ///
- /// \returns A suitable pointer type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildPointerType(QualType T,
- SourceLocation Loc, DeclarationName Entity) {
- if (T->isReferenceType()) {
- // C++ 8.3.2p4: There shall be no ... pointers to references ...
- Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- if (T->isFunctionType() && getLangOpts().OpenCL) {
- Diag(Loc, diag::err_opencl_function_pointer);
- return QualType();
- }
- if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer))
- return QualType();
- assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
- // In ARC, it is forbidden to build pointers to unqualified pointers.
- if (getLangOpts().ObjCAutoRefCount)
- T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
- // Build the pointer type.
- return Context.getPointerType(T);
- }
- /// \brief Build a reference type.
- ///
- /// \param T The type to which we'll be building a reference.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// reference type or, if there is no such entity, the location of the
- /// type that will have reference type.
- ///
- /// \param Entity The name of the entity that involves the reference
- /// type, if known.
- ///
- /// \returns A suitable reference type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
- SourceLocation Loc,
- DeclarationName Entity) {
- assert(Context.getCanonicalType(T) != Context.OverloadTy &&
- "Unresolved overloaded function type");
- // C++0x [dcl.ref]p6:
- // If a typedef (7.1.3), a type template-parameter (14.3.1), or a
- // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a
- // type T, an attempt to create the type "lvalue reference to cv TR" creates
- // the type "lvalue reference to T", while an attempt to create the type
- // "rvalue reference to cv TR" creates the type TR.
- bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
- // C++ [dcl.ref]p4: There shall be no references to references.
- //
- // According to C++ DR 106, references to references are only
- // diagnosed when they are written directly (e.g., "int & &"),
- // but not when they happen via a typedef:
- //
- // typedef int& intref;
- // typedef intref& intref2;
- //
- // Parser::ParseDeclaratorInternal diagnoses the case where
- // references are written directly; here, we handle the
- // collapsing of references-to-references as described in C++0x.
- // DR 106 and 540 introduce reference-collapsing into C++98/03.
- // C++ [dcl.ref]p1:
- // A declarator that specifies the type "reference to cv void"
- // is ill-formed.
- if (T->isVoidType()) {
- Diag(Loc, diag::err_reference_to_void);
- return QualType();
- }
- if (checkQualifiedFunction(*this, T, Loc, QFK_Reference))
- return QualType();
- // In ARC, it is forbidden to build references to unqualified pointers.
- if (getLangOpts().ObjCAutoRefCount)
- T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
- // Handle restrict on references.
- if (LValueRef)
- return Context.getLValueReferenceType(T, SpelledAsLValue);
- return Context.getRValueReferenceType(T);
- }
- /// \brief Build a Read-only Pipe type.
- ///
- /// \param T The type to which we'll be building a Pipe.
- ///
- /// \param Loc We do not use it for now.
- ///
- /// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
- /// NULL type.
- QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) {
- return Context.getReadPipeType(T);
- }
- /// \brief Build a Write-only Pipe type.
- ///
- /// \param T The type to which we'll be building a Pipe.
- ///
- /// \param Loc We do not use it for now.
- ///
- /// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
- /// NULL type.
- QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) {
- return Context.getWritePipeType(T);
- }
- /// Check whether the specified array size makes the array type a VLA. If so,
- /// return true, if not, return the size of the array in SizeVal.
- static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
- // If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
- // (like gnu99, but not c99) accept any evaluatable value as an extension.
- class VLADiagnoser : public Sema::VerifyICEDiagnoser {
- public:
- VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
- void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
- }
- void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) override {
- S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
- }
- } Diagnoser;
- return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
- S.LangOpts.GNUMode ||
- S.LangOpts.OpenCL).isInvalid();
- }
- /// \brief Build an array type.
- ///
- /// \param T The type of each element in the array.
- ///
- /// \param ASM C99 array size modifier (e.g., '*', 'static').
- ///
- /// \param ArraySize Expression describing the size of the array.
- ///
- /// \param Brackets The range from the opening '[' to the closing ']'.
- ///
- /// \param Entity The name of the entity that involves the array
- /// type, if known.
- ///
- /// \returns A suitable array type, if there are no errors. Otherwise,
- /// returns a NULL type.
- QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
- Expr *ArraySize, unsigned Quals,
- SourceRange Brackets, DeclarationName Entity) {
- SourceLocation Loc = Brackets.getBegin();
- if (getLangOpts().CPlusPlus) {
- // C++ [dcl.array]p1:
- // T is called the array element type; this type shall not be a reference
- // type, the (possibly cv-qualified) type void, a function type or an
- // abstract class type.
- //
- // C++ [dcl.array]p3:
- // When several "array of" specifications are adjacent, [...] only the
- // first of the constant expressions that specify the bounds of the arrays
- // may be omitted.
- //
- // Note: function types are handled in the common path with C.
- if (T->isReferenceType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_references)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- if (T->isVoidType() || T->isIncompleteArrayType()) {
- Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
- return QualType();
- }
- if (RequireNonAbstractType(Brackets.getBegin(), T,
- diag::err_array_of_abstract_type))
- return QualType();
- // Mentioning a member pointer type for an array type causes us to lock in
- // an inheritance model, even if it's inside an unused typedef.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
- if (!MPTy->getClass()->isDependentType())
- (void)isCompleteType(Loc, T);
- } else {
- // C99 6.7.5.2p1: If the element type is an incomplete or function type,
- // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- if (RequireCompleteType(Loc, T,
- diag::err_illegal_decl_array_incomplete_type))
- return QualType();
- }
- if (T->isFunctionType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_functions)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- if (const RecordType *EltTy = T->getAs<RecordType>()) {
- // If the element type is a struct or union that contains a variadic
- // array, accept it as a GNU extension: C99 6.7.2.1p2.
- if (EltTy->getDecl()->hasFlexibleArrayMember())
- Diag(Loc, diag::ext_flexible_array_in_array) << T;
- } else if (T->isObjCObjectType()) {
- Diag(Loc, diag::err_objc_array_of_interfaces) << T;
- return QualType();
- }
- // Do placeholder conversions on the array size expression.
- if (ArraySize && ArraySize->hasPlaceholderType()) {
- ExprResult Result = CheckPlaceholderExpr(ArraySize);
- if (Result.isInvalid()) return QualType();
- ArraySize = Result.get();
- }
- // Do lvalue-to-rvalue conversions on the array size expression.
- if (ArraySize && !ArraySize->isRValue()) {
- ExprResult Result = DefaultLvalueConversion(ArraySize);
- if (Result.isInvalid())
- return QualType();
- ArraySize = Result.get();
- }
- // C99 6.7.5.2p1: The size expression shall have integer type.
- // C++11 allows contextual conversions to such types.
- if (!getLangOpts().CPlusPlus11 &&
- ArraySize && !ArraySize->isTypeDependent() &&
- !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
- Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
- << ArraySize->getType() << ArraySize->getSourceRange();
- return QualType();
- }
- llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
- if (!ArraySize) {
- if (ASM == ArrayType::Star)
- T = Context.getVariableArrayType(T, nullptr, ASM, Quals, Brackets);
- else
- T = Context.getIncompleteArrayType(T, ASM, Quals);
- } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
- T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else if ((!T->isDependentType() && !T->isIncompleteType() &&
- !T->isConstantSizeType()) ||
- isArraySizeVLA(*this, ArraySize, ConstVal)) {
- // Even in C++11, don't allow contextual conversions in the array bound
- // of a VLA.
- if (getLangOpts().CPlusPlus11 &&
- !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
- Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
- << ArraySize->getType() << ArraySize->getSourceRange();
- return QualType();
- }
- // C99: an array with an element type that has a non-constant-size is a VLA.
- // C99: an array with a non-ICE size is a VLA. We accept any expression
- // that we can fold to a non-zero positive value as an extension.
- T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else {
- // C99 6.7.5.2p1: If the expression is a constant expression, it shall
- // have a value greater than zero.
- if (ConstVal.isSigned() && ConstVal.isNegative()) {
- if (Entity)
- Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
- << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
- else
- Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange();
- return QualType();
- }
- if (ConstVal == 0) {
- // GCC accepts zero sized static arrays. We allow them when
- // we're not in a SFINAE context.
- Diag(ArraySize->getLocStart(),
- isSFINAEContext()? diag::err_typecheck_zero_array_size
- : diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
- if (ASM == ArrayType::Static) {
- Diag(ArraySize->getLocStart(),
- diag::warn_typecheck_zero_static_array_size)
- << ArraySize->getSourceRange();
- ASM = ArrayType::Normal;
- }
- } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType() && !T->isUndeducedType()) {
- // Is the array too large?
- unsigned ActiveSizeBits
- = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
- if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
- Diag(ArraySize->getLocStart(), diag::err_array_too_large)
- << ConstVal.toString(10)
- << ArraySize->getSourceRange();
- return QualType();
- }
- }
- T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
- }
- // OpenCL v1.2 s6.9.d: variable length arrays are not supported.
- if (getLangOpts().OpenCL && T->isVariableArrayType()) {
- Diag(Loc, diag::err_opencl_vla);
- return QualType();
- }
- if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) {
- if (getLangOpts().CUDA) {
- // CUDA device code doesn't support VLAs.
- CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget();
- } else if (!getLangOpts().OpenMP ||
- shouldDiagnoseTargetSupportFromOpenMP()) {
- // Some targets don't support VLAs.
- Diag(Loc, diag::err_vla_unsupported);
- return QualType();
- }
- }
- // If this is not C99, extwarn about VLA's and C99 array size modifiers.
- if (!getLangOpts().C99) {
- if (T->isVariableArrayType()) {
- // Prohibit the use of VLAs during template argument deduction.
- if (isSFINAEContext()) {
- Diag(Loc, diag::err_vla_in_sfinae);
- return QualType();
- }
- // Just extwarn about VLAs.
- else
- Diag(Loc, diag::ext_vla);
- } else if (ASM != ArrayType::Normal || Quals != 0)
- Diag(Loc,
- getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
- : diag::ext_c99_array_usage) << ASM;
- }
- if (T->isVariableArrayType()) {
- // Warn about VLAs for -Wvla.
- Diag(Loc, diag::warn_vla_used);
- }
- // OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
- // OpenCL v2.0 s6.16.13.1 - Arrays of pipe type are not supported.
- // OpenCL v2.0 s6.9.b - Arrays of image/sampler type are not supported.
- if (getLangOpts().OpenCL) {
- const QualType ArrType = Context.getBaseElementType(T);
- if (ArrType->isBlockPointerType() || ArrType->isPipeType() ||
- ArrType->isSamplerT() || ArrType->isImageType()) {
- Diag(Loc, diag::err_opencl_invalid_type_array) << ArrType;
- return QualType();
- }
- }
- return T;
- }
- /// \brief Build an ext-vector type.
- ///
- /// Run the required checks for the extended vector type.
- QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
- SourceLocation AttrLoc) {
- // Unlike gcc's vector_size attribute, we do not allow vectors to be defined
- // in conjunction with complex types (pointers, arrays, functions, etc.).
- //
- // Additionally, OpenCL prohibits vectors of booleans (they're considered a
- // reserved data type under OpenCL v2.0 s6.1.4), we don't support selects
- // on bitvectors, and we have no well-defined ABI for bitvectors, so vectors
- // of bool aren't allowed.
- if ((!T->isDependentType() && !T->isIntegerType() &&
- !T->isRealFloatingType()) ||
- T->isBooleanType()) {
- Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
- return QualType();
- }
- if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
- llvm::APSInt vecSize(32);
- if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
- Diag(AttrLoc, diag::err_attribute_argument_type)
- << "ext_vector_type" << AANT_ArgumentIntegerConstant
- << ArraySize->getSourceRange();
- return QualType();
- }
- // Unlike gcc's vector_size attribute, the size is specified as the
- // number of elements, not the number of bytes.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
- if (vectorSize == 0) {
- Diag(AttrLoc, diag::err_attribute_zero_size)
- << ArraySize->getSourceRange();
- return QualType();
- }
- if (VectorType::isVectorSizeTooLarge(vectorSize)) {
- Diag(AttrLoc, diag::err_attribute_size_too_large)
- << ArraySize->getSourceRange();
- return QualType();
- }
- return Context.getExtVectorType(T, vectorSize);
- }
- return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
- }
- bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
- if (T->isArrayType() || T->isFunctionType()) {
- Diag(Loc, diag::err_func_returning_array_function)
- << T->isFunctionType() << T;
- return true;
- }
- // Functions cannot return half FP.
- if (T->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
- Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
- FixItHint::CreateInsertion(Loc, "*");
- return true;
- }
- // Methods cannot return interface types. All ObjC objects are
- // passed by reference.
- if (T->isObjCObjectType()) {
- Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value)
- << 0 << T << FixItHint::CreateInsertion(Loc, "*");
- return true;
- }
- return false;
- }
- /// Check the extended parameter information. Most of the necessary
- /// checking should occur when applying the parameter attribute; the
- /// only other checks required are positional restrictions.
- static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
- const FunctionProtoType::ExtProtoInfo &EPI,
- llvm::function_ref<SourceLocation(unsigned)> getParamLoc) {
- assert(EPI.ExtParameterInfos && "shouldn't get here without param infos");
- bool hasCheckedSwiftCall = false;
- auto checkForSwiftCC = [&](unsigned paramIndex) {
- // Only do this once.
- if (hasCheckedSwiftCall) return;
- hasCheckedSwiftCall = true;
- if (EPI.ExtInfo.getCC() == CC_Swift) return;
- S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall)
- << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI());
- };
- for (size_t paramIndex = 0, numParams = paramTypes.size();
- paramIndex != numParams; ++paramIndex) {
- switch (EPI.ExtParameterInfos[paramIndex].getABI()) {
- // Nothing interesting to check for orindary-ABI parameters.
- case ParameterABI::Ordinary:
- continue;
- // swift_indirect_result parameters must be a prefix of the function
- // arguments.
- case ParameterABI::SwiftIndirectResult:
- checkForSwiftCC(paramIndex);
- if (paramIndex != 0 &&
- EPI.ExtParameterInfos[paramIndex - 1].getABI()
- != ParameterABI::SwiftIndirectResult) {
- S.Diag(getParamLoc(paramIndex),
- diag::err_swift_indirect_result_not_first);
- }
- continue;
- case ParameterABI::SwiftContext:
- checkForSwiftCC(paramIndex);
- continue;
- // swift_error parameters must be preceded by a swift_context parameter.
- case ParameterABI::SwiftErrorResult:
- checkForSwiftCC(paramIndex);
- if (paramIndex == 0 ||
- EPI.ExtParameterInfos[paramIndex - 1].getABI() !=
- ParameterABI::SwiftContext) {
- S.Diag(getParamLoc(paramIndex),
- diag::err_swift_error_result_not_after_swift_context);
- }
- continue;
- }
- llvm_unreachable("bad ABI kind");
- }
- }
- QualType Sema::BuildFunctionType(QualType T,
- MutableArrayRef<QualType> ParamTypes,
- SourceLocation Loc, DeclarationName Entity,
- const FunctionProtoType::ExtProtoInfo &EPI) {
- bool Invalid = false;
- Invalid |= CheckFunctionReturnType(T, Loc);
- for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {
- // FIXME: Loc is too inprecise here, should use proper locations for args.
- QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
- if (ParamType->isVoidType()) {
- Diag(Loc, diag::err_param_with_void_type);
- Invalid = true;
- } else if (ParamType->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
- // Disallow half FP arguments.
- Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
- FixItHint::CreateInsertion(Loc, "*");
- Invalid = true;
- }
- ParamTypes[Idx] = ParamType;
- }
- if (EPI.ExtParameterInfos) {
- checkExtParameterInfos(*this, ParamTypes, EPI,
- [=](unsigned i) { return Loc; });
- }
- if (EPI.ExtInfo.getProducesResult()) {
- // This is just a warning, so we can't fail to build if we see it.
- checkNSReturnsRetainedReturnType(Loc, T);
- }
- if (Invalid)
- return QualType();
- return Context.getFunctionType(T, ParamTypes, EPI);
- }
- /// \brief Build a member pointer type \c T Class::*.
- ///
- /// \param T the type to which the member pointer refers.
- /// \param Class the class type into which the member pointer points.
- /// \param Loc the location where this type begins
- /// \param Entity the name of the entity that will have this member pointer type
- ///
- /// \returns a member pointer type, if successful, or a NULL type if there was
- /// an error.
- QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
- SourceLocation Loc,
- DeclarationName Entity) {
- // Verify that we're not building a pointer to pointer to function with
- // exception specification.
- if (CheckDistantExceptionSpec(T)) {
- Diag(Loc, diag::err_distant_exception_spec);
- return QualType();
- }
- // C++ 8.3.3p3: A pointer to member shall not point to ... a member
- // with reference type, or "cv void."
- if (T->isReferenceType()) {
- Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- if (T->isVoidType()) {
- Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
- << getPrintableNameForEntity(Entity);
- return QualType();
- }
- if (!Class->isDependentType() && !Class->isRecordType()) {
- Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
- return QualType();
- }
- // Adjust the default free function calling convention to the default method
- // calling convention.
- bool IsCtorOrDtor =
- (Entity.getNameKind() == DeclarationName::CXXConstructorName) ||
- (Entity.getNameKind() == DeclarationName::CXXDestructorName);
- if (T->isFunctionType())
- adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc);
- return Context.getMemberPointerType(T, Class.getTypePtr());
- }
- /// \brief Build a block pointer type.
- ///
- /// \param T The type to which we'll be building a block pointer.
- ///
- /// \param Loc The source location, used for diagnostics.
- ///
- /// \param Entity The name of the entity that involves the block pointer
- /// type, if known.
- ///
- /// \returns A suitable block pointer type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildBlockPointerType(QualType T,
- SourceLocation Loc,
- DeclarationName Entity) {
- if (!T->isFunctionType()) {
- Diag(Loc, diag::err_nonfunction_block_type);
- return QualType();
- }
- if (checkQualifiedFunction(*this, T, Loc, QFK_BlockPointer))
- return QualType();
- return Context.getBlockPointerType(T);
- }
- QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
- QualType QT = Ty.get();
- if (QT.isNull()) {
- if (TInfo) *TInfo = nullptr;
- return QualType();
- }
- TypeSourceInfo *DI = nullptr;
- if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
- QT = LIT->getType();
- DI = LIT->getTypeSourceInfo();
- }
- if (TInfo) *TInfo = DI;
- return QT;
- }
- static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
- Qualifiers::ObjCLifetime ownership,
- unsigned chunkIndex);
- /// Given that this is the declaration of a parameter under ARC,
- /// attempt to infer attributes and such for pointer-to-whatever
- /// types.
- static void inferARCWriteback(TypeProcessingState &state,
- QualType &declSpecType) {
- Sema &S = state.getSema();
- Declarator &declarator = state.getDeclarator();
- // TODO: should we care about decl qualifiers?
- // Check whether the declarator has the expected form. We walk
- // from the inside out in order to make the block logic work.
- unsigned outermostPointerIndex = 0;
- bool isBlockPointer = false;
- unsigned numPointers = 0;
- for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
- unsigned chunkIndex = i;
- DeclaratorChunk &chunk = declarator.getTypeObject(chunkIndex);
- switch (chunk.Kind) {
- case DeclaratorChunk::Paren:
- // Ignore parens.
- break;
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Pointer:
- // Count the number of pointers. Treat references
- // interchangeably as pointers; if they're mis-ordered, normal
- // type building will discover that.
- outermostPointerIndex = chunkIndex;
- numPointers++;
- break;
- case DeclaratorChunk::BlockPointer:
- // If we have a pointer to block pointer, that's an acceptable
- // indirect reference; anything else is not an application of
- // the rules.
- if (numPointers != 1) return;
- numPointers++;
- outermostPointerIndex = chunkIndex;
- isBlockPointer = true;
- // We don't care about pointer structure in return values here.
- goto done;
- case DeclaratorChunk::Array: // suppress if written (id[])?
- case DeclaratorChunk::Function:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- return;
- }
- }
- done:
- // If we have *one* pointer, then we want to throw the qualifier on
- // the declaration-specifiers, which means that it needs to be a
- // retainable object type.
- if (numPointers == 1) {
- // If it's not a retainable object type, the rule doesn't apply.
- if (!declSpecType->isObjCRetainableType()) return;
- // If it already has lifetime, don't do anything.
- if (declSpecType.getObjCLifetime()) return;
- // Otherwise, modify the type in-place.
- Qualifiers qs;
- if (declSpecType->isObjCARCImplicitlyUnretainedType())
- qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
- else
- qs.addObjCLifetime(Qualifiers::OCL_Autoreleasing);
- declSpecType = S.Context.getQualifiedType(declSpecType, qs);
- // If we have *two* pointers, then we want to throw the qualifier on
- // the outermost pointer.
- } else if (numPointers == 2) {
- // If we don't have a block pointer, we need to check whether the
- // declaration-specifiers gave us something that will turn into a
- // retainable object pointer after we slap the first pointer on it.
- if (!isBlockPointer && !declSpecType->isObjCObjectType())
- return;
- // Look for an explicit lifetime attribute there.
- DeclaratorChunk &chunk = declarator.getTypeObject(outermostPointerIndex);
- if (chunk.Kind != DeclaratorChunk::Pointer &&
- chunk.Kind != DeclaratorChunk::BlockPointer)
- return;
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_ObjCOwnership)
- return;
- transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
- outermostPointerIndex);
- // Any other number of pointers/references does not trigger the rule.
- } else return;
- // TODO: mark whether we did this inference?
- }
- void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
- SourceLocation FallbackLoc,
- SourceLocation ConstQualLoc,
- SourceLocation VolatileQualLoc,
- SourceLocation RestrictQualLoc,
- SourceLocation AtomicQualLoc,
- SourceLocation UnalignedQualLoc) {
- if (!Quals)
- return;
- struct Qual {
- const char *Name;
- unsigned Mask;
- SourceLocation Loc;
- } const QualKinds[5] = {
- { "const", DeclSpec::TQ_const, ConstQualLoc },
- { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc },
- { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc },
- { "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc },
- { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc }
- };
- SmallString<32> QualStr;
- unsigned NumQuals = 0;
- SourceLocation Loc;
- FixItHint FixIts[5];
- // Build a string naming the redundant qualifiers.
- for (auto &E : QualKinds) {
- if (Quals & E.Mask) {
- if (!QualStr.empty()) QualStr += ' ';
- QualStr += E.Name;
- // If we have a location for the qualifier, offer a fixit.
- SourceLocation QualLoc = E.Loc;
- if (QualLoc.isValid()) {
- FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
- if (Loc.isInvalid() ||
- getSourceManager().isBeforeInTranslationUnit(QualLoc, Loc))
- Loc = QualLoc;
- }
- ++NumQuals;
- }
- }
- Diag(Loc.isInvalid() ? FallbackLoc : Loc, DiagID)
- << QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3];
- }
- // Diagnose pointless type qualifiers on the return type of a function.
- static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
- Declarator &D,
- unsigned FunctionChunkIndex) {
- if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) {
- // FIXME: TypeSourceInfo doesn't preserve location information for
- // qualifiers.
- S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
- RetTy.getLocalCVRQualifiers(),
- D.getIdentifierLoc());
- return;
- }
- for (unsigned OuterChunkIndex = FunctionChunkIndex + 1,
- End = D.getNumTypeObjects();
- OuterChunkIndex != End; ++OuterChunkIndex) {
- DeclaratorChunk &OuterChunk = D.getTypeObject(OuterChunkIndex);
- switch (OuterChunk.Kind) {
- case DeclaratorChunk::Paren:
- continue;
- case DeclaratorChunk::Pointer: {
- DeclaratorChunk::PointerTypeInfo &PTI = OuterChunk.Ptr;
- S.diagnoseIgnoredQualifiers(
- diag::warn_qual_return_type,
- PTI.TypeQuals,
- SourceLocation(),
- SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
- SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
- SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
- SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc),
- SourceLocation::getFromRawEncoding(PTI.UnalignedQualLoc));
- return;
- }
- case DeclaratorChunk::Function:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- // FIXME: We can't currently provide an accurate source location and a
- // fix-it hint for these.
- unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
- S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
- RetTy.getCVRQualifiers() | AtomicQual,
- D.getIdentifierLoc());
- return;
- }
- llvm_unreachable("unknown declarator chunk kind");
- }
- // If the qualifiers come from a conversion function type, don't diagnose
- // them -- they're not necessarily redundant, since such a conversion
- // operator can be explicitly called as "x.operator const int()".
- if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
- return;
- // Just parens all the way out to the decl specifiers. Diagnose any qualifiers
- // which are present there.
- S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
- D.getDeclSpec().getTypeQualifiers(),
- D.getIdentifierLoc(),
- D.getDeclSpec().getConstSpecLoc(),
- D.getDeclSpec().getVolatileSpecLoc(),
- D.getDeclSpec().getRestrictSpecLoc(),
- D.getDeclSpec().getAtomicSpecLoc(),
- D.getDeclSpec().getUnalignedSpecLoc());
- }
- static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
- TypeSourceInfo *&ReturnTypeInfo) {
- Sema &SemaRef = state.getSema();
- Declarator &D = state.getDeclarator();
- QualType T;
- ReturnTypeInfo = nullptr;
- // The TagDecl owned by the DeclSpec.
- TagDecl *OwnedTagDecl = nullptr;
- switch (D.getName().getKind()) {
- case UnqualifiedIdKind::IK_ImplicitSelfParam:
- case UnqualifiedIdKind::IK_OperatorFunctionId:
- case UnqualifiedIdKind::IK_Identifier:
- case UnqualifiedIdKind::IK_LiteralOperatorId:
- case UnqualifiedIdKind::IK_TemplateId:
- T = ConvertDeclSpecToType(state);
- if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
- OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- // Owned declaration is embedded in declarator.
- OwnedTagDecl->setEmbeddedInDeclarator(true);
- }
- break;
- case UnqualifiedIdKind::IK_ConstructorName:
- case UnqualifiedIdKind::IK_ConstructorTemplateId:
- case UnqualifiedIdKind::IK_DestructorName:
- // Constructors and destructors don't have return types. Use
- // "void" instead.
- T = SemaRef.Context.VoidTy;
- processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
- break;
- case UnqualifiedIdKind::IK_DeductionGuideName:
- // Deduction guides have a trailing return type and no type in their
- // decl-specifier sequence. Use a placeholder return type for now.
- T = SemaRef.Context.DependentTy;
- break;
- case UnqualifiedIdKind::IK_ConversionFunctionId:
- // The result type of a conversion function is the type that it
- // converts to.
- T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
- &ReturnTypeInfo);
- break;
- }
- if (D.getAttributes())
- distributeTypeAttrsFromDeclarator(state, T);
- // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- if (DeducedType *Deduced = T->getContainedDeducedType()) {
- AutoType *Auto = dyn_cast<AutoType>(Deduced);
- int Error = -1;
- // Is this a 'auto' or 'decltype(auto)' type (as opposed to __auto_type or
- // class template argument deduction)?
- bool IsCXXAutoType =
- (Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
- switch (D.getContext()) {
- case DeclaratorContext::LambdaExprContext:
- // Declared return type of a lambda-declarator is implicit and is always
- // 'auto'.
- break;
- case DeclaratorContext::ObjCParameterContext:
- case DeclaratorContext::ObjCResultContext:
- case DeclaratorContext::PrototypeContext:
- Error = 0;
- break;
- case DeclaratorContext::LambdaExprParameterContext:
- // In C++14, generic lambdas allow 'auto' in their parameters.
- if (!SemaRef.getLangOpts().CPlusPlus14 ||
- !Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
- Error = 16;
- else {
- // If auto is mentioned in a lambda parameter context, convert it to a
- // template parameter type.
- sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
- assert(LSI && "No LambdaScopeInfo on the stack!");
- const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
- const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
- const bool IsParameterPack = D.hasEllipsis();
- // Create the TemplateTypeParmDecl here to retrieve the corresponding
- // template parameter type. Template parameters are temporarily added
- // to the TU until the associated TemplateDecl is created.
- TemplateTypeParmDecl *CorrespondingTemplateParam =
- TemplateTypeParmDecl::Create(
- SemaRef.Context, SemaRef.Context.getTranslationUnitDecl(),
- /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
- TemplateParameterDepth, AutoParameterPosition,
- /*Identifier*/nullptr, false, IsParameterPack);
- LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
- // Replace the 'auto' in the function parameter with this invented
- // template type parameter.
- // FIXME: Retain some type sugar to indicate that this was written
- // as 'auto'.
- T = SemaRef.ReplaceAutoType(
- T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0));
- }
- break;
- case DeclaratorContext::MemberContext: {
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
- D.isFunctionDeclarator())
- break;
- bool Cxx = SemaRef.getLangOpts().CPlusPlus;
- switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
- case TTK_Enum: llvm_unreachable("unhandled tag kind");
- case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break;
- case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break;
- case TTK_Class: Error = 5; /* Class member */ break;
- case TTK_Interface: Error = 6; /* Interface member */ break;
- }
- if (D.getDeclSpec().isFriendSpecified())
- Error = 20; // Friend type
- break;
- }
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::ObjCCatchContext:
- Error = 7; // Exception declaration
- break;
- case DeclaratorContext::TemplateParamContext:
- if (isa<DeducedTemplateSpecializationType>(Deduced))
- Error = 19; // Template parameter
- else if (!SemaRef.getLangOpts().CPlusPlus17)
- Error = 8; // Template parameter (until C++17)
- break;
- case DeclaratorContext::BlockLiteralContext:
- Error = 9; // Block literal
- break;
- case DeclaratorContext::TemplateTypeArgContext:
- Error = 10; // Template type argument
- break;
- case DeclaratorContext::AliasDeclContext:
- case DeclaratorContext::AliasTemplateContext:
- Error = 12; // Type alias
- break;
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
- if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
- Error = 13; // Function return type
- break;
- case DeclaratorContext::ConversionIdContext:
- if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
- Error = 14; // conversion-type-id
- break;
- case DeclaratorContext::FunctionalCastContext:
- if (isa<DeducedTemplateSpecializationType>(Deduced))
- break;
- LLVM_FALLTHROUGH;
- case DeclaratorContext::TypeNameContext:
- Error = 15; // Generic
- break;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::ConditionContext:
- // FIXME: P0091R3 (erroneously) does not permit class template argument
- // deduction in conditions, for-init-statements, and other declarations
- // that are not simple-declarations.
- break;
- case DeclaratorContext::CXXNewContext:
- // FIXME: P0091R3 does not permit class template argument deduction here,
- // but we follow GCC and allow it anyway.
- if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced))
- Error = 17; // 'new' type
- break;
- case DeclaratorContext::KNRTypeListContext:
- Error = 18; // K&R function parameter
- break;
- }
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- Error = 11;
- // In Objective-C it is an error to use 'auto' on a function declarator
- // (and everywhere for '__auto_type').
- if (D.isFunctionDeclarator() &&
- (!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
- Error = 13;
- bool HaveTrailing = false;
- // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
- // contains a trailing return type. That is only legal at the outermost
- // level. Check all declarator chunks (outermost first) anyway, to give
- // better diagnostics.
- // We don't support '__auto_type' with trailing return types.
- // FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
- if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType &&
- D.hasTrailingReturnType()) {
- HaveTrailing = true;
- Error = -1;
- }
- SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
- if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
- AutoRange = D.getName().getSourceRange();
- if (Error != -1) {
- unsigned Kind;
- if (Auto) {
- switch (Auto->getKeyword()) {
- case AutoTypeKeyword::Auto: Kind = 0; break;
- case AutoTypeKeyword::DecltypeAuto: Kind = 1; break;
- case AutoTypeKeyword::GNUAutoType: Kind = 2; break;
- }
- } else {
- assert(isa<DeducedTemplateSpecializationType>(Deduced) &&
- "unknown auto type");
- Kind = 3;
- }
- auto *DTST = dyn_cast<DeducedTemplateSpecializationType>(Deduced);
- TemplateName TN = DTST ? DTST->getTemplateName() : TemplateName();
- SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
- << Kind << Error << (int)SemaRef.getTemplateNameKindForDiagnostics(TN)
- << QualType(Deduced, 0) << AutoRange;
- if (auto *TD = TN.getAsTemplateDecl())
- SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here);
- T = SemaRef.Context.IntTy;
- D.setInvalidType(true);
- } else if (!HaveTrailing) {
- // If there was a trailing return type, we already got
- // warn_cxx98_compat_trailing_return_type in the parser.
- SemaRef.Diag(AutoRange.getBegin(),
- diag::warn_cxx98_compat_auto_type_specifier)
- << AutoRange;
- }
- }
- if (SemaRef.getLangOpts().CPlusPlus &&
- OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
- // Check the contexts where C++ forbids the declaration of a new class
- // or enumeration in a type-specifier-seq.
- unsigned DiagID = 0;
- switch (D.getContext()) {
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
- // Class and enumeration definitions are syntactically not allowed in
- // trailing return types.
- llvm_unreachable("parser should not have allowed this");
- break;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::MemberContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::BlockLiteralContext:
- case DeclaratorContext::LambdaExprContext:
- // C++11 [dcl.type]p3:
- // A type-specifier-seq shall not define a class or enumeration unless
- // it appears in the type-id of an alias-declaration (7.1.3) that is not
- // the declaration of a template-declaration.
- case DeclaratorContext::AliasDeclContext:
- break;
- case DeclaratorContext::AliasTemplateContext:
- DiagID = diag::err_type_defined_in_alias_template;
- break;
- case DeclaratorContext::TypeNameContext:
- case DeclaratorContext::FunctionalCastContext:
- case DeclaratorContext::ConversionIdContext:
- case DeclaratorContext::TemplateParamContext:
- case DeclaratorContext::CXXNewContext:
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::ObjCCatchContext:
- case DeclaratorContext::TemplateTypeArgContext:
- DiagID = diag::err_type_defined_in_type_specifier;
- break;
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::LambdaExprParameterContext:
- case DeclaratorContext::ObjCParameterContext:
- case DeclaratorContext::ObjCResultContext:
- case DeclaratorContext::KNRTypeListContext:
- // C++ [dcl.fct]p6:
- // Types shall not be defined in return or parameter types.
- DiagID = diag::err_type_defined_in_param_type;
- break;
- case DeclaratorContext::ConditionContext:
- // C++ 6.4p2:
- // The type-specifier-seq shall not contain typedef and shall not declare
- // a new class or enumeration.
- DiagID = diag::err_type_defined_in_condition;
- break;
- }
- if (DiagID != 0) {
- SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
- }
- }
- assert(!T.isNull() && "This function should not return a null type");
- return T;
- }
- /// Produce an appropriate diagnostic for an ambiguity between a function
- /// declarator and a C++ direct-initializer.
- static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
- DeclaratorChunk &DeclType, QualType RT) {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- assert(FTI.isAmbiguous && "no direct-initializer / function ambiguity");
- // If the return type is void there is no ambiguity.
- if (RT->isVoidType())
- return;
- // An initializer for a non-class type can have at most one argument.
- if (!RT->isRecordType() && FTI.NumParams > 1)
- return;
- // An initializer for a reference must have exactly one argument.
- if (RT->isReferenceType() && FTI.NumParams != 1)
- return;
- // Only warn if this declarator is declaring a function at block scope, and
- // doesn't have a storage class (such as 'extern') specified.
- if (!D.isFunctionDeclarator() ||
- D.getFunctionDefinitionKind() != FDK_Declaration ||
- !S.CurContext->isFunctionOrMethod() ||
- D.getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_unspecified)
- return;
- // Inside a condition, a direct initializer is not permitted. We allow one to
- // be parsed in order to give better diagnostics in condition parsing.
- if (D.getContext() == DeclaratorContext::ConditionContext)
- return;
- SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
- S.Diag(DeclType.Loc,
- FTI.NumParams ? diag::warn_parens_disambiguated_as_function_declaration
- : diag::warn_empty_parens_are_function_decl)
- << ParenRange;
- // If the declaration looks like:
- // T var1,
- // f();
- // and name lookup finds a function named 'f', then the ',' was
- // probably intended to be a ';'.
- if (!D.isFirstDeclarator() && D.getIdentifier()) {
- FullSourceLoc Comma(D.getCommaLoc(), S.SourceMgr);
- FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr);
- if (Comma.getFileID() != Name.getFileID() ||
- Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) {
- LookupResult Result(S, D.getIdentifier(), SourceLocation(),
- Sema::LookupOrdinaryName);
- if (S.LookupName(Result, S.getCurScope()))
- S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
- << FixItHint::CreateReplacement(D.getCommaLoc(), ";")
- << D.getIdentifier();
- Result.suppressDiagnostics();
- }
- }
- if (FTI.NumParams > 0) {
- // For a declaration with parameters, eg. "T var(T());", suggest adding
- // parens around the first parameter to turn the declaration into a
- // variable declaration.
- SourceRange Range = FTI.Params[0].Param->getSourceRange();
- SourceLocation B = Range.getBegin();
- SourceLocation E = S.getLocForEndOfToken(Range.getEnd());
- // FIXME: Maybe we should suggest adding braces instead of parens
- // in C++11 for classes that don't have an initializer_list constructor.
- S.Diag(B, diag::note_additional_parens_for_variable_declaration)
- << FixItHint::CreateInsertion(B, "(")
- << FixItHint::CreateInsertion(E, ")");
- } else {
- // For a declaration without parameters, eg. "T var();", suggest replacing
- // the parens with an initializer to turn the declaration into a variable
- // declaration.
- const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
- // Empty parens mean value-initialization, and no parens mean
- // default initialization. These are equivalent if the default
- // constructor is user-provided or if zero-initialization is a
- // no-op.
- if (RD && RD->hasDefinition() &&
- (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor()))
- S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor)
- << FixItHint::CreateRemoval(ParenRange);
- else {
- std::string Init =
- S.getFixItZeroInitializerForType(RT, ParenRange.getBegin());
- if (Init.empty() && S.LangOpts.CPlusPlus11)
- Init = "{}";
- if (!Init.empty())
- S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize)
- << FixItHint::CreateReplacement(ParenRange, Init);
- }
- }
- }
- /// Produce an appropriate diagnostic for a declarator with top-level
- /// parentheses.
- static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
- DeclaratorChunk &Paren = D.getTypeObject(D.getNumTypeObjects() - 1);
- assert(Paren.Kind == DeclaratorChunk::Paren &&
- "do not have redundant top-level parentheses");
- // This is a syntactic check; we're not interested in cases that arise
- // during template instantiation.
- if (S.inTemplateInstantiation())
- return;
- // Check whether this could be intended to be a construction of a temporary
- // object in C++ via a function-style cast.
- bool CouldBeTemporaryObject =
- S.getLangOpts().CPlusPlus && D.isExpressionContext() &&
- !D.isInvalidType() && D.getIdentifier() &&
- D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
- (T->isRecordType() || T->isDependentType()) &&
- D.getDeclSpec().getTypeQualifiers() == 0 && D.isFirstDeclarator();
- bool StartsWithDeclaratorId = true;
- for (auto &C : D.type_objects()) {
- switch (C.Kind) {
- case DeclaratorChunk::Paren:
- if (&C == &Paren)
- continue;
- LLVM_FALLTHROUGH;
- case DeclaratorChunk::Pointer:
- StartsWithDeclaratorId = false;
- continue;
- case DeclaratorChunk::Array:
- if (!C.Arr.NumElts)
- CouldBeTemporaryObject = false;
- continue;
- case DeclaratorChunk::Reference:
- // FIXME: Suppress the warning here if there is no initializer; we're
- // going to give an error anyway.
- // We assume that something like 'T (&x) = y;' is highly likely to not
- // be intended to be a temporary object.
- CouldBeTemporaryObject = false;
- StartsWithDeclaratorId = false;
- continue;
- case DeclaratorChunk::Function:
- // In a new-type-id, function chunks require parentheses.
- if (D.getContext() == DeclaratorContext::CXXNewContext)
- return;
- // FIXME: "A(f())" deserves a vexing-parse warning, not just a
- // redundant-parens warning, but we don't know whether the function
- // chunk was syntactically valid as an expression here.
- CouldBeTemporaryObject = false;
- continue;
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- // These cannot appear in expressions.
- CouldBeTemporaryObject = false;
- StartsWithDeclaratorId = false;
- continue;
- }
- }
- // FIXME: If there is an initializer, assume that this is not intended to be
- // a construction of a temporary object.
- // Check whether the name has already been declared; if not, this is not a
- // function-style cast.
- if (CouldBeTemporaryObject) {
- LookupResult Result(S, D.getIdentifier(), SourceLocation(),
- Sema::LookupOrdinaryName);
- if (!S.LookupName(Result, S.getCurScope()))
- CouldBeTemporaryObject = false;
- Result.suppressDiagnostics();
- }
- SourceRange ParenRange(Paren.Loc, Paren.EndLoc);
- if (!CouldBeTemporaryObject) {
- // If we have A (::B), the parentheses affect the meaning of the program.
- // Suppress the warning in that case. Don't bother looking at the DeclSpec
- // here: even (e.g.) "int ::x" is visually ambiguous even though it's
- // formally unambiguous.
- if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) {
- for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS;
- NNS = NNS->getPrefix()) {
- if (NNS->getKind() == NestedNameSpecifier::Global)
- return;
- }
- }
- S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator)
- << ParenRange << FixItHint::CreateRemoval(Paren.Loc)
- << FixItHint::CreateRemoval(Paren.EndLoc);
- return;
- }
- S.Diag(Paren.Loc, diag::warn_parens_disambiguated_as_variable_declaration)
- << ParenRange << D.getIdentifier();
- auto *RD = T->getAsCXXRecordDecl();
- if (!RD || !RD->hasDefinition() || RD->hasNonTrivialDestructor())
- S.Diag(Paren.Loc, diag::note_raii_guard_add_name)
- << FixItHint::CreateInsertion(Paren.Loc, " varname") << T
- << D.getIdentifier();
- // FIXME: A cast to void is probably a better suggestion in cases where it's
- // valid (when there is no initializer and we're not in a condition).
- S.Diag(D.getLocStart(), diag::note_function_style_cast_add_parentheses)
- << FixItHint::CreateInsertion(D.getLocStart(), "(")
- << FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getLocEnd()), ")");
- S.Diag(Paren.Loc, diag::note_remove_parens_for_variable_declaration)
- << FixItHint::CreateRemoval(Paren.Loc)
- << FixItHint::CreateRemoval(Paren.EndLoc);
- }
- /// Helper for figuring out the default CC for a function declarator type. If
- /// this is the outermost chunk, then we can determine the CC from the
- /// declarator context. If not, then this could be either a member function
- /// type or normal function type.
- static CallingConv
- getCCForDeclaratorChunk(Sema &S, Declarator &D,
- const DeclaratorChunk::FunctionTypeInfo &FTI,
- unsigned ChunkIndex) {
- assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
- // Check for an explicit CC attribute.
- for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) {
- switch (Attr->getKind()) {
- CALLING_CONV_ATTRS_CASELIST: {
- // Ignore attributes that don't validate or can't apply to the
- // function type. We'll diagnose the failure to apply them in
- // handleFunctionTypeAttr.
- CallingConv CC;
- if (!S.CheckCallingConvAttr(*Attr, CC) &&
- (!FTI.isVariadic || supportsVariadicCall(CC))) {
- return CC;
- }
- break;
- }
- default:
- break;
- }
- }
- bool IsCXXInstanceMethod = false;
- if (S.getLangOpts().CPlusPlus) {
- // Look inwards through parentheses to see if this chunk will form a
- // member pointer type or if we're the declarator. Any type attributes
- // between here and there will override the CC we choose here.
- unsigned I = ChunkIndex;
- bool FoundNonParen = false;
- while (I && !FoundNonParen) {
- --I;
- if (D.getTypeObject(I).Kind != DeclaratorChunk::Paren)
- FoundNonParen = true;
- }
- if (FoundNonParen) {
- // If we're not the declarator, we're a regular function type unless we're
- // in a member pointer.
- IsCXXInstanceMethod =
- D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
- } else if (D.getContext() == DeclaratorContext::LambdaExprContext) {
- // This can only be a call operator for a lambda, which is an instance
- // method.
- IsCXXInstanceMethod = true;
- } else {
- // We're the innermost decl chunk, so must be a function declarator.
- assert(D.isFunctionDeclarator());
- // If we're inside a record, we're declaring a method, but it could be
- // explicitly or implicitly static.
- IsCXXInstanceMethod =
- D.isFirstDeclarationOfMember() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- !D.isStaticMember();
- }
- }
- CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic,
- IsCXXInstanceMethod);
- // Attribute AT_OpenCLKernel affects the calling convention for SPIR
- // and AMDGPU targets, hence it cannot be treated as a calling
- // convention attribute. This is the simplest place to infer
- // calling convention for OpenCL kernels.
- if (S.getLangOpts().OpenCL) {
- for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_OpenCLKernel) {
- CC = CC_OpenCLKernel;
- break;
- }
- }
- }
- return CC;
- }
- namespace {
- /// A simple notion of pointer kinds, which matches up with the various
- /// pointer declarators.
- enum class SimplePointerKind {
- Pointer,
- BlockPointer,
- MemberPointer,
- Array,
- };
- } // end anonymous namespace
- IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
- switch (nullability) {
- case NullabilityKind::NonNull:
- if (!Ident__Nonnull)
- Ident__Nonnull = PP.getIdentifierInfo("_Nonnull");
- return Ident__Nonnull;
- case NullabilityKind::Nullable:
- if (!Ident__Nullable)
- Ident__Nullable = PP.getIdentifierInfo("_Nullable");
- return Ident__Nullable;
- case NullabilityKind::Unspecified:
- if (!Ident__Null_unspecified)
- Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
- return Ident__Null_unspecified;
- }
- llvm_unreachable("Unknown nullability kind.");
- }
- /// Retrieve the identifier "NSError".
- IdentifierInfo *Sema::getNSErrorIdent() {
- if (!Ident_NSError)
- Ident_NSError = PP.getIdentifierInfo("NSError");
- return Ident_NSError;
- }
- /// Check whether there is a nullability attribute of any kind in the given
- /// attribute list.
- static bool hasNullabilityAttr(const AttributeList *attrs) {
- for (const AttributeList *attr = attrs; attr;
- attr = attr->getNext()) {
- if (attr->getKind() == AttributeList::AT_TypeNonNull ||
- attr->getKind() == AttributeList::AT_TypeNullable ||
- attr->getKind() == AttributeList::AT_TypeNullUnspecified)
- return true;
- }
- return false;
- }
- namespace {
- /// Describes the kind of a pointer a declarator describes.
- enum class PointerDeclaratorKind {
- // Not a pointer.
- NonPointer,
- // Single-level pointer.
- SingleLevelPointer,
- // Multi-level pointer (of any pointer kind).
- MultiLevelPointer,
- // CFFooRef*
- MaybePointerToCFRef,
- // CFErrorRef*
- CFErrorRefPointer,
- // NSError**
- NSErrorPointerPointer,
- };
- /// Describes a declarator chunk wrapping a pointer that marks inference as
- /// unexpected.
- // These values must be kept in sync with diagnostics.
- enum class PointerWrappingDeclaratorKind {
- /// Pointer is top-level.
- None = -1,
- /// Pointer is an array element.
- Array = 0,
- /// Pointer is the referent type of a C++ reference.
- Reference = 1
- };
- } // end anonymous namespace
- /// Classify the given declarator, whose type-specified is \c type, based on
- /// what kind of pointer it refers to.
- ///
- /// This is used to determine the default nullability.
- static PointerDeclaratorKind
- classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
- PointerWrappingDeclaratorKind &wrappingKind) {
- unsigned numNormalPointers = 0;
- // For any dependent type, we consider it a non-pointer.
- if (type->isDependentType())
- return PointerDeclaratorKind::NonPointer;
- // Look through the declarator chunks to identify pointers.
- for (unsigned i = 0, n = declarator.getNumTypeObjects(); i != n; ++i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i);
- switch (chunk.Kind) {
- case DeclaratorChunk::Array:
- if (numNormalPointers == 0)
- wrappingKind = PointerWrappingDeclaratorKind::Array;
- break;
- case DeclaratorChunk::Function:
- case DeclaratorChunk::Pipe:
- break;
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::MemberPointer:
- return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
- : PointerDeclaratorKind::SingleLevelPointer;
- case DeclaratorChunk::Paren:
- break;
- case DeclaratorChunk::Reference:
- if (numNormalPointers == 0)
- wrappingKind = PointerWrappingDeclaratorKind::Reference;
- break;
- case DeclaratorChunk::Pointer:
- ++numNormalPointers;
- if (numNormalPointers > 2)
- return PointerDeclaratorKind::MultiLevelPointer;
- break;
- }
- }
- // Then, dig into the type specifier itself.
- unsigned numTypeSpecifierPointers = 0;
- do {
- // Decompose normal pointers.
- if (auto ptrType = type->getAs<PointerType>()) {
- ++numNormalPointers;
- if (numNormalPointers > 2)
- return PointerDeclaratorKind::MultiLevelPointer;
- type = ptrType->getPointeeType();
- ++numTypeSpecifierPointers;
- continue;
- }
- // Decompose block pointers.
- if (type->getAs<BlockPointerType>()) {
- return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
- : PointerDeclaratorKind::SingleLevelPointer;
- }
- // Decompose member pointers.
- if (type->getAs<MemberPointerType>()) {
- return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
- : PointerDeclaratorKind::SingleLevelPointer;
- }
- // Look at Objective-C object pointers.
- if (auto objcObjectPtr = type->getAs<ObjCObjectPointerType>()) {
- ++numNormalPointers;
- ++numTypeSpecifierPointers;
- // If this is NSError**, report that.
- if (auto objcClassDecl = objcObjectPtr->getInterfaceDecl()) {
- if (objcClassDecl->getIdentifier() == S.getNSErrorIdent() &&
- numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
- return PointerDeclaratorKind::NSErrorPointerPointer;
- }
- }
- break;
- }
- // Look at Objective-C class types.
- if (auto objcClass = type->getAs<ObjCInterfaceType>()) {
- if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) {
- if (numNormalPointers == 2 && numTypeSpecifierPointers < 2)
- return PointerDeclaratorKind::NSErrorPointerPointer;
- }
- break;
- }
- // If at this point we haven't seen a pointer, we won't see one.
- if (numNormalPointers == 0)
- return PointerDeclaratorKind::NonPointer;
- if (auto recordType = type->getAs<RecordType>()) {
- RecordDecl *recordDecl = recordType->getDecl();
- bool isCFError = false;
- if (S.CFError) {
- // If we already know about CFError, test it directly.
- isCFError = (S.CFError == recordDecl);
- } else {
- // Check whether this is CFError, which we identify based on its bridge
- // to NSError. CFErrorRef used to be declared with "objc_bridge" but is
- // now declared with "objc_bridge_mutable", so look for either one of
- // the two attributes.
- if (recordDecl->getTagKind() == TTK_Struct && numNormalPointers > 0) {
- IdentifierInfo *bridgedType = nullptr;
- if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>())
- bridgedType = bridgeAttr->getBridgedType();
- else if (auto bridgeAttr =
- recordDecl->getAttr<ObjCBridgeMutableAttr>())
- bridgedType = bridgeAttr->getBridgedType();
- if (bridgedType == S.getNSErrorIdent()) {
- S.CFError = recordDecl;
- isCFError = true;
- }
- }
- }
- // If this is CFErrorRef*, report it as such.
- if (isCFError && numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
- return PointerDeclaratorKind::CFErrorRefPointer;
- }
- break;
- }
- break;
- } while (true);
- switch (numNormalPointers) {
- case 0:
- return PointerDeclaratorKind::NonPointer;
- case 1:
- return PointerDeclaratorKind::SingleLevelPointer;
- case 2:
- return PointerDeclaratorKind::MaybePointerToCFRef;
- default:
- return PointerDeclaratorKind::MultiLevelPointer;
- }
- }
- static FileID getNullabilityCompletenessCheckFileID(Sema &S,
- SourceLocation loc) {
- // If we're anywhere in a function, method, or closure context, don't perform
- // completeness checks.
- for (DeclContext *ctx = S.CurContext; ctx; ctx = ctx->getParent()) {
- if (ctx->isFunctionOrMethod())
- return FileID();
- if (ctx->isFileContext())
- break;
- }
- // We only care about the expansion location.
- loc = S.SourceMgr.getExpansionLoc(loc);
- FileID file = S.SourceMgr.getFileID(loc);
- if (file.isInvalid())
- return FileID();
- // Retrieve file information.
- bool invalid = false;
- const SrcMgr::SLocEntry &sloc = S.SourceMgr.getSLocEntry(file, &invalid);
- if (invalid || !sloc.isFile())
- return FileID();
- // We don't want to perform completeness checks on the main file or in
- // system headers.
- const SrcMgr::FileInfo &fileInfo = sloc.getFile();
- if (fileInfo.getIncludeLoc().isInvalid())
- return FileID();
- if (fileInfo.getFileCharacteristic() != SrcMgr::C_User &&
- S.Diags.getSuppressSystemWarnings()) {
- return FileID();
- }
- return file;
- }
- /// Creates a fix-it to insert a C-style nullability keyword at \p pointerLoc,
- /// taking into account whitespace before and after.
- static void fixItNullability(Sema &S, DiagnosticBuilder &Diag,
- SourceLocation PointerLoc,
- NullabilityKind Nullability) {
- assert(PointerLoc.isValid());
- if (PointerLoc.isMacroID())
- return;
- SourceLocation FixItLoc = S.getLocForEndOfToken(PointerLoc);
- if (!FixItLoc.isValid() || FixItLoc == PointerLoc)
- return;
- const char *NextChar = S.SourceMgr.getCharacterData(FixItLoc);
- if (!NextChar)
- return;
- SmallString<32> InsertionTextBuf{" "};
- InsertionTextBuf += getNullabilitySpelling(Nullability);
- InsertionTextBuf += " ";
- StringRef InsertionText = InsertionTextBuf.str();
- if (isWhitespace(*NextChar)) {
- InsertionText = InsertionText.drop_back();
- } else if (NextChar[-1] == '[') {
- if (NextChar[0] == ']')
- InsertionText = InsertionText.drop_back().drop_front();
- else
- InsertionText = InsertionText.drop_front();
- } else if (!isIdentifierBody(NextChar[0], /*allow dollar*/true) &&
- !isIdentifierBody(NextChar[-1], /*allow dollar*/true)) {
- InsertionText = InsertionText.drop_back().drop_front();
- }
- Diag << FixItHint::CreateInsertion(FixItLoc, InsertionText);
- }
- static void emitNullabilityConsistencyWarning(Sema &S,
- SimplePointerKind PointerKind,
- SourceLocation PointerLoc,
- SourceLocation PointerEndLoc) {
- assert(PointerLoc.isValid());
- if (PointerKind == SimplePointerKind::Array) {
- S.Diag(PointerLoc, diag::warn_nullability_missing_array);
- } else {
- S.Diag(PointerLoc, diag::warn_nullability_missing)
- << static_cast<unsigned>(PointerKind);
- }
- auto FixItLoc = PointerEndLoc.isValid() ? PointerEndLoc : PointerLoc;
- if (FixItLoc.isMacroID())
- return;
- auto addFixIt = [&](NullabilityKind Nullability) {
- auto Diag = S.Diag(FixItLoc, diag::note_nullability_fix_it);
- Diag << static_cast<unsigned>(Nullability);
- Diag << static_cast<unsigned>(PointerKind);
- fixItNullability(S, Diag, FixItLoc, Nullability);
- };
- addFixIt(NullabilityKind::Nullable);
- addFixIt(NullabilityKind::NonNull);
- }
- /// Complains about missing nullability if the file containing \p pointerLoc
- /// has other uses of nullability (either the keywords or the \c assume_nonnull
- /// pragma).
- ///
- /// If the file has \e not seen other uses of nullability, this particular
- /// pointer is saved for possible later diagnosis. See recordNullabilitySeen().
- static void
- checkNullabilityConsistency(Sema &S, SimplePointerKind pointerKind,
- SourceLocation pointerLoc,
- SourceLocation pointerEndLoc = SourceLocation()) {
- // Determine which file we're performing consistency checking for.
- FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
- if (file.isInvalid())
- return;
- // If we haven't seen any type nullability in this file, we won't warn now
- // about anything.
- FileNullability &fileNullability = S.NullabilityMap[file];
- if (!fileNullability.SawTypeNullability) {
- // If this is the first pointer declarator in the file, and the appropriate
- // warning is on, record it in case we need to diagnose it retroactively.
- diag::kind diagKind;
- if (pointerKind == SimplePointerKind::Array)
- diagKind = diag::warn_nullability_missing_array;
- else
- diagKind = diag::warn_nullability_missing;
- if (fileNullability.PointerLoc.isInvalid() &&
- !S.Context.getDiagnostics().isIgnored(diagKind, pointerLoc)) {
- fileNullability.PointerLoc = pointerLoc;
- fileNullability.PointerEndLoc = pointerEndLoc;
- fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
- }
- return;
- }
- // Complain about missing nullability.
- emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc, pointerEndLoc);
- }
- /// Marks that a nullability feature has been used in the file containing
- /// \p loc.
- ///
- /// If this file already had pointer types in it that were missing nullability,
- /// the first such instance is retroactively diagnosed.
- ///
- /// \sa checkNullabilityConsistency
- static void recordNullabilitySeen(Sema &S, SourceLocation loc) {
- FileID file = getNullabilityCompletenessCheckFileID(S, loc);
- if (file.isInvalid())
- return;
- FileNullability &fileNullability = S.NullabilityMap[file];
- if (fileNullability.SawTypeNullability)
- return;
- fileNullability.SawTypeNullability = true;
- // If we haven't seen any type nullability before, now we have. Retroactively
- // diagnose the first unannotated pointer, if there was one.
- if (fileNullability.PointerLoc.isInvalid())
- return;
- auto kind = static_cast<SimplePointerKind>(fileNullability.PointerKind);
- emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc,
- fileNullability.PointerEndLoc);
- }
- /// Returns true if any of the declarator chunks before \p endIndex include a
- /// level of indirection: array, pointer, reference, or pointer-to-member.
- ///
- /// Because declarator chunks are stored in outer-to-inner order, testing
- /// every chunk before \p endIndex is testing all chunks that embed the current
- /// chunk as part of their type.
- ///
- /// It is legal to pass the result of Declarator::getNumTypeObjects() as the
- /// end index, in which case all chunks are tested.
- static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) {
- unsigned i = endIndex;
- while (i != 0) {
- // Walk outwards along the declarator chunks.
- --i;
- const DeclaratorChunk &DC = D.getTypeObject(i);
- switch (DC.Kind) {
- case DeclaratorChunk::Paren:
- break;
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- return true;
- case DeclaratorChunk::Function:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Pipe:
- // These are invalid anyway, so just ignore.
- break;
- }
- }
- return false;
- }
- static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
- QualType declSpecType,
- TypeSourceInfo *TInfo) {
- // The TypeSourceInfo that this function returns will not be a null type.
- // If there is an error, this function will fill in a dummy type as fallback.
- QualType T = declSpecType;
- Declarator &D = state.getDeclarator();
- Sema &S = state.getSema();
- ASTContext &Context = S.Context;
- const LangOptions &LangOpts = S.getLangOpts();
- // The name we're declaring, if any.
- DeclarationName Name;
- if (D.getIdentifier())
- Name = D.getIdentifier();
- // Does this declaration declare a typedef-name?
- bool IsTypedefName =
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
- D.getContext() == DeclaratorContext::AliasDeclContext ||
- D.getContext() == DeclaratorContext::AliasTemplateContext;
- // Does T refer to a function type with a cv-qualifier or a ref-qualifier?
- bool IsQualifiedFunction = T->isFunctionProtoType() &&
- (T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
- T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
- // If T is 'decltype(auto)', the only declarators we can have are parens
- // and at most one function declarator if this is a function declaration.
- // If T is a deduced class template specialization type, we can have no
- // declarator chunks at all.
- if (auto *DT = T->getAs<DeducedType>()) {
- const AutoType *AT = T->getAs<AutoType>();
- bool IsClassTemplateDeduction = isa<DeducedTemplateSpecializationType>(DT);
- if ((AT && AT->isDecltypeAuto()) || IsClassTemplateDeduction) {
- for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
- unsigned Index = E - I - 1;
- DeclaratorChunk &DeclChunk = D.getTypeObject(Index);
- unsigned DiagId = IsClassTemplateDeduction
- ? diag::err_deduced_class_template_compound_type
- : diag::err_decltype_auto_compound_type;
- unsigned DiagKind = 0;
- switch (DeclChunk.Kind) {
- case DeclaratorChunk::Paren:
- // FIXME: Rejecting this is a little silly.
- if (IsClassTemplateDeduction) {
- DiagKind = 4;
- break;
- }
- continue;
- case DeclaratorChunk::Function: {
- if (IsClassTemplateDeduction) {
- DiagKind = 3;
- break;
- }
- unsigned FnIndex;
- if (D.isFunctionDeclarationContext() &&
- D.isFunctionDeclarator(FnIndex) && FnIndex == Index)
- continue;
- DiagId = diag::err_decltype_auto_function_declarator_not_declaration;
- break;
- }
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::MemberPointer:
- DiagKind = 0;
- break;
- case DeclaratorChunk::Reference:
- DiagKind = 1;
- break;
- case DeclaratorChunk::Array:
- DiagKind = 2;
- break;
- case DeclaratorChunk::Pipe:
- break;
- }
- S.Diag(DeclChunk.Loc, DiagId) << DiagKind;
- D.setInvalidType(true);
- break;
- }
- }
- }
- // Determine whether we should infer _Nonnull on pointer types.
- Optional<NullabilityKind> inferNullability;
- bool inferNullabilityCS = false;
- bool inferNullabilityInnerOnly = false;
- bool inferNullabilityInnerOnlyComplete = false;
- // Are we in an assume-nonnull region?
- bool inAssumeNonNullRegion = false;
- SourceLocation assumeNonNullLoc = S.PP.getPragmaAssumeNonNullLoc();
- if (assumeNonNullLoc.isValid()) {
- inAssumeNonNullRegion = true;
- recordNullabilitySeen(S, assumeNonNullLoc);
- }
- // Whether to complain about missing nullability specifiers or not.
- enum {
- /// Never complain.
- CAMN_No,
- /// Complain on the inner pointers (but not the outermost
- /// pointer).
- CAMN_InnerPointers,
- /// Complain about any pointers that don't have nullability
- /// specified or inferred.
- CAMN_Yes
- } complainAboutMissingNullability = CAMN_No;
- unsigned NumPointersRemaining = 0;
- auto complainAboutInferringWithinChunk = PointerWrappingDeclaratorKind::None;
- if (IsTypedefName) {
- // For typedefs, we do not infer any nullability (the default),
- // and we only complain about missing nullability specifiers on
- // inner pointers.
- complainAboutMissingNullability = CAMN_InnerPointers;
- if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
- !T->getNullability(S.Context)) {
- // Note that we allow but don't require nullability on dependent types.
- ++NumPointersRemaining;
- }
- for (unsigned i = 0, n = D.getNumTypeObjects(); i != n; ++i) {
- DeclaratorChunk &chunk = D.getTypeObject(i);
- switch (chunk.Kind) {
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Function:
- case DeclaratorChunk::Pipe:
- break;
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::MemberPointer:
- ++NumPointersRemaining;
- break;
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Reference:
- continue;
- case DeclaratorChunk::Pointer:
- ++NumPointersRemaining;
- continue;
- }
- }
- } else {
- bool isFunctionOrMethod = false;
- switch (auto context = state.getDeclarator().getContext()) {
- case DeclaratorContext::ObjCParameterContext:
- case DeclaratorContext::ObjCResultContext:
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
- isFunctionOrMethod = true;
- LLVM_FALLTHROUGH;
- case DeclaratorContext::MemberContext:
- if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
- complainAboutMissingNullability = CAMN_No;
- break;
- }
- // Weak properties are inferred to be nullable.
- if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
- inferNullability = NullabilityKind::Nullable;
- break;
- }
- LLVM_FALLTHROUGH;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::KNRTypeListContext: {
- complainAboutMissingNullability = CAMN_Yes;
- // Nullability inference depends on the type and declarator.
- auto wrappingKind = PointerWrappingDeclaratorKind::None;
- switch (classifyPointerDeclarator(S, T, D, wrappingKind)) {
- case PointerDeclaratorKind::NonPointer:
- case PointerDeclaratorKind::MultiLevelPointer:
- // Cannot infer nullability.
- break;
- case PointerDeclaratorKind::SingleLevelPointer:
- // Infer _Nonnull if we are in an assumes-nonnull region.
- if (inAssumeNonNullRegion) {
- complainAboutInferringWithinChunk = wrappingKind;
- inferNullability = NullabilityKind::NonNull;
- inferNullabilityCS =
- (context == DeclaratorContext::ObjCParameterContext ||
- context == DeclaratorContext::ObjCResultContext);
- }
- break;
- case PointerDeclaratorKind::CFErrorRefPointer:
- case PointerDeclaratorKind::NSErrorPointerPointer:
- // Within a function or method signature, infer _Nullable at both
- // levels.
- if (isFunctionOrMethod && inAssumeNonNullRegion)
- inferNullability = NullabilityKind::Nullable;
- break;
- case PointerDeclaratorKind::MaybePointerToCFRef:
- if (isFunctionOrMethod) {
- // On pointer-to-pointer parameters marked cf_returns_retained or
- // cf_returns_not_retained, if the outer pointer is explicit then
- // infer the inner pointer as _Nullable.
- auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
- while (NextAttr) {
- if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
- NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained)
- return true;
- NextAttr = NextAttr->getNext();
- }
- return false;
- };
- if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) {
- if (hasCFReturnsAttr(D.getAttributes()) ||
- hasCFReturnsAttr(InnermostChunk->getAttrs()) ||
- hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) {
- inferNullability = NullabilityKind::Nullable;
- inferNullabilityInnerOnly = true;
- }
- }
- }
- break;
- }
- break;
- }
- case DeclaratorContext::ConversionIdContext:
- complainAboutMissingNullability = CAMN_Yes;
- break;
- case DeclaratorContext::AliasDeclContext:
- case DeclaratorContext::AliasTemplateContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::BlockLiteralContext:
- case DeclaratorContext::ConditionContext:
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::CXXNewContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::LambdaExprContext:
- case DeclaratorContext::LambdaExprParameterContext:
- case DeclaratorContext::ObjCCatchContext:
- case DeclaratorContext::TemplateParamContext:
- case DeclaratorContext::TemplateTypeArgContext:
- case DeclaratorContext::TypeNameContext:
- case DeclaratorContext::FunctionalCastContext:
- // Don't infer in these contexts.
- break;
- }
- }
- // Local function that returns true if its argument looks like a va_list.
- auto isVaList = [&S](QualType T) -> bool {
- auto *typedefTy = T->getAs<TypedefType>();
- if (!typedefTy)
- return false;
- TypedefDecl *vaListTypedef = S.Context.getBuiltinVaListDecl();
- do {
- if (typedefTy->getDecl() == vaListTypedef)
- return true;
- if (auto *name = typedefTy->getDecl()->getIdentifier())
- if (name->isStr("va_list"))
- return true;
- typedefTy = typedefTy->desugar()->getAs<TypedefType>();
- } while (typedefTy);
- return false;
- };
- // Local function that checks the nullability for a given pointer declarator.
- // Returns true if _Nonnull was inferred.
- auto inferPointerNullability = [&](SimplePointerKind pointerKind,
- SourceLocation pointerLoc,
- SourceLocation pointerEndLoc,
- AttributeList *&attrs) -> AttributeList * {
- // We've seen a pointer.
- if (NumPointersRemaining > 0)
- --NumPointersRemaining;
- // If a nullability attribute is present, there's nothing to do.
- if (hasNullabilityAttr(attrs))
- return nullptr;
- // If we're supposed to infer nullability, do so now.
- if (inferNullability && !inferNullabilityInnerOnlyComplete) {
- AttributeList::Syntax syntax
- = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
- : AttributeList::AS_Keyword;
- AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool()
- .create(
- S.getNullabilityKeyword(
- *inferNullability),
- SourceRange(pointerLoc),
- nullptr, SourceLocation(),
- nullptr, 0, syntax);
- spliceAttrIntoList(*nullabilityAttr, attrs);
- if (inferNullabilityCS) {
- state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
- ->setObjCDeclQualifier(ObjCDeclSpec::DQ_CSNullability);
- }
- if (pointerLoc.isValid() &&
- complainAboutInferringWithinChunk !=
- PointerWrappingDeclaratorKind::None) {
- auto Diag =
- S.Diag(pointerLoc, diag::warn_nullability_inferred_on_nested_type);
- Diag << static_cast<int>(complainAboutInferringWithinChunk);
- fixItNullability(S, Diag, pointerLoc, NullabilityKind::NonNull);
- }
- if (inferNullabilityInnerOnly)
- inferNullabilityInnerOnlyComplete = true;
- return nullabilityAttr;
- }
- // If we're supposed to complain about missing nullability, do so
- // now if it's truly missing.
- switch (complainAboutMissingNullability) {
- case CAMN_No:
- break;
- case CAMN_InnerPointers:
- if (NumPointersRemaining == 0)
- break;
- LLVM_FALLTHROUGH;
- case CAMN_Yes:
- checkNullabilityConsistency(S, pointerKind, pointerLoc, pointerEndLoc);
- }
- return nullptr;
- };
- // If the type itself could have nullability but does not, infer pointer
- // nullability and perform consistency checking.
- if (S.CodeSynthesisContexts.empty()) {
- if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
- !T->getNullability(S.Context)) {
- if (isVaList(T)) {
- // Record that we've seen a pointer, but do nothing else.
- if (NumPointersRemaining > 0)
- --NumPointersRemaining;
- } else {
- SimplePointerKind pointerKind = SimplePointerKind::Pointer;
- if (T->isBlockPointerType())
- pointerKind = SimplePointerKind::BlockPointer;
- else if (T->isMemberPointerType())
- pointerKind = SimplePointerKind::MemberPointer;
- if (auto *attr = inferPointerNullability(
- pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getDeclSpec().getLocEnd(),
- D.getMutableDeclSpec().getAttributes().getListRef())) {
- T = Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
- attr->setUsedAsTypeAttr();
- }
- }
- }
- if (complainAboutMissingNullability == CAMN_Yes &&
- T->isArrayType() && !T->getNullability(S.Context) && !isVaList(T) &&
- D.isPrototypeContext() &&
- !hasOuterPointerLikeChunk(D, D.getNumTypeObjects())) {
- checkNullabilityConsistency(S, SimplePointerKind::Array,
- D.getDeclSpec().getTypeSpecTypeLoc());
- }
- }
- // Walk the DeclTypeInfo, building the recursive type as we go.
- // DeclTypeInfos are ordered from the identifier out, which is
- // opposite of what we want :).
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- unsigned chunkIndex = e - i - 1;
- state.setCurrentChunkIndex(chunkIndex);
- DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- IsQualifiedFunction &= DeclType.Kind == DeclaratorChunk::Paren;
- switch (DeclType.Kind) {
- case DeclaratorChunk::Paren:
- if (i == 0)
- warnAboutRedundantParens(S, D, T);
- T = S.BuildParenType(T);
- break;
- case DeclaratorChunk::BlockPointer:
- // If blocks are disabled, emit an error.
- if (!LangOpts.Blocks)
- S.Diag(DeclType.Loc, diag::err_blocks_disable) << LangOpts.OpenCL;
- // Handle pointer nullability.
- inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
- T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
- if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
- // OpenCL v2.0, s6.12.5 - Block variable declarations are implicitly
- // qualified with const.
- if (LangOpts.OpenCL)
- DeclType.Cls.TypeQuals |= DeclSpec::TQ_const;
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
- }
- break;
- case DeclaratorChunk::Pointer:
- // Verify that we're not building a pointer to pointer to function with
- // exception specification.
- if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
- S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
- // Handle pointer nullability
- inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
- if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
- T = Context.getObjCObjectPointerType(T);
- if (DeclType.Ptr.TypeQuals)
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
- break;
- }
- // OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used.
- // OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used.
- // OpenCL v2.0 s6.12.5 - Pointers to Blocks are not allowed.
- if (LangOpts.OpenCL) {
- if (T->isImageType() || T->isSamplerT() || T->isPipeType() ||
- T->isBlockPointerType()) {
- S.Diag(D.getIdentifierLoc(), diag::err_opencl_pointer_to_type) << T;
- D.setInvalidType(true);
- }
- }
- T = S.BuildPointerType(T, DeclType.Loc, Name);
- if (DeclType.Ptr.TypeQuals)
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
- break;
- case DeclaratorChunk::Reference: {
- // Verify that we're not building a reference to pointer to function with
- // exception specification.
- if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
- S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
- T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
- if (DeclType.Ref.HasRestrict)
- T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
- break;
- }
- case DeclaratorChunk::Array: {
- // Verify that we're not building an array of pointers to function with
- // exception specification.
- if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
- S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
- DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
- Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
- ArrayType::ArraySizeModifier ASM;
- if (ATI.isStar)
- ASM = ArrayType::Star;
- else if (ATI.hasStatic)
- ASM = ArrayType::Static;
- else
- ASM = ArrayType::Normal;
- if (ASM == ArrayType::Star && !D.isPrototypeContext()) {
- // FIXME: This check isn't quite right: it allows star in prototypes
- // for function definitions, and disallows some edge cases detailed
- // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
- S.Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
- ASM = ArrayType::Normal;
- D.setInvalidType(true);
- }
- // C99 6.7.5.2p1: The optional type qualifiers and the keyword static
- // shall appear only in a declaration of a function parameter with an
- // array type, ...
- if (ASM == ArrayType::Static || ATI.TypeQuals) {
- if (!(D.isPrototypeContext() ||
- D.getContext() == DeclaratorContext::KNRTypeListContext)) {
- S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
- (ASM == ArrayType::Static ? "'static'" : "type qualifier");
- // Remove the 'static' and the type qualifiers.
- if (ASM == ArrayType::Static)
- ASM = ArrayType::Normal;
- ATI.TypeQuals = 0;
- D.setInvalidType(true);
- }
- // C99 6.7.5.2p1: ... and then only in the outermost array type
- // derivation.
- if (hasOuterPointerLikeChunk(D, chunkIndex)) {
- S.Diag(DeclType.Loc, diag::err_array_static_not_outermost) <<
- (ASM == ArrayType::Static ? "'static'" : "type qualifier");
- if (ASM == ArrayType::Static)
- ASM = ArrayType::Normal;
- ATI.TypeQuals = 0;
- D.setInvalidType(true);
- }
- }
- const AutoType *AT = T->getContainedAutoType();
- // Allow arrays of auto if we are a generic lambda parameter.
- // i.e. [](auto (&array)[5]) { return array[0]; }; OK
- if (AT &&
- D.getContext() != DeclaratorContext::LambdaExprParameterContext) {
- // We've already diagnosed this for decltype(auto).
- if (!AT->isDecltypeAuto())
- S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
- << getPrintableNameForEntity(Name) << T;
- T = QualType();
- break;
- }
- // Array parameters can be marked nullable as well, although it's not
- // necessary if they're marked 'static'.
- if (complainAboutMissingNullability == CAMN_Yes &&
- !hasNullabilityAttr(DeclType.getAttrs()) &&
- ASM != ArrayType::Static &&
- D.isPrototypeContext() &&
- !hasOuterPointerLikeChunk(D, chunkIndex)) {
- checkNullabilityConsistency(S, SimplePointerKind::Array, DeclType.Loc);
- }
- T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
- SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
- break;
- }
- case DeclaratorChunk::Function: {
- // If the function declarator has a prototype (i.e. it is not () and
- // does not have a K&R-style identifier list), then the arguments are part
- // of the type, otherwise the argument list is ().
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier();
- // Check for auto functions and trailing return type and adjust the
- // return type accordingly.
- if (!D.isInvalidType()) {
- // trailing-return-type is only required if we're declaring a function,
- // and not, for instance, a pointer to a function.
- if (D.getDeclSpec().hasAutoTypeSpec() &&
- !FTI.hasTrailingReturnType() && chunkIndex == 0 &&
- !S.getLangOpts().CPlusPlus14) {
- S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
- ? diag::err_auto_missing_trailing_return
- : diag::err_deduced_return_type);
- T = Context.IntTy;
- D.setInvalidType(true);
- } else if (FTI.hasTrailingReturnType()) {
- // T must be exactly 'auto' at this point. See CWG issue 681.
- if (isa<ParenType>(T)) {
- S.Diag(D.getLocStart(),
- diag::err_trailing_return_in_parens)
- << T << D.getSourceRange();
- D.setInvalidType(true);
- } else if (D.getName().getKind() ==
- UnqualifiedIdKind::IK_DeductionGuideName) {
- if (T != Context.DependentTy) {
- S.Diag(D.getDeclSpec().getLocStart(),
- diag::err_deduction_guide_with_complex_decl)
- << D.getSourceRange();
- D.setInvalidType(true);
- }
- } else if (D.getContext() != DeclaratorContext::LambdaExprContext &&
- (T.hasQualifiers() || !isa<AutoType>(T) ||
- cast<AutoType>(T)->getKeyword() !=
- AutoTypeKeyword::Auto)) {
- S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_trailing_return_without_auto)
- << T << D.getDeclSpec().getSourceRange();
- D.setInvalidType(true);
- }
- T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
- if (T.isNull()) {
- // An error occurred parsing the trailing return type.
- T = Context.IntTy;
- D.setInvalidType(true);
- }
- }
- }
- // C99 6.7.5.3p1: The return type may not be a function or array type.
- // For conversion functions, we'll diagnose this particular error later.
- if (!D.isInvalidType() && (T->isArrayType() || T->isFunctionType()) &&
- (D.getName().getKind() !=
- UnqualifiedIdKind::IK_ConversionFunctionId)) {
- unsigned diagID = diag::err_func_returning_array_function;
- // Last processing chunk in block context means this function chunk
- // represents the block.
- if (chunkIndex == 0 &&
- D.getContext() == DeclaratorContext::BlockLiteralContext)
- diagID = diag::err_block_returning_array_function;
- S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
- T = Context.IntTy;
- D.setInvalidType(true);
- }
- // Do not allow returning half FP value.
- // FIXME: This really should be in BuildFunctionType.
- if (T->isHalfType()) {
- if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
- S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
- << T << 0 /*pointer hint*/;
- D.setInvalidType(true);
- }
- } else if (!S.getLangOpts().HalfArgsAndReturns) {
- S.Diag(D.getIdentifierLoc(),
- diag::err_parameters_retval_cannot_have_fp16_type) << 1;
- D.setInvalidType(true);
- }
- }
- if (LangOpts.OpenCL) {
- // OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
- // function.
- if (T->isBlockPointerType() || T->isImageType() || T->isSamplerT() ||
- T->isPipeType()) {
- S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
- << T << 1 /*hint off*/;
- D.setInvalidType(true);
- }
- // OpenCL doesn't support variadic functions and blocks
- // (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
- // We also allow here any toolchain reserved identifiers.
- if (FTI.isVariadic &&
- !(D.getIdentifier() &&
- ((D.getIdentifier()->getName() == "printf" &&
- LangOpts.OpenCLVersion >= 120) ||
- D.getIdentifier()->getName().startswith("__")))) {
- S.Diag(D.getIdentifierLoc(), diag::err_opencl_variadic_function);
- D.setInvalidType(true);
- }
- }
- // Methods cannot return interface types. All ObjC objects are
- // passed by reference.
- if (T->isObjCObjectType()) {
- SourceLocation DiagLoc, FixitLoc;
- if (TInfo) {
- DiagLoc = TInfo->getTypeLoc().getLocStart();
- FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getLocEnd());
- } else {
- DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
- FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getLocEnd());
- }
- S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
- << 0 << T
- << FixItHint::CreateInsertion(FixitLoc, "*");
- T = Context.getObjCObjectPointerType(T);
- if (TInfo) {
- TypeLocBuilder TLB;
- TLB.pushFullCopy(TInfo->getTypeLoc());
- ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T);
- TLoc.setStarLoc(FixitLoc);
- TInfo = TLB.getTypeSourceInfo(Context, T);
- }
- D.setInvalidType(true);
- }
- // cv-qualifiers on return types are pointless except when the type is a
- // class type in C++.
- if ((T.getCVRQualifiers() || T->isAtomicType()) &&
- !(S.getLangOpts().CPlusPlus &&
- (T->isDependentType() || T->isRecordType()))) {
- if (T->isVoidType() && !S.getLangOpts().CPlusPlus &&
- D.getFunctionDefinitionKind() == FDK_Definition) {
- // [6.9.1/3] qualified void return is invalid on a C
- // function definition. Apparently ok on declarations and
- // in C++ though (!)
- S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T;
- } else
- diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex);
- }
- // Objective-C ARC ownership qualifiers are ignored on the function
- // return type (by type canonicalization). Complain if this attribute
- // was written here.
- if (T.getQualifiers().hasObjCLifetime()) {
- SourceLocation AttrLoc;
- if (chunkIndex + 1 < D.getNumTypeObjects()) {
- DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
- for (const AttributeList *Attr = ReturnTypeChunk.getAttrs();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
- AttrLoc = Attr->getLoc();
- break;
- }
- }
- }
- if (AttrLoc.isInvalid()) {
- for (const AttributeList *Attr
- = D.getDeclSpec().getAttributes().getList();
- Attr; Attr = Attr->getNext()) {
- if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
- AttrLoc = Attr->getLoc();
- break;
- }
- }
- }
- if (AttrLoc.isValid()) {
- // The ownership attributes are almost always written via
- // the predefined
- // __strong/__weak/__autoreleasing/__unsafe_unretained.
- if (AttrLoc.isMacroID())
- AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
- S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
- << T.getQualifiers().getObjCLifetime();
- }
- }
- if (LangOpts.CPlusPlus && D.getDeclSpec().hasTagDefinition()) {
- // C++ [dcl.fct]p6:
- // Types shall not be defined in return or parameter types.
- TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
- << Context.getTypeDeclType(Tag);
- }
- // Exception specs are not allowed in typedefs. Complain, but add it
- // anyway.
- if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
- S.Diag(FTI.getExceptionSpecLocBeg(),
- diag::err_exception_spec_in_typedef)
- << (D.getContext() == DeclaratorContext::AliasDeclContext ||
- D.getContext() == DeclaratorContext::AliasTemplateContext);
- // If we see "T var();" or "T var(T());" at block scope, it is probably
- // an attempt to initialize a variable, not a function declaration.
- if (FTI.isAmbiguous)
- warnAboutAmbiguousFunction(S, D, DeclType, T);
- FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
- if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus
- && !LangOpts.OpenCL) {
- // Simple void foo(), where the incoming T is the result type.
- T = Context.getFunctionNoProtoType(T, EI);
- } else {
- // We allow a zero-parameter variadic function in C if the
- // function is marked with the "overloadable" attribute. Scan
- // for this attribute now.
- if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) {
- bool Overloadable = false;
- for (const AttributeList *Attrs = D.getAttributes();
- Attrs; Attrs = Attrs->getNext()) {
- if (Attrs->getKind() == AttributeList::AT_Overloadable) {
- Overloadable = true;
- break;
- }
- }
- if (!Overloadable)
- S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
- }
- if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
- // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
- // definition.
- S.Diag(FTI.Params[0].IdentLoc,
- diag::err_ident_list_in_fn_declaration);
- D.setInvalidType(true);
- // Recover by creating a K&R-style function type.
- T = Context.getFunctionNoProtoType(T, EI);
- break;
- }
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.ExtInfo = EI;
- EPI.Variadic = FTI.isVariadic;
- EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
- EPI.TypeQuals = FTI.TypeQuals;
- EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
- : FTI.RefQualifierIsLValueRef? RQ_LValue
- : RQ_RValue;
- // Otherwise, we have a function with a parameter list that is
- // potentially variadic.
- SmallVector<QualType, 16> ParamTys;
- ParamTys.reserve(FTI.NumParams);
- SmallVector<FunctionProtoType::ExtParameterInfo, 16>
- ExtParameterInfos(FTI.NumParams);
- bool HasAnyInterestingExtParameterInfos = false;
- for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
- QualType ParamTy = Param->getType();
- assert(!ParamTy.isNull() && "Couldn't parse type?");
- // Look for 'void'. void is allowed only as a single parameter to a
- // function with no other parameters (C99 6.7.5.3p10). We record
- // int(void) as a FunctionProtoType with an empty parameter list.
- if (ParamTy->isVoidType()) {
- // If this is something like 'float(int, void)', reject it. 'void'
- // is an incomplete type (C99 6.2.5p19) and function decls cannot
- // have parameters of incomplete type.
- if (FTI.NumParams != 1 || FTI.isVariadic) {
- S.Diag(DeclType.Loc, diag::err_void_only_param);
- ParamTy = Context.IntTy;
- Param->setType(ParamTy);
- } else if (FTI.Params[i].Ident) {
- // Reject, but continue to parse 'int(void abc)'.
- S.Diag(FTI.Params[i].IdentLoc, diag::err_param_with_void_type);
- ParamTy = Context.IntTy;
- Param->setType(ParamTy);
- } else {
- // Reject, but continue to parse 'float(const void)'.
- if (ParamTy.hasQualifiers())
- S.Diag(DeclType.Loc, diag::err_void_param_qualified);
- // Do not add 'void' to the list.
- break;
- }
- } else if (ParamTy->isHalfType()) {
- // Disallow half FP parameters.
- // FIXME: This really should be in BuildFunctionType.
- if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
- S.Diag(Param->getLocation(),
- diag::err_opencl_half_param) << ParamTy;
- D.setInvalidType();
- Param->setInvalidDecl();
- }
- } else if (!S.getLangOpts().HalfArgsAndReturns) {
- S.Diag(Param->getLocation(),
- diag::err_parameters_retval_cannot_have_fp16_type) << 0;
- D.setInvalidType();
- }
- } else if (!FTI.hasPrototype) {
- if (ParamTy->isPromotableIntegerType()) {
- ParamTy = Context.getPromotedIntegerType(ParamTy);
- Param->setKNRPromoted(true);
- } else if (const BuiltinType* BTy = ParamTy->getAs<BuiltinType>()) {
- if (BTy->getKind() == BuiltinType::Float) {
- ParamTy = Context.DoubleTy;
- Param->setKNRPromoted(true);
- }
- }
- }
- if (LangOpts.ObjCAutoRefCount && Param->hasAttr<NSConsumedAttr>()) {
- ExtParameterInfos[i] = ExtParameterInfos[i].withIsConsumed(true);
- HasAnyInterestingExtParameterInfos = true;
- }
- if (auto attr = Param->getAttr<ParameterABIAttr>()) {
- ExtParameterInfos[i] =
- ExtParameterInfos[i].withABI(attr->getABI());
- HasAnyInterestingExtParameterInfos = true;
- }
- if (Param->hasAttr<PassObjectSizeAttr>()) {
- ExtParameterInfos[i] = ExtParameterInfos[i].withHasPassObjectSize();
- HasAnyInterestingExtParameterInfos = true;
- }
- if (Param->hasAttr<NoEscapeAttr>()) {
- ExtParameterInfos[i] = ExtParameterInfos[i].withIsNoEscape(true);
- HasAnyInterestingExtParameterInfos = true;
- }
- ParamTys.push_back(ParamTy);
- }
- if (HasAnyInterestingExtParameterInfos) {
- EPI.ExtParameterInfos = ExtParameterInfos.data();
- checkExtParameterInfos(S, ParamTys, EPI,
- [&](unsigned i) { return FTI.Params[i].Param->getLocation(); });
- }
- SmallVector<QualType, 4> Exceptions;
- SmallVector<ParsedType, 2> DynamicExceptions;
- SmallVector<SourceRange, 2> DynamicExceptionRanges;
- Expr *NoexceptExpr = nullptr;
- if (FTI.getExceptionSpecType() == EST_Dynamic) {
- // FIXME: It's rather inefficient to have to split into two vectors
- // here.
- unsigned N = FTI.getNumExceptions();
- DynamicExceptions.reserve(N);
- DynamicExceptionRanges.reserve(N);
- for (unsigned I = 0; I != N; ++I) {
- DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
- DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
- }
- } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
- NoexceptExpr = FTI.NoexceptExpr;
- }
- S.checkExceptionSpecification(D.isFunctionDeclarationContext(),
- FTI.getExceptionSpecType(),
- DynamicExceptions,
- DynamicExceptionRanges,
- NoexceptExpr,
- Exceptions,
- EPI.ExceptionSpec);
- T = Context.getFunctionType(T, ParamTys, EPI);
- }
- break;
- }
- case DeclaratorChunk::MemberPointer: {
- // The scope spec must refer to a class, or be dependent.
- CXXScopeSpec &SS = DeclType.Mem.Scope();
- QualType ClsType;
- // Handle pointer nullability.
- inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
- DeclType.EndLoc, DeclType.getAttrListRef());
- if (SS.isInvalid()) {
- // Avoid emitting extra errors if we already errored on the scope.
- D.setInvalidType(true);
- } else if (S.isDependentScopeSpecifier(SS) ||
- dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
- NestedNameSpecifier *NNS = SS.getScopeRep();
- NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
- NNS->getAsIdentifier());
- break;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- llvm_unreachable("Nested-name-specifier must name a type");
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- ClsType = QualType(NNS->getAsType(), 0);
- // Note: if the NNS has a prefix and ClsType is a nondependent
- // TemplateSpecializationType, then the NNS prefix is NOT included
- // in ClsType; hence we wrap ClsType into an ElaboratedType.
- // NOTE: in particular, no wrap occurs if ClsType already is an
- // Elaborated, DependentName, or DependentTemplateSpecialization.
- if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
- ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
- break;
- }
- } else {
- S.Diag(DeclType.Mem.Scope().getBeginLoc(),
- diag::err_illegal_decl_mempointer_in_nonclass)
- << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
- << DeclType.Mem.Scope().getRange();
- D.setInvalidType(true);
- }
- if (!ClsType.isNull())
- T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
- D.getIdentifier());
- if (T.isNull()) {
- T = Context.IntTy;
- D.setInvalidType(true);
- } else if (DeclType.Mem.TypeQuals) {
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
- }
- break;
- }
- case DeclaratorChunk::Pipe: {
- T = S.BuildReadPipeType(T, DeclType.Loc);
- processTypeAttrs(state, T, TAL_DeclSpec,
- D.getDeclSpec().getAttributes().getList());
- break;
- }
- }
- if (T.isNull()) {
- D.setInvalidType(true);
- T = Context.IntTy;
- }
- // See if there are any attributes on this declarator chunk.
- processTypeAttrs(state, T, TAL_DeclChunk,
- const_cast<AttributeList *>(DeclType.getAttrs()));
- }
- // GNU warning -Wstrict-prototypes
- // Warn if a function declaration is without a prototype.
- // This warning is issued for all kinds of unprototyped function
- // declarations (i.e. function type typedef, function pointer etc.)
- // C99 6.7.5.3p14:
- // The empty list in a function declarator that is not part of a definition
- // of that function specifies that no information about the number or types
- // of the parameters is supplied.
- if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) {
- bool IsBlock = false;
- for (const DeclaratorChunk &DeclType : D.type_objects()) {
- switch (DeclType.Kind) {
- case DeclaratorChunk::BlockPointer:
- IsBlock = true;
- break;
- case DeclaratorChunk::Function: {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (FTI.NumParams == 0 && !FTI.isVariadic)
- S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
- << IsBlock
- << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
- IsBlock = false;
- break;
- }
- default:
- break;
- }
- }
- }
- assert(!T.isNull() && "T must not be null after this point");
- if (LangOpts.CPlusPlus && T->isFunctionType()) {
- const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
- assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
- // C++ 8.3.5p4:
- // A cv-qualifier-seq shall only be part of the function type
- // for a nonstatic member function, the function type to which a pointer
- // to member refers, or the top-level function type of a function typedef
- // declaration.
- //
- // Core issue 547 also allows cv-qualifiers on function types that are
- // top-level template type arguments.
- enum { NonMember, Member, DeductionGuide } Kind = NonMember;
- if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName)
- Kind = DeductionGuide;
- else if (!D.getCXXScopeSpec().isSet()) {
- if ((D.getContext() == DeclaratorContext::MemberContext ||
- D.getContext() == DeclaratorContext::LambdaExprContext) &&
- !D.getDeclSpec().isFriendSpecified())
- Kind = Member;
- } else {
- DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
- if (!DC || DC->isRecord())
- Kind = Member;
- }
- // C++11 [dcl.fct]p6 (w/DR1417):
- // An attempt to specify a function type with a cv-qualifier-seq or a
- // ref-qualifier (including by typedef-name) is ill-formed unless it is:
- // - the function type for a non-static member function,
- // - the function type to which a pointer to member refers,
- // - the top-level function type of a function typedef declaration or
- // alias-declaration,
- // - the type-id in the default argument of a type-parameter, or
- // - the type-id of a template-argument for a type-parameter
- //
- // FIXME: Checking this here is insufficient. We accept-invalid on:
- //
- // template<typename T> struct S { void f(T); };
- // S<int() const> s;
- //
- // ... for instance.
- if (IsQualifiedFunction &&
- !(Kind == Member &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
- !IsTypedefName &&
- D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
- SourceLocation Loc = D.getLocStart();
- SourceRange RemovalRange;
- unsigned I;
- if (D.isFunctionDeclarator(I)) {
- SmallVector<SourceLocation, 4> RemovalLocs;
- const DeclaratorChunk &Chunk = D.getTypeObject(I);
- assert(Chunk.Kind == DeclaratorChunk::Function);
- if (Chunk.Fun.hasRefQualifier())
- RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc());
- if (Chunk.Fun.TypeQuals & Qualifiers::Const)
- RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc());
- if (Chunk.Fun.TypeQuals & Qualifiers::Volatile)
- RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc());
- if (Chunk.Fun.TypeQuals & Qualifiers::Restrict)
- RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
- if (!RemovalLocs.empty()) {
- std::sort(RemovalLocs.begin(), RemovalLocs.end(),
- BeforeThanCompare<SourceLocation>(S.getSourceManager()));
- RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
- Loc = RemovalLocs.front();
- }
- }
- S.Diag(Loc, diag::err_invalid_qualified_function_type)
- << Kind << D.isFunctionDeclarator() << T
- << getFunctionQualifiersAsString(FnTy)
- << FixItHint::CreateRemoval(RemovalRange);
- // Strip the cv-qualifiers and ref-qualifiers from the type.
- FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
- EPI.TypeQuals = 0;
- EPI.RefQualifier = RQ_None;
- T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
- EPI);
- // Rebuild any parens around the identifier in the function type.
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren)
- break;
- T = S.BuildParenType(T);
- }
- }
- }
- // Apply any undistributed attributes from the declarator.
- processTypeAttrs(state, T, TAL_DeclName, D.getAttributes());
- // Diagnose any ignored type attributes.
- state.diagnoseIgnoredTypeAttrs(T);
- // C++0x [dcl.constexpr]p9:
- // A constexpr specifier used in an object declaration declares the object
- // as const.
- if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
- T.addConst();
- }
- // If there was an ellipsis in the declarator, the declaration declares a
- // parameter pack whose type may be a pack expansion type.
- if (D.hasEllipsis()) {
- // C++0x [dcl.fct]p13:
- // A declarator-id or abstract-declarator containing an ellipsis shall
- // only be used in a parameter-declaration. Such a parameter-declaration
- // is a parameter pack (14.5.3). [...]
- switch (D.getContext()) {
- case DeclaratorContext::PrototypeContext:
- case DeclaratorContext::LambdaExprParameterContext:
- // C++0x [dcl.fct]p13:
- // [...] When it is part of a parameter-declaration-clause, the
- // parameter pack is a function parameter pack (14.5.3). The type T
- // of the declarator-id of the function parameter pack shall contain
- // a template parameter pack; each template parameter pack in T is
- // expanded by the function parameter pack.
- //
- // We represent function parameter packs as function parameters whose
- // type is a pack expansion.
- if (!T->containsUnexpandedParameterPack()) {
- S.Diag(D.getEllipsisLoc(),
- diag::err_function_parameter_pack_without_parameter_packs)
- << T << D.getSourceRange();
- D.setEllipsisLoc(SourceLocation());
- } else {
- T = Context.getPackExpansionType(T, None);
- }
- break;
- case DeclaratorContext::TemplateParamContext:
- // C++0x [temp.param]p15:
- // If a template-parameter is a [...] is a parameter-declaration that
- // declares a parameter pack (8.3.5), then the template-parameter is a
- // template parameter pack (14.5.3).
- //
- // Note: core issue 778 clarifies that, if there are any unexpanded
- // parameter packs in the type of the non-type template parameter, then
- // it expands those parameter packs.
- if (T->containsUnexpandedParameterPack())
- T = Context.getPackExpansionType(T, None);
- else
- S.Diag(D.getEllipsisLoc(),
- LangOpts.CPlusPlus11
- ? diag::warn_cxx98_compat_variadic_templates
- : diag::ext_variadic_templates);
- break;
- case DeclaratorContext::FileContext:
- case DeclaratorContext::KNRTypeListContext:
- case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic
- // here?
- case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic
- // here?
- case DeclaratorContext::TypeNameContext:
- case DeclaratorContext::FunctionalCastContext:
- case DeclaratorContext::CXXNewContext:
- case DeclaratorContext::AliasDeclContext:
- case DeclaratorContext::AliasTemplateContext:
- case DeclaratorContext::MemberContext:
- case DeclaratorContext::BlockContext:
- case DeclaratorContext::ForContext:
- case DeclaratorContext::InitStmtContext:
- case DeclaratorContext::ConditionContext:
- case DeclaratorContext::CXXCatchContext:
- case DeclaratorContext::ObjCCatchContext:
- case DeclaratorContext::BlockLiteralContext:
- case DeclaratorContext::LambdaExprContext:
- case DeclaratorContext::ConversionIdContext:
- case DeclaratorContext::TrailingReturnContext:
- case DeclaratorContext::TrailingReturnVarContext:
- case DeclaratorContext::TemplateTypeArgContext:
- // FIXME: We may want to allow parameter packs in block-literal contexts
- // in the future.
- S.Diag(D.getEllipsisLoc(),
- diag::err_ellipsis_in_declarator_not_parameter);
- D.setEllipsisLoc(SourceLocation());
- break;
- }
- }
- assert(!T.isNull() && "T must not be null at the end of this function");
- if (D.isInvalidType())
- return Context.getTrivialTypeSourceInfo(T);
- return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
- }
- /// GetTypeForDeclarator - Convert the type for the specified
- /// declarator to Type instances.
- ///
- /// The result of this call will never be null, but the associated
- /// type may be a null type if there's an unrecoverable error.
- TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
- // Determine the type of the declarator. Not all forms of declarator
- // have a type.
- TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = nullptr;
- QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
- inferARCWriteback(state, T);
- return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
- }
- static void transferARCOwnershipToDeclSpec(Sema &S,
- QualType &declSpecTy,
- Qualifiers::ObjCLifetime ownership) {
- if (declSpecTy->isObjCRetainableType() &&
- declSpecTy.getObjCLifetime() == Qualifiers::OCL_None) {
- Qualifiers qs;
- qs.addObjCLifetime(ownership);
- declSpecTy = S.Context.getQualifiedType(declSpecTy, qs);
- }
- }
- static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
- Qualifiers::ObjCLifetime ownership,
- unsigned chunkIndex) {
- Sema &S = state.getSema();
- Declarator &D = state.getDeclarator();
- // Look for an explicit lifetime attribute.
- DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_ObjCOwnership)
- return;
- const char *attrStr = nullptr;
- switch (ownership) {
- case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
- case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
- case Qualifiers::OCL_Strong: attrStr = "strong"; break;
- case Qualifiers::OCL_Weak: attrStr = "weak"; break;
- case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
- }
- IdentifierLoc *Arg = new (S.Context) IdentifierLoc;
- Arg->Ident = &S.Context.Idents.get(attrStr);
- Arg->Loc = SourceLocation();
- ArgsUnion Args(Arg);
- // If there wasn't one, add one (with an invalid source location
- // so that we don't make an AttributedType for it).
- AttributeList *attr = D.getAttributePool()
- .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
- /*scope*/ nullptr, SourceLocation(),
- /*args*/ &Args, 1, AttributeList::AS_GNU);
- spliceAttrIntoList(*attr, chunk.getAttrListRef());
- // TODO: mark whether we did this inference?
- }
- /// \brief Used for transferring ownership in casts resulting in l-values.
- static void transferARCOwnership(TypeProcessingState &state,
- QualType &declSpecTy,
- Qualifiers::ObjCLifetime ownership) {
- Sema &S = state.getSema();
- Declarator &D = state.getDeclarator();
- int inner = -1;
- bool hasIndirection = false;
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &chunk = D.getTypeObject(i);
- switch (chunk.Kind) {
- case DeclaratorChunk::Paren:
- // Ignore parens.
- break;
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Pointer:
- if (inner != -1)
- hasIndirection = true;
- inner = i;
- break;
- case DeclaratorChunk::BlockPointer:
- if (inner != -1)
- transferARCOwnershipToDeclaratorChunk(state, ownership, i);
- return;
- case DeclaratorChunk::Function:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Pipe:
- return;
- }
- }
- if (inner == -1)
- return;
- DeclaratorChunk &chunk = D.getTypeObject(inner);
- if (chunk.Kind == DeclaratorChunk::Pointer) {
- if (declSpecTy->isObjCRetainableType())
- return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
- if (declSpecTy->isObjCObjectType() && hasIndirection)
- return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
- } else {
- assert(chunk.Kind == DeclaratorChunk::Array ||
- chunk.Kind == DeclaratorChunk::Reference);
- return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
- }
- }
- TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
- TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = nullptr;
- QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (getLangOpts().ObjC1) {
- Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
- if (ownership != Qualifiers::OCL_None)
- transferARCOwnership(state, declSpecTy, ownership);
- }
- return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
- }
- /// Map an AttributedType::Kind to an AttributeList::Kind.
- static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
- switch (kind) {
- case AttributedType::attr_address_space:
- return AttributeList::AT_AddressSpace;
- case AttributedType::attr_regparm:
- return AttributeList::AT_Regparm;
- case AttributedType::attr_vector_size:
- return AttributeList::AT_VectorSize;
- case AttributedType::attr_neon_vector_type:
- return AttributeList::AT_NeonVectorType;
- case AttributedType::attr_neon_polyvector_type:
- return AttributeList::AT_NeonPolyVectorType;
- case AttributedType::attr_objc_gc:
- return AttributeList::AT_ObjCGC;
- case AttributedType::attr_objc_ownership:
- case AttributedType::attr_objc_inert_unsafe_unretained:
- return AttributeList::AT_ObjCOwnership;
- case AttributedType::attr_noreturn:
- return AttributeList::AT_NoReturn;
- case AttributedType::attr_cdecl:
- return AttributeList::AT_CDecl;
- case AttributedType::attr_fastcall:
- return AttributeList::AT_FastCall;
- case AttributedType::attr_stdcall:
- return AttributeList::AT_StdCall;
- case AttributedType::attr_thiscall:
- return AttributeList::AT_ThisCall;
- case AttributedType::attr_regcall:
- return AttributeList::AT_RegCall;
- case AttributedType::attr_pascal:
- return AttributeList::AT_Pascal;
- case AttributedType::attr_swiftcall:
- return AttributeList::AT_SwiftCall;
- case AttributedType::attr_vectorcall:
- return AttributeList::AT_VectorCall;
- case AttributedType::attr_pcs:
- case AttributedType::attr_pcs_vfp:
- return AttributeList::AT_Pcs;
- case AttributedType::attr_inteloclbicc:
- return AttributeList::AT_IntelOclBicc;
- case AttributedType::attr_ms_abi:
- return AttributeList::AT_MSABI;
- case AttributedType::attr_sysv_abi:
- return AttributeList::AT_SysVABI;
- case AttributedType::attr_preserve_most:
- return AttributeList::AT_PreserveMost;
- case AttributedType::attr_preserve_all:
- return AttributeList::AT_PreserveAll;
- case AttributedType::attr_ptr32:
- return AttributeList::AT_Ptr32;
- case AttributedType::attr_ptr64:
- return AttributeList::AT_Ptr64;
- case AttributedType::attr_sptr:
- return AttributeList::AT_SPtr;
- case AttributedType::attr_uptr:
- return AttributeList::AT_UPtr;
- case AttributedType::attr_nonnull:
- return AttributeList::AT_TypeNonNull;
- case AttributedType::attr_nullable:
- return AttributeList::AT_TypeNullable;
- case AttributedType::attr_null_unspecified:
- return AttributeList::AT_TypeNullUnspecified;
- case AttributedType::attr_objc_kindof:
- return AttributeList::AT_ObjCKindOf;
- case AttributedType::attr_ns_returns_retained:
- return AttributeList::AT_NSReturnsRetained;
- }
- llvm_unreachable("unexpected attribute kind!");
- }
- static void fillAttributedTypeLoc(AttributedTypeLoc TL,
- const AttributeList *attrs,
- const AttributeList *DeclAttrs = nullptr) {
- // DeclAttrs and attrs cannot be both empty.
- assert((attrs || DeclAttrs) &&
- "no type attributes in the expected location!");
- AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind());
- // Try to search for an attribute of matching kind in attrs list.
- while (attrs && attrs->getKind() != parsedKind)
- attrs = attrs->getNext();
- if (!attrs) {
- // No matching type attribute in attrs list found.
- // Try searching through C++11 attributes in the declarator attribute list.
- while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() ||
- DeclAttrs->getKind() != parsedKind))
- DeclAttrs = DeclAttrs->getNext();
- attrs = DeclAttrs;
- }
- assert(attrs && "no matching type attribute in expected location!");
- TL.setAttrNameLoc(attrs->getLoc());
- if (TL.hasAttrExprOperand()) {
- assert(attrs->isArgExpr(0) && "mismatched attribute operand kind");
- TL.setAttrExprOperand(attrs->getArgAsExpr(0));
- } else if (TL.hasAttrEnumOperand()) {
- assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) &&
- "unexpected attribute operand kind");
- if (attrs->isArgIdent(0))
- TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc);
- else
- TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc());
- }
- // FIXME: preserve this information to here.
- if (TL.hasAttrOperand())
- TL.setAttrOperandParensRange(SourceRange());
- }
- namespace {
- class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
- ASTContext &Context;
- const DeclSpec &DS;
- public:
- TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
- : Context(Context), DS(DS) {}
- void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, DS.getAttributes().getList());
- Visit(TL.getModifiedLoc());
- }
- void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
- Visit(TL.getUnqualifiedLoc());
- }
- void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
- }
- void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
- // FIXME. We should have DS.getTypeSpecTypeEndLoc(). But, it requires
- // addition field. What we have is good enough for dispay of location
- // of 'fixit' on interface name.
- TL.setNameEndLoc(DS.getLocEnd());
- }
- void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
- TypeSourceInfo *RepTInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo);
- TL.copy(RepTInfo->getTypeLoc());
- }
- void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
- TypeSourceInfo *RepTInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo);
- TL.copy(RepTInfo->getTypeLoc());
- }
- void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- // If we got no declarator info from previous Sema routines,
- // just fill with the typespec loc.
- if (!TInfo) {
- TL.initialize(Context, DS.getTypeSpecTypeNameLoc());
- return;
- }
- TypeLoc OldTL = TInfo->getTypeLoc();
- if (TInfo->getType()->getAs<ElaboratedType>()) {
- ElaboratedTypeLoc ElabTL = OldTL.castAs<ElaboratedTypeLoc>();
- TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
- .castAs<TemplateSpecializationTypeLoc>();
- TL.copy(NamedTL);
- } else {
- TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
- assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
- }
-
- }
- void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
- TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- }
- void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
- TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.setUnderlyingTInfo(TInfo);
- }
- void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
- // FIXME: This holds only because we only have one unary transform.
- assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
- TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.setUnderlyingTInfo(TInfo);
- }
- void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
- // By default, use the source location of the type specifier.
- TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
- if (TL.needsExtraLocalData()) {
- // Set info for the written builtin specifiers.
- TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
- // Try to have a meaningful source location.
- if (TL.getWrittenSignSpec() != TSS_unspecified)
- TL.expandBuiltinRange(DS.getTypeSpecSignLoc());
- if (TL.getWrittenWidthSpec() != TSW_unspecified)
- TL.expandBuiltinRange(DS.getTypeSpecWidthRange());
- }
- }
- void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- ElaboratedTypeKeyword Keyword
- = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
- if (DS.getTypeSpecType() == TST_typename) {
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- if (TInfo) {
- TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>());
- return;
- }
- }
- TL.setElaboratedKeywordLoc(Keyword != ETK_None
- ? DS.getTypeSpecTypeLoc()
- : SourceLocation());
- const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
- Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
- }
- void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
- assert(DS.getTypeSpecType() == TST_typename);
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- assert(TInfo);
- TL.copy(TInfo->getTypeLoc().castAs<DependentNameTypeLoc>());
- }
- void VisitDependentTemplateSpecializationTypeLoc(
- DependentTemplateSpecializationTypeLoc TL) {
- assert(DS.getTypeSpecType() == TST_typename);
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- assert(TInfo);
- TL.copy(
- TInfo->getTypeLoc().castAs<DependentTemplateSpecializationTypeLoc>());
- }
- void VisitTagTypeLoc(TagTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
- }
- void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
- // An AtomicTypeLoc can come from either an _Atomic(...) type specifier
- // or an _Atomic qualifier.
- if (DS.getTypeSpecType() == DeclSpec::TST_atomic) {
- TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- assert(TInfo);
- TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
- } else {
- TL.setKWLoc(DS.getAtomicSpecLoc());
- // No parens, to indicate this was spelled as an _Atomic qualifier.
- TL.setParensRange(SourceRange());
- Visit(TL.getValueLoc());
- }
- }
- void VisitPipeTypeLoc(PipeTypeLoc TL) {
- TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TypeSourceInfo *TInfo = nullptr;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
- }
- void VisitTypeLoc(TypeLoc TL) {
- // FIXME: add other typespec types and change this to an assert.
- TL.initialize(Context, DS.getTypeSpecTypeLoc());
- }
- };
- class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
- ASTContext &Context;
- const DeclaratorChunk &Chunk;
- public:
- DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
- : Context(Context), Chunk(Chunk) {}
- void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
- llvm_unreachable("qualified type locs not expected here!");
- }
- void VisitDecayedTypeLoc(DecayedTypeLoc TL) {
- llvm_unreachable("decayed type locs not expected here!");
- }
- void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, Chunk.getAttrs());
- }
- void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
- // nothing
- }
- void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
- TL.setCaretLoc(Chunk.Loc);
- }
- void VisitPointerTypeLoc(PointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Pointer);
- TL.setStarLoc(Chunk.Loc);
- }
- void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Pointer);
- TL.setStarLoc(Chunk.Loc);
- }
- void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
- const CXXScopeSpec& SS = Chunk.Mem.Scope();
- NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
- const Type* ClsTy = TL.getClass();
- QualType ClsQT = QualType(ClsTy, 0);
- TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
- // Now copy source location info into the type loc component.
- TypeLoc ClsTL = ClsTInfo->getTypeLoc();
- switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
- {
- DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>();
- DNTLoc.setElaboratedKeywordLoc(SourceLocation());
- DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
- DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
- }
- break;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- if (isa<ElaboratedType>(ClsTy)) {
- ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>();
- ETLoc.setElaboratedKeywordLoc(SourceLocation());
- ETLoc.setQualifierLoc(NNSLoc.getPrefix());
- TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
- NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
- } else {
- ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
- }
- break;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- llvm_unreachable("Nested-name-specifier must name a type");
- }
- // Finally fill in MemberPointerLocInfo fields.
- TL.setStarLoc(Chunk.Loc);
- TL.setClassTInfo(ClsTInfo);
- }
- void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Reference);
- // 'Amp' is misleading: this might have been originally
- /// spelled with AmpAmp.
- TL.setAmpLoc(Chunk.Loc);
- }
- void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Reference);
- assert(!Chunk.Ref.LValueRef);
- TL.setAmpAmpLoc(Chunk.Loc);
- }
- void VisitArrayTypeLoc(ArrayTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Array);
- TL.setLBracketLoc(Chunk.Loc);
- TL.setRBracketLoc(Chunk.EndLoc);
- TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
- }
- void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Function);
- TL.setLocalRangeBegin(Chunk.Loc);
- TL.setLocalRangeEnd(Chunk.EndLoc);
- const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
- TL.setLParenLoc(FTI.getLParenLoc());
- TL.setRParenLoc(FTI.getRParenLoc());
- for (unsigned i = 0, e = TL.getNumParams(), tpi = 0; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
- TL.setParam(tpi++, Param);
- }
- TL.setExceptionSpecRange(FTI.getExceptionSpecRange());
- }
- void VisitParenTypeLoc(ParenTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Paren);
- TL.setLParenLoc(Chunk.Loc);
- TL.setRParenLoc(Chunk.EndLoc);
- }
- void VisitPipeTypeLoc(PipeTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Pipe);
- TL.setKWLoc(Chunk.Loc);
- }
- void VisitTypeLoc(TypeLoc TL) {
- llvm_unreachable("unsupported TypeLoc kind in declarator!");
- }
- };
- } // end anonymous namespace
- static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
- SourceLocation Loc;
- switch (Chunk.Kind) {
- case DeclaratorChunk::Function:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Pipe:
- llvm_unreachable("cannot be _Atomic qualified");
- case DeclaratorChunk::Pointer:
- Loc = SourceLocation::getFromRawEncoding(Chunk.Ptr.AtomicQualLoc);
- break;
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- // FIXME: Provide a source location for the _Atomic keyword.
- break;
- }
- ATL.setKWLoc(Loc);
- ATL.setParensRange(SourceRange());
- }
- static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
- const AttributeList *Attrs) {
- while (Attrs && Attrs->getKind() != AttributeList::AT_AddressSpace)
- Attrs = Attrs->getNext();
- assert(Attrs && "no address_space attribute found at the expected location!");
-
- DASTL.setAttrNameLoc(Attrs->getLoc());
- DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0));
- DASTL.setAttrOperandParensRange(SourceRange());
- }
- /// \brief Create and instantiate a TypeSourceInfo with type source information.
- ///
- /// \param T QualType referring to the type as written in source code.
- ///
- /// \param ReturnTypeInfo For declarators whose return type does not show
- /// up in the normal place in the declaration specifiers (such as a C++
- /// conversion function), this pointer will refer to a type source information
- /// for that return type.
- TypeSourceInfo *
- Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
- TypeSourceInfo *ReturnTypeInfo) {
- TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
- UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
- const AttributeList *DeclAttrs = D.getAttributes();
- // Handle parameter packs whose type is a pack expansion.
- if (isa<PackExpansionType>(T)) {
- CurrTL.castAs<PackExpansionTypeLoc>().setEllipsisLoc(D.getEllipsisLoc());
- CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
- }
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-
- if (DependentAddressSpaceTypeLoc DASTL =
- CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
- fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
- CurrTL = DASTL.getPointeeTypeLoc().getUnqualifiedLoc();
- }
- // An AtomicTypeLoc might be produced by an atomic qualifier in this
- // declarator chunk.
- if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) {
- fillAtomicQualLoc(ATL, D.getTypeObject(i));
- CurrTL = ATL.getValueLoc().getUnqualifiedLoc();
- }
- while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
- fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs);
- CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
- }
- // FIXME: Ordering here?
- while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
- CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
- DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
- CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
- }
- // If we have different source information for the return type, use
- // that. This really only applies to C++ conversion functions.
- if (ReturnTypeInfo) {
- TypeLoc TL = ReturnTypeInfo->getTypeLoc();
- assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
- memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
- } else {
- TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
- }
- return TInfo;
- }
- /// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
- ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
- // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
- // and Sema during declaration parsing. Try deallocating/caching them when
- // it's appropriate, instead of allocating them and keeping them around.
- LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
- TypeAlignment);
- new (LocT) LocInfoType(T, TInfo);
- assert(LocT->getTypeClass() != T->getTypeClass() &&
- "LocInfoType's TypeClass conflicts with an existing Type class");
- return ParsedType::make(QualType(LocT, 0));
- }
- void LocInfoType::getAsStringInternal(std::string &Str,
- const PrintingPolicy &Policy) const {
- llvm_unreachable("LocInfoType leaked into the type system; an opaque TypeTy*"
- " was used directly instead of getting the QualType through"
- " GetTypeFromParser");
- }
- TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
- // C99 6.7.6: Type names have no identifier. This is already validated by
- // the parser.
- assert(D.getIdentifier() == nullptr &&
- "Type name should have no identifier!");
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType T = TInfo->getType();
- if (D.isInvalidType())
- return true;
- // Make sure there are no unused decl attributes on the declarator.
- // We don't want to do this for ObjC parameters because we're going
- // to apply them to the actual parameter declaration.
- // Likewise, we don't want to do this for alias declarations, because
- // we are actually going to build a declaration from this eventually.
- if (D.getContext() != DeclaratorContext::ObjCParameterContext &&
- D.getContext() != DeclaratorContext::AliasDeclContext &&
- D.getContext() != DeclaratorContext::AliasTemplateContext)
- checkUnusedDeclAttributes(D);
- if (getLangOpts().CPlusPlus) {
- // Check that there are no default arguments (C++ only).
- CheckExtraCXXDefaultArguments(D);
- }
- return CreateParsedType(T, TInfo);
- }
- ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
- QualType T = Context.getObjCInstanceType();
- TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
- return CreateParsedType(T, TInfo);
- }
- //===----------------------------------------------------------------------===//
- // Type Attribute Processing
- //===----------------------------------------------------------------------===//
- /// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an expression
- /// is uninstantiated. If instantiated it will apply the appropriate address space
- /// to the type. This function allows dependent template variables to be used in
- /// conjunction with the address_space attribute
- QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
- SourceLocation AttrLoc) {
- if (!AddrSpace->isValueDependent()) {
- // If this type is already address space qualified, reject it.
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified
- // by qualifiers for two or more different address spaces."
- if (T.getAddressSpace() != LangAS::Default) {
- Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
- return QualType();
- }
- llvm::APSInt addrSpace(32);
- if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) {
- Diag(AttrLoc, diag::err_attribute_argument_type)
- << "'address_space'" << AANT_ArgumentIntegerConstant
- << AddrSpace->getSourceRange();
- return QualType();
- }
- // Bounds checking.
- if (addrSpace.isSigned()) {
- if (addrSpace.isNegative()) {
- Diag(AttrLoc, diag::err_attribute_address_space_negative)
- << AddrSpace->getSourceRange();
- return QualType();
- }
- addrSpace.setIsSigned(false);
- }
- llvm::APSInt max(addrSpace.getBitWidth());
- max =
- Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace;
- if (addrSpace > max) {
- Diag(AttrLoc, diag::err_attribute_address_space_too_high)
- << (unsigned)max.getZExtValue() << AddrSpace->getSourceRange();
- return QualType();
- }
- LangAS ASIdx =
- getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue()));
- return Context.getAddrSpaceQualType(T, ASIdx);
- }
- // A check with similar intentions as checking if a type already has an
- // address space except for on a dependent types, basically if the
- // current type is already a DependentAddressSpaceType then its already
- // lined up to have another address space on it and we can't have
- // multiple address spaces on the one pointer indirection
- if (T->getAs<DependentAddressSpaceType>()) {
- Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
- return QualType();
- }
- return Context.getDependentAddressSpaceType(T, AddrSpace, AttrLoc);
- }
- /// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
- /// specified type. The attribute contains 1 argument, the id of the address
- /// space for the type.
- static void HandleAddressSpaceTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S){
- // If this type is already address space qualified, reject it.
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
- // qualifiers for two or more different address spaces."
- if (Type.getAddressSpace() != LangAS::Default) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
- Attr.setInvalid();
- return;
- }
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
- // qualified by an address-space qualifier."
- if (Type->isFunctionType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type);
- Attr.setInvalid();
- return;
- }
- LangAS ASIdx;
- if (Attr.getKind() == AttributeList::AT_AddressSpace) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- Expr *ASArgExpr;
- if (Attr.isArgIdent(0)) {
- // Special case where the argument is a template id.
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
- ExprResult AddrSpace = S.ActOnIdExpression(
- S.getCurScope(), SS, TemplateKWLoc, id, false, false);
- if (AddrSpace.isInvalid())
- return;
- ASArgExpr = static_cast<Expr *>(AddrSpace.get());
- } else {
- ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- }
- // Create the DependentAddressSpaceType or append an address space onto
- // the type.
- QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
- if (!T.isNull())
- Type = T;
- else
- Attr.setInvalid();
- } else {
- // The keyword-based type attributes imply which address space to use.
- switch (Attr.getKind()) {
- case AttributeList::AT_OpenCLGlobalAddressSpace:
- ASIdx = LangAS::opencl_global; break;
- case AttributeList::AT_OpenCLLocalAddressSpace:
- ASIdx = LangAS::opencl_local; break;
- case AttributeList::AT_OpenCLConstantAddressSpace:
- ASIdx = LangAS::opencl_constant; break;
- case AttributeList::AT_OpenCLGenericAddressSpace:
- ASIdx = LangAS::opencl_generic; break;
- case AttributeList::AT_OpenCLPrivateAddressSpace:
- ASIdx = LangAS::opencl_private; break;
- default:
- llvm_unreachable("Invalid address space");
- }
- Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
- }
- }
- /// Does this type have a "direct" ownership qualifier? That is,
- /// is it written like "__strong id", as opposed to something like
- /// "typeof(foo)", where that happens to be strong?
- static bool hasDirectOwnershipQualifier(QualType type) {
- // Fast path: no qualifier at all.
- assert(type.getQualifiers().hasObjCLifetime());
- while (true) {
- // __strong id
- if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
- if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
- return true;
- type = attr->getModifiedType();
- // X *__strong (...)
- } else if (const ParenType *paren = dyn_cast<ParenType>(type)) {
- type = paren->getInnerType();
- // That's it for things we want to complain about. In particular,
- // we do not want to look through typedefs, typeof(expr),
- // typeof(type), or any other way that the type is somehow
- // abstracted.
- } else {
- return false;
- }
- }
- }
- /// handleObjCOwnershipTypeAttr - Process an objc_ownership
- /// attribute on the specified type.
- ///
- /// Returns 'true' if the attribute was handled.
- static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
- bool NonObjCPointer = false;
- if (!type->isDependentType() && !type->isUndeducedType()) {
- if (const PointerType *ptr = type->getAs<PointerType>()) {
- QualType pointee = ptr->getPointeeType();
- if (pointee->isObjCRetainableType() || pointee->isPointerType())
- return false;
- // It is important not to lose the source info that there was an attribute
- // applied to non-objc pointer. We will create an attributed type but
- // its type will be the same as the original type.
- NonObjCPointer = true;
- } else if (!type->isObjCRetainableType()) {
- return false;
- }
- // Don't accept an ownership attribute in the declspec if it would
- // just be the return type of a block pointer.
- if (state.isProcessingDeclSpec()) {
- Declarator &D = state.getDeclarator();
- if (maybeMovePastReturnType(D, D.getNumTypeObjects(),
- /*onlyBlockPointers=*/true))
- return false;
- }
- }
- Sema &S = state.getSema();
- SourceLocation AttrLoc = attr.getLoc();
- if (AttrLoc.isMacroID())
- AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
- if (!attr.isArgIdent(0)) {
- S.Diag(AttrLoc, diag::err_attribute_argument_type)
- << attr.getName() << AANT_ArgumentString;
- attr.setInvalid();
- return true;
- }
- IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
- Qualifiers::ObjCLifetime lifetime;
- if (II->isStr("none"))
- lifetime = Qualifiers::OCL_ExplicitNone;
- else if (II->isStr("strong"))
- lifetime = Qualifiers::OCL_Strong;
- else if (II->isStr("weak"))
- lifetime = Qualifiers::OCL_Weak;
- else if (II->isStr("autoreleasing"))
- lifetime = Qualifiers::OCL_Autoreleasing;
- else {
- S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
- << attr.getName() << II;
- attr.setInvalid();
- return true;
- }
- // Just ignore lifetime attributes other than __weak and __unsafe_unretained
- // outside of ARC mode.
- if (!S.getLangOpts().ObjCAutoRefCount &&
- lifetime != Qualifiers::OCL_Weak &&
- lifetime != Qualifiers::OCL_ExplicitNone) {
- return true;
- }
- SplitQualType underlyingType = type.split();
- // Check for redundant/conflicting ownership qualifiers.
- if (Qualifiers::ObjCLifetime previousLifetime
- = type.getQualifiers().getObjCLifetime()) {
- // If it's written directly, that's an error.
- if (hasDirectOwnershipQualifier(type)) {
- S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
- << type;
- return true;
- }
- // Otherwise, if the qualifiers actually conflict, pull sugar off
- // and remove the ObjCLifetime qualifiers.
- if (previousLifetime != lifetime) {
- // It's possible to have multiple local ObjCLifetime qualifiers. We
- // can't stop after we reach a type that is directly qualified.
- const Type *prevTy = nullptr;
- while (!prevTy || prevTy != underlyingType.Ty) {
- prevTy = underlyingType.Ty;
- underlyingType = underlyingType.getSingleStepDesugaredType();
- }
- underlyingType.Quals.removeObjCLifetime();
- }
- }
- underlyingType.Quals.addObjCLifetime(lifetime);
- if (NonObjCPointer) {
- StringRef name = attr.getName()->getName();
- switch (lifetime) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- break;
- case Qualifiers::OCL_Strong: name = "__strong"; break;
- case Qualifiers::OCL_Weak: name = "__weak"; break;
- case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
- }
- S.Diag(AttrLoc, diag::warn_type_attribute_wrong_type) << name
- << TDS_ObjCObjOrBlock << type;
- }
- // Don't actually add the __unsafe_unretained qualifier in non-ARC files,
- // because having both 'T' and '__unsafe_unretained T' exist in the type
- // system causes unfortunate widespread consistency problems. (For example,
- // they're not considered compatible types, and we mangle them identicially
- // as template arguments.) These problems are all individually fixable,
- // but it's easier to just not add the qualifier and instead sniff it out
- // in specific places using isObjCInertUnsafeUnretainedType().
- //
- // Doing this does means we miss some trivial consistency checks that
- // would've triggered in ARC, but that's better than trying to solve all
- // the coexistence problems with __unsafe_unretained.
- if (!S.getLangOpts().ObjCAutoRefCount &&
- lifetime == Qualifiers::OCL_ExplicitNone) {
- type = S.Context.getAttributedType(
- AttributedType::attr_objc_inert_unsafe_unretained,
- type, type);
- return true;
- }
- QualType origType = type;
- if (!NonObjCPointer)
- type = S.Context.getQualifiedType(underlyingType);
- // If we have a valid source location for the attribute, use an
- // AttributedType instead.
- if (AttrLoc.isValid())
- type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
- origType, type);
- auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
- unsigned diagnostic, QualType type) {
- if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
- S.DelayedDiagnostics.add(
- sema::DelayedDiagnostic::makeForbiddenType(
- S.getSourceManager().getExpansionLoc(loc),
- diagnostic, type, /*ignored*/ 0));
- } else {
- S.Diag(loc, diagnostic);
- }
- };
- // Sometimes, __weak isn't allowed.
- if (lifetime == Qualifiers::OCL_Weak &&
- !S.getLangOpts().ObjCWeak && !NonObjCPointer) {
- // Use a specialized diagnostic if the runtime just doesn't support them.
- unsigned diagnostic =
- (S.getLangOpts().ObjCWeakRuntime ? diag::err_arc_weak_disabled
- : diag::err_arc_weak_no_runtime);
- // In any case, delay the diagnostic until we know what we're parsing.
- diagnoseOrDelay(S, AttrLoc, diagnostic, type);
- attr.setInvalid();
- return true;
- }
- // Forbid __weak for class objects marked as
- // objc_arc_weak_reference_unavailable
- if (lifetime == Qualifiers::OCL_Weak) {
- if (const ObjCObjectPointerType *ObjT =
- type->getAs<ObjCObjectPointerType>()) {
- if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
- if (Class->isArcWeakrefUnavailable()) {
- S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
- S.Diag(ObjT->getInterfaceDecl()->getLocation(),
- diag::note_class_declared);
- }
- }
- }
- }
- return true;
- }
- /// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type
- /// attribute on the specified type. Returns true to indicate that
- /// the attribute was handled, false to indicate that the type does
- /// not permit the attribute.
- static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
- Sema &S = state.getSema();
- // Delay if this isn't some kind of pointer.
- if (!type->isPointerType() &&
- !type->isObjCObjectPointerType() &&
- !type->isBlockPointerType())
- return false;
- if (type.getObjCGCAttr() != Qualifiers::GCNone) {
- S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
- attr.setInvalid();
- return true;
- }
-
- // Check the attribute arguments.
- if (!attr.isArgIdent(0)) {
- S.Diag(attr.getLoc(), diag::err_attribute_argument_type)
- << attr.getName() << AANT_ArgumentString;
- attr.setInvalid();
- return true;
- }
- Qualifiers::GC GCAttr;
- if (attr.getNumArgs() > 1) {
- S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << attr.getName() << 1;
- attr.setInvalid();
- return true;
- }
- IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
- if (II->isStr("weak"))
- GCAttr = Qualifiers::Weak;
- else if (II->isStr("strong"))
- GCAttr = Qualifiers::Strong;
- else {
- S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
- << attr.getName() << II;
- attr.setInvalid();
- return true;
- }
- QualType origType = type;
- type = S.Context.getObjCGCQualType(origType, GCAttr);
- // Make an attributed type to preserve the source information.
- if (attr.getLoc().isValid())
- type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
- origType, type);
- return true;
- }
- namespace {
- /// A helper class to unwrap a type down to a function for the
- /// purposes of applying attributes there.
- ///
- /// Use:
- /// FunctionTypeUnwrapper unwrapped(SemaRef, T);
- /// if (unwrapped.isFunctionType()) {
- /// const FunctionType *fn = unwrapped.get();
- /// // change fn somehow
- /// T = unwrapped.wrap(fn);
- /// }
- struct FunctionTypeUnwrapper {
- enum WrapKind {
- Desugar,
- Attributed,
- Parens,
- Pointer,
- BlockPointer,
- Reference,
- MemberPointer
- };
- QualType Original;
- const FunctionType *Fn;
- SmallVector<unsigned char /*WrapKind*/, 8> Stack;
- FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
- while (true) {
- const Type *Ty = T.getTypePtr();
- if (isa<FunctionType>(Ty)) {
- Fn = cast<FunctionType>(Ty);
- return;
- } else if (isa<ParenType>(Ty)) {
- T = cast<ParenType>(Ty)->getInnerType();
- Stack.push_back(Parens);
- } else if (isa<PointerType>(Ty)) {
- T = cast<PointerType>(Ty)->getPointeeType();
- Stack.push_back(Pointer);
- } else if (isa<BlockPointerType>(Ty)) {
- T = cast<BlockPointerType>(Ty)->getPointeeType();
- Stack.push_back(BlockPointer);
- } else if (isa<MemberPointerType>(Ty)) {
- T = cast<MemberPointerType>(Ty)->getPointeeType();
- Stack.push_back(MemberPointer);
- } else if (isa<ReferenceType>(Ty)) {
- T = cast<ReferenceType>(Ty)->getPointeeType();
- Stack.push_back(Reference);
- } else if (isa<AttributedType>(Ty)) {
- T = cast<AttributedType>(Ty)->getEquivalentType();
- Stack.push_back(Attributed);
- } else {
- const Type *DTy = Ty->getUnqualifiedDesugaredType();
- if (Ty == DTy) {
- Fn = nullptr;
- return;
- }
- T = QualType(DTy, 0);
- Stack.push_back(Desugar);
- }
- }
- }
- bool isFunctionType() const { return (Fn != nullptr); }
- const FunctionType *get() const { return Fn; }
- QualType wrap(Sema &S, const FunctionType *New) {
- // If T wasn't modified from the unwrapped type, do nothing.
- if (New == get()) return Original;
- Fn = New;
- return wrap(S.Context, Original, 0);
- }
- private:
- QualType wrap(ASTContext &C, QualType Old, unsigned I) {
- if (I == Stack.size())
- return C.getQualifiedType(Fn, Old.getQualifiers());
- // Build up the inner type, applying the qualifiers from the old
- // type to the new type.
- SplitQualType SplitOld = Old.split();
- // As a special case, tail-recurse if there are no qualifiers.
- if (SplitOld.Quals.empty())
- return wrap(C, SplitOld.Ty, I);
- return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
- }
- QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
- if (I == Stack.size()) return QualType(Fn, 0);
- switch (static_cast<WrapKind>(Stack[I++])) {
- case Desugar:
- // This is the point at which we potentially lose source
- // information.
- return wrap(C, Old->getUnqualifiedDesugaredType(), I);
- case Attributed:
- return wrap(C, cast<AttributedType>(Old)->getEquivalentType(), I);
- case Parens: {
- QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
- return C.getParenType(New);
- }
- case Pointer: {
- QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
- return C.getPointerType(New);
- }
- case BlockPointer: {
- QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
- return C.getBlockPointerType(New);
- }
- case MemberPointer: {
- const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
- QualType New = wrap(C, OldMPT->getPointeeType(), I);
- return C.getMemberPointerType(New, OldMPT->getClass());
- }
- case Reference: {
- const ReferenceType *OldRef = cast<ReferenceType>(Old);
- QualType New = wrap(C, OldRef->getPointeeType(), I);
- if (isa<LValueReferenceType>(OldRef))
- return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
- else
- return C.getRValueReferenceType(New);
- }
- }
- llvm_unreachable("unknown wrapping kind");
- }
- };
- } // end anonymous namespace
- static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
- AttributeList &Attr,
- QualType &Type) {
- Sema &S = State.getSema();
- AttributeList::Kind Kind = Attr.getKind();
- QualType Desugared = Type;
- const AttributedType *AT = dyn_cast<AttributedType>(Type);
- while (AT) {
- AttributedType::Kind CurAttrKind = AT->getAttrKind();
- // You cannot specify duplicate type attributes, so if the attribute has
- // already been applied, flag it.
- if (getAttrListKind(CurAttrKind) == Kind) {
- S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
- << Attr.getName();
- return true;
- }
- // You cannot have both __sptr and __uptr on the same type, nor can you
- // have __ptr32 and __ptr64.
- if ((CurAttrKind == AttributedType::attr_ptr32 &&
- Kind == AttributeList::AT_Ptr64) ||
- (CurAttrKind == AttributedType::attr_ptr64 &&
- Kind == AttributeList::AT_Ptr32)) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "'__ptr32'" << "'__ptr64'";
- return true;
- } else if ((CurAttrKind == AttributedType::attr_sptr &&
- Kind == AttributeList::AT_UPtr) ||
- (CurAttrKind == AttributedType::attr_uptr &&
- Kind == AttributeList::AT_SPtr)) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "'__sptr'" << "'__uptr'";
- return true;
- }
-
- Desugared = AT->getEquivalentType();
- AT = dyn_cast<AttributedType>(Desugared);
- }
- // Pointer type qualifiers can only operate on pointer types, but not
- // pointer-to-member types.
- if (!isa<PointerType>(Desugared)) {
- if (Type->isMemberPointerType())
- S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers)
- << Attr.getName();
- else
- S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << Attr.getName() << 0;
- return true;
- }
- AttributedType::Kind TAK;
- switch (Kind) {
- default: llvm_unreachable("Unknown attribute kind");
- case AttributeList::AT_Ptr32: TAK = AttributedType::attr_ptr32; break;
- case AttributeList::AT_Ptr64: TAK = AttributedType::attr_ptr64; break;
- case AttributeList::AT_SPtr: TAK = AttributedType::attr_sptr; break;
- case AttributeList::AT_UPtr: TAK = AttributedType::attr_uptr; break;
- }
- Type = S.Context.getAttributedType(TAK, Type, Type);
- return false;
- }
- bool Sema::checkNullabilityTypeSpecifier(QualType &type,
- NullabilityKind nullability,
- SourceLocation nullabilityLoc,
- bool isContextSensitive,
- bool allowOnArrayType) {
- recordNullabilitySeen(*this, nullabilityLoc);
- // Check for existing nullability attributes on the type.
- QualType desugared = type;
- while (auto attributed = dyn_cast<AttributedType>(desugared.getTypePtr())) {
- // Check whether there is already a null
- if (auto existingNullability = attributed->getImmediateNullability()) {
- // Duplicated nullability.
- if (nullability == *existingNullability) {
- Diag(nullabilityLoc, diag::warn_nullability_duplicate)
- << DiagNullabilityKind(nullability, isContextSensitive)
- << FixItHint::CreateRemoval(nullabilityLoc);
- break;
- }
- // Conflicting nullability.
- Diag(nullabilityLoc, diag::err_nullability_conflicting)
- << DiagNullabilityKind(nullability, isContextSensitive)
- << DiagNullabilityKind(*existingNullability, false);
- return true;
- }
- desugared = attributed->getModifiedType();
- }
- // If there is already a different nullability specifier, complain.
- // This (unlike the code above) looks through typedefs that might
- // have nullability specifiers on them, which means we cannot
- // provide a useful Fix-It.
- if (auto existingNullability = desugared->getNullability(Context)) {
- if (nullability != *existingNullability) {
- Diag(nullabilityLoc, diag::err_nullability_conflicting)
- << DiagNullabilityKind(nullability, isContextSensitive)
- << DiagNullabilityKind(*existingNullability, false);
- // Try to find the typedef with the existing nullability specifier.
- if (auto typedefType = desugared->getAs<TypedefType>()) {
- TypedefNameDecl *typedefDecl = typedefType->getDecl();
- QualType underlyingType = typedefDecl->getUnderlyingType();
- if (auto typedefNullability
- = AttributedType::stripOuterNullability(underlyingType)) {
- if (*typedefNullability == *existingNullability) {
- Diag(typedefDecl->getLocation(), diag::note_nullability_here)
- << DiagNullabilityKind(*existingNullability, false);
- }
- }
- }
- return true;
- }
- }
- // If this definitely isn't a pointer type, reject the specifier.
- if (!desugared->canHaveNullability() &&
- !(allowOnArrayType && desugared->isArrayType())) {
- Diag(nullabilityLoc, diag::err_nullability_nonpointer)
- << DiagNullabilityKind(nullability, isContextSensitive) << type;
- return true;
- }
-
- // For the context-sensitive keywords/Objective-C property
- // attributes, require that the type be a single-level pointer.
- if (isContextSensitive) {
- // Make sure that the pointee isn't itself a pointer type.
- const Type *pointeeType;
- if (desugared->isArrayType())
- pointeeType = desugared->getArrayElementTypeNoTypeQual();
- else
- pointeeType = desugared->getPointeeType().getTypePtr();
- if (pointeeType->isAnyPointerType() ||
- pointeeType->isObjCObjectPointerType() ||
- pointeeType->isMemberPointerType()) {
- Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
- << DiagNullabilityKind(nullability, true)
- << type;
- Diag(nullabilityLoc, diag::note_nullability_type_specifier)
- << DiagNullabilityKind(nullability, false)
- << type
- << FixItHint::CreateReplacement(nullabilityLoc,
- getNullabilitySpelling(nullability));
- return true;
- }
- }
- // Form the attributed type.
- type = Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(nullability), type, type);
- return false;
- }
- bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
- if (isa<ObjCTypeParamType>(type)) {
- // Build the attributed type to record where __kindof occurred.
- type = Context.getAttributedType(AttributedType::attr_objc_kindof,
- type, type);
- return false;
- }
- // Find out if it's an Objective-C object or object pointer type;
- const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
- const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
- : type->getAs<ObjCObjectType>();
- // If not, we can't apply __kindof.
- if (!objType) {
- // FIXME: Handle dependent types that aren't yet object types.
- Diag(loc, diag::err_objc_kindof_nonobject)
- << type;
- return true;
- }
- // Rebuild the "equivalent" type, which pushes __kindof down into
- // the object type.
- // There is no need to apply kindof on an unqualified id type.
- QualType equivType = Context.getObjCObjectType(
- objType->getBaseType(), objType->getTypeArgsAsWritten(),
- objType->getProtocols(),
- /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
- // If we started with an object pointer type, rebuild it.
- if (ptrType) {
- equivType = Context.getObjCObjectPointerType(equivType);
- if (auto nullability = type->getNullability(Context)) {
- auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
- equivType = Context.getAttributedType(attrKind, equivType, equivType);
- }
- }
- // Build the attributed type to record where __kindof occurred.
- type = Context.getAttributedType(AttributedType::attr_objc_kindof,
- type,
- equivType);
- return false;
- }
- /// Map a nullability attribute kind to a nullability kind.
- static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {
- switch (kind) {
- case AttributeList::AT_TypeNonNull:
- return NullabilityKind::NonNull;
- case AttributeList::AT_TypeNullable:
- return NullabilityKind::Nullable;
- case AttributeList::AT_TypeNullUnspecified:
- return NullabilityKind::Unspecified;
- default:
- llvm_unreachable("not a nullability attribute kind");
- }
- }
- /// Distribute a nullability type attribute that cannot be applied to
- /// the type specifier to a pointer, block pointer, or member pointer
- /// declarator, complaining if necessary.
- ///
- /// \returns true if the nullability annotation was distributed, false
- /// otherwise.
- static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
- QualType type,
- AttributeList &attr) {
- Declarator &declarator = state.getDeclarator();
- /// Attempt to move the attribute to the specified chunk.
- auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool {
- // If there is already a nullability attribute there, don't add
- // one.
- if (hasNullabilityAttr(chunk.getAttrListRef()))
- return false;
- // Complain about the nullability qualifier being in the wrong
- // place.
- enum {
- PK_Pointer,
- PK_BlockPointer,
- PK_MemberPointer,
- PK_FunctionPointer,
- PK_MemberFunctionPointer,
- } pointerKind
- = chunk.Kind == DeclaratorChunk::Pointer ? (inFunction ? PK_FunctionPointer
- : PK_Pointer)
- : chunk.Kind == DeclaratorChunk::BlockPointer ? PK_BlockPointer
- : inFunction? PK_MemberFunctionPointer : PK_MemberPointer;
- auto diag = state.getSema().Diag(attr.getLoc(),
- diag::warn_nullability_declspec)
- << DiagNullabilityKind(mapNullabilityAttrKind(attr.getKind()),
- attr.isContextSensitiveKeywordAttribute())
- << type
- << static_cast<unsigned>(pointerKind);
- // FIXME: MemberPointer chunks don't carry the location of the *.
- if (chunk.Kind != DeclaratorChunk::MemberPointer) {
- diag << FixItHint::CreateRemoval(attr.getLoc())
- << FixItHint::CreateInsertion(
- state.getSema().getPreprocessor()
- .getLocForEndOfToken(chunk.Loc),
- " " + attr.getName()->getName().str() + " ");
- }
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
- return true;
- };
- // Move it to the outermost pointer, member pointer, or block
- // pointer declarator.
- for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
- switch (chunk.Kind) {
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::MemberPointer:
- return moveToChunk(chunk, false);
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Array:
- continue;
- case DeclaratorChunk::Function:
- // Try to move past the return type to a function/block/member
- // function pointer.
- if (DeclaratorChunk *dest = maybeMovePastReturnType(
- declarator, i,
- /*onlyBlockPointers=*/false)) {
- return moveToChunk(*dest, true);
- }
- return false;
-
- // Don't walk through these.
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Pipe:
- return false;
- }
- }
- return false;
- }
- static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
- assert(!Attr.isInvalid());
- switch (Attr.getKind()) {
- default:
- llvm_unreachable("not a calling convention attribute");
- case AttributeList::AT_CDecl:
- return AttributedType::attr_cdecl;
- case AttributeList::AT_FastCall:
- return AttributedType::attr_fastcall;
- case AttributeList::AT_StdCall:
- return AttributedType::attr_stdcall;
- case AttributeList::AT_ThisCall:
- return AttributedType::attr_thiscall;
- case AttributeList::AT_RegCall:
- return AttributedType::attr_regcall;
- case AttributeList::AT_Pascal:
- return AttributedType::attr_pascal;
- case AttributeList::AT_SwiftCall:
- return AttributedType::attr_swiftcall;
- case AttributeList::AT_VectorCall:
- return AttributedType::attr_vectorcall;
- case AttributeList::AT_Pcs: {
- // The attribute may have had a fixit applied where we treated an
- // identifier as a string literal. The contents of the string are valid,
- // but the form may not be.
- StringRef Str;
- if (Attr.isArgExpr(0))
- Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
- else
- Str = Attr.getArgAsIdent(0)->Ident->getName();
- return llvm::StringSwitch<AttributedType::Kind>(Str)
- .Case("aapcs", AttributedType::attr_pcs)
- .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
- }
- case AttributeList::AT_IntelOclBicc:
- return AttributedType::attr_inteloclbicc;
- case AttributeList::AT_MSABI:
- return AttributedType::attr_ms_abi;
- case AttributeList::AT_SysVABI:
- return AttributedType::attr_sysv_abi;
- case AttributeList::AT_PreserveMost:
- return AttributedType::attr_preserve_most;
- case AttributeList::AT_PreserveAll:
- return AttributedType::attr_preserve_all;
- }
- llvm_unreachable("unexpected attribute kind!");
- }
- /// Process an individual function attribute. Returns true to
- /// indicate that the attribute was handled, false if it wasn't.
- static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
- Sema &S = state.getSema();
- FunctionTypeUnwrapper unwrapped(S, type);
- if (attr.getKind() == AttributeList::AT_NoReturn) {
- if (S.CheckNoReturnAttr(attr))
- return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- // Otherwise we can process right away.
- FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- // ns_returns_retained is not always a type attribute, but if we got
- // here, we're treating it as one right now.
- if (attr.getKind() == AttributeList::AT_NSReturnsRetained) {
- if (attr.getNumArgs()) return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- // Check whether the return type is reasonable.
- if (S.checkNSReturnsRetainedReturnType(attr.getLoc(),
- unwrapped.get()->getReturnType()))
- return true;
- // Only actually change the underlying type in ARC builds.
- QualType origType = type;
- if (state.getSema().getLangOpts().ObjCAutoRefCount) {
- FunctionType::ExtInfo EI
- = unwrapped.get()->getExtInfo().withProducesResult(true);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- }
- type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
- origType, type);
- return true;
- }
- if (attr.getKind() == AttributeList::AT_AnyX86NoCallerSavedRegisters) {
- if (S.CheckNoCallerSavedRegsAttr(attr))
- return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- FunctionType::ExtInfo EI =
- unwrapped.get()->getExtInfo().withNoCallerSavedRegs(true);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- if (attr.getKind() == AttributeList::AT_Regparm) {
- unsigned value;
- if (S.CheckRegparmAttr(attr, value))
- return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- // Diagnose regparm with fastcall.
- const FunctionType *fn = unwrapped.get();
- CallingConv CC = fn->getCallConv();
- if (CC == CC_X86FastCall) {
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << "regparm";
- attr.setInvalid();
- return true;
- }
- FunctionType::ExtInfo EI =
- unwrapped.get()->getExtInfo().withRegParm(value);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- // Delay if the type didn't work out to a function.
- if (!unwrapped.isFunctionType()) return false;
- // Otherwise, a calling convention.
- CallingConv CC;
- if (S.CheckCallingConvAttr(attr, CC))
- return true;
- const FunctionType *fn = unwrapped.get();
- CallingConv CCOld = fn->getCallConv();
- AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
- if (CCOld != CC) {
- // Error out on when there's already an attribute on the type
- // and the CCs don't match.
- const AttributedType *AT = S.getCallingConvAttributedType(type);
- if (AT && AT->getAttrKind() != CCAttrKind) {
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << FunctionType::getNameForCallConv(CCOld);
- attr.setInvalid();
- return true;
- }
- }
- // Diagnose use of variadic functions with calling conventions that
- // don't support them (e.g. because they're callee-cleanup).
- // We delay warning about this on unprototyped function declarations
- // until after redeclaration checking, just in case we pick up a
- // prototype that way. And apparently we also "delay" warning about
- // unprototyped function types in general, despite not necessarily having
- // much ability to diagnose it later.
- if (!supportsVariadicCall(CC)) {
- const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
- if (FnP && FnP->isVariadic()) {
- unsigned DiagID = diag::err_cconv_varargs;
- // stdcall and fastcall are ignored with a warning for GCC and MS
- // compatibility.
- bool IsInvalid = true;
- if (CC == CC_X86StdCall || CC == CC_X86FastCall) {
- DiagID = diag::warn_cconv_varargs;
- IsInvalid = false;
- }
- S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC);
- if (IsInvalid) attr.setInvalid();
- return true;
- }
- }
- // Also diagnose fastcall with regparm.
- if (CC == CC_X86FastCall && fn->getHasRegParm()) {
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
- attr.setInvalid();
- return true;
- }
- // Modify the CC from the wrapped function type, wrap it all back, and then
- // wrap the whole thing in an AttributedType as written. The modified type
- // might have a different CC if we ignored the attribute.
- QualType Equivalent;
- if (CCOld == CC) {
- Equivalent = type;
- } else {
- auto EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
- Equivalent =
- unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- }
- type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
- return true;
- }
- bool Sema::hasExplicitCallingConv(QualType &T) {
- QualType R = T.IgnoreParens();
- while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
- if (AT->isCallingConv())
- return true;
- R = AT->getModifiedType().IgnoreParens();
- }
- return false;
- }
- void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
- SourceLocation Loc) {
- FunctionTypeUnwrapper Unwrapped(*this, T);
- const FunctionType *FT = Unwrapped.get();
- bool IsVariadic = (isa<FunctionProtoType>(FT) &&
- cast<FunctionProtoType>(FT)->isVariadic());
- CallingConv CurCC = FT->getCallConv();
- CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
- if (CurCC == ToCC)
- return;
- // MS compiler ignores explicit calling convention attributes on structors. We
- // should do the same.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) {
- // Issue a warning on ignored calling convention -- except of __stdcall.
- // Again, this is what MS compiler does.
- if (CurCC != CC_X86StdCall)
- Diag(Loc, diag::warn_cconv_structors)
- << FunctionType::getNameForCallConv(CurCC);
- // Default adjustment.
- } else {
- // Only adjust types with the default convention. For example, on Windows
- // we should adjust a __cdecl type to __thiscall for instance methods, and a
- // __thiscall type to __cdecl for static methods.
- CallingConv DefaultCC =
- Context.getDefaultCallingConvention(IsVariadic, IsStatic);
- if (CurCC != DefaultCC || DefaultCC == ToCC)
- return;
- if (hasExplicitCallingConv(T))
- return;
- }
- FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
- QualType Wrapped = Unwrapped.wrap(*this, FT);
- T = Context.getAdjustedType(T, Wrapped);
- }
- /// HandleVectorSizeAttribute - this attribute is only applicable to integral
- /// and float scalars, although arrays, pointers, and function return values are
- /// allowed in conjunction with this construct. Aggregates with this attribute
- /// are invalid, even if they are of the same size as a corresponding scalar.
- /// The raw attribute should contain precisely 1 argument, the vector size for
- /// the variable, measured in bytes. If curType and rawAttr are well formed,
- /// this routine will return a new vector type.
- static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt vecSize(32);
- if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
- !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // The base type must be integer (not Boolean or enumeration) or float, and
- // can't already be a vector.
- if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
- Attr.setInvalid();
- return;
- }
- unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
- // vecSize is specified in bytes - convert to bits.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
- // the vector size needs to be an integral multiple of the type size.
- if (vectorSize % typeSize) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (vectorSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // Success! Instantiate the vector type, the number of elements is > 0, and
- // not required to be a power of 2, unlike GCC.
- CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
- VectorType::GenericVector);
- }
- /// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
- /// a type.
- static void HandleExtVectorTypeAttr(QualType &CurType,
- const AttributeList &Attr,
- Sema &S) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- return;
- }
- Expr *sizeExpr;
- // Special case where the argument is a template id.
- if (Attr.isArgIdent(0)) {
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId id;
- id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
- ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
- id, false, false);
- if (Size.isInvalid())
- return;
- sizeExpr = Size.get();
- } else {
- sizeExpr = Attr.getArgAsExpr(0);
- }
- // Create the vector type.
- QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
- if (!T.isNull())
- CurType = T;
- }
- static bool isPermittedNeonBaseType(QualType &Ty,
- VectorType::VectorKind VecKind, Sema &S) {
- const BuiltinType *BTy = Ty->getAs<BuiltinType>();
- if (!BTy)
- return false;
- llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
- // Signed poly is mathematically wrong, but has been baked into some ABIs by
- // now.
- bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
- Triple.getArch() == llvm::Triple::aarch64_be;
- if (VecKind == VectorType::NeonPolyVector) {
- if (IsPolyUnsigned) {
- // AArch64 polynomial vectors are unsigned and support poly64.
- return BTy->getKind() == BuiltinType::UChar ||
- BTy->getKind() == BuiltinType::UShort ||
- BTy->getKind() == BuiltinType::ULong ||
- BTy->getKind() == BuiltinType::ULongLong;
- } else {
- // AArch32 polynomial vector are signed.
- return BTy->getKind() == BuiltinType::SChar ||
- BTy->getKind() == BuiltinType::Short;
- }
- }
- // Non-polynomial vector types: the usual suspects are allowed, as well as
- // float64_t on AArch64.
- bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
- Triple.getArch() == llvm::Triple::aarch64_be;
- if (Is64Bit && BTy->getKind() == BuiltinType::Double)
- return true;
- return BTy->getKind() == BuiltinType::SChar ||
- BTy->getKind() == BuiltinType::UChar ||
- BTy->getKind() == BuiltinType::Short ||
- BTy->getKind() == BuiltinType::UShort ||
- BTy->getKind() == BuiltinType::Int ||
- BTy->getKind() == BuiltinType::UInt ||
- BTy->getKind() == BuiltinType::Long ||
- BTy->getKind() == BuiltinType::ULong ||
- BTy->getKind() == BuiltinType::LongLong ||
- BTy->getKind() == BuiltinType::ULongLong ||
- BTy->getKind() == BuiltinType::Float ||
- BTy->getKind() == BuiltinType::Half;
- }
- /// HandleNeonVectorTypeAttr - The "neon_vector_type" and
- /// "neon_polyvector_type" attributes are used to create vector types that
- /// are mangled according to ARM's ABI. Otherwise, these types are identical
- /// to those created with the "vector_size" attribute. Unlike "vector_size"
- /// the argument to these Neon attributes is the number of vector elements,
- /// not the vector size in bytes. The vector width and element type must
- /// match one of the standard Neon vector types.
- static void HandleNeonVectorTypeAttr(QualType& CurType,
- const AttributeList &Attr, Sema &S,
- VectorType::VectorKind VecKind) {
- // Target must have NEON
- if (!S.Context.getTargetInfo().hasFeature("neon")) {
- S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr.getName();
- Attr.setInvalid();
- return;
- }
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr.getName() << 1;
- Attr.setInvalid();
- return;
- }
- // The number of elements must be an ICE.
- Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- llvm::APSInt numEltsInt(32);
- if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
- !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
- << Attr.getName() << AANT_ArgumentIntegerConstant
- << numEltsExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // Only certain element types are supported for Neon vectors.
- if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
- Attr.setInvalid();
- return;
- }
- // The total size of the vector must be 64 or 128 bits.
- unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
- unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
- unsigned vecSize = typeSize * numElts;
- if (vecSize != 64 && vecSize != 128) {
- S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
- Attr.setInvalid();
- return;
- }
- CurType = S.Context.getVectorType(CurType, numElts, VecKind);
- }
- /// Handle OpenCL Access Qualifier Attribute.
- static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
- Sema &S) {
- // OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
- if (!(CurType->isImageType() || CurType->isPipeType())) {
- S.Diag(Attr.getLoc(), diag::err_opencl_invalid_access_qualifier);
- Attr.setInvalid();
- return;
- }
- if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) {
- QualType PointeeTy = TypedefTy->desugar();
- S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
- std::string PrevAccessQual;
- switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) {
- #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
- case BuiltinType::Id: \
- PrevAccessQual = #Access; \
- break;
- #include "clang/Basic/OpenCLImageTypes.def"
- default:
- assert(0 && "Unable to find corresponding image type.");
- }
- S.Diag(TypedefTy->getDecl()->getLocStart(),
- diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
- } else if (CurType->isPipeType()) {
- if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) {
- QualType ElemType = CurType->getAs<PipeType>()->getElementType();
- CurType = S.Context.getWritePipeType(ElemType);
- }
- }
- }
- static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
- QualType &T, TypeAttrLocation TAL) {
- Declarator &D = State.getDeclarator();
- // Handle the cases where address space should not be deduced.
- //
- // The pointee type of a pointer type is alwasy deduced since a pointer always
- // points to some memory location which should has an address space.
- //
- // There are situations that at the point of certain declarations, the address
- // space may be unknown and better to be left as default. For example, when
- // definining a typedef or struct type, they are not associated with any
- // specific address space. Later on, they may be used with any address space
- // to declare a variable.
- //
- // The return value of a function is r-value, therefore should not have
- // address space.
- //
- // The void type does not occupy memory, therefore should not have address
- // space, except when it is used as a pointee type.
- //
- // Since LLVM assumes function type is in default address space, it should not
- // have address space.
- auto ChunkIndex = State.getCurrentChunkIndex();
- bool IsPointee =
- ChunkIndex > 0 &&
- (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer ||
- D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer);
- bool IsFuncReturnType =
- ChunkIndex > 0 &&
- D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function;
- bool IsFuncType =
- ChunkIndex < D.getNumTypeObjects() &&
- D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function;
- if ( // Do not deduce addr space for function return type and function type,
- // otherwise it will fail some sema check.
- IsFuncReturnType || IsFuncType ||
- // Do not deduce addr space for member types of struct, except the pointee
- // type of a pointer member type.
- (D.getContext() == DeclaratorContext::MemberContext && !IsPointee) ||
- // Do not deduce addr space for types used to define a typedef and the
- // typedef itself, except the pointee type of a pointer type which is used
- // to define the typedef.
- (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef &&
- !IsPointee) ||
- // Do not deduce addr space of the void type, e.g. in f(void), otherwise
- // it will fail some sema check.
- (T->isVoidType() && !IsPointee))
- return;
- LangAS ImpAddr;
- // Put OpenCL automatic variable in private address space.
- // OpenCL v1.2 s6.5:
- // The default address space name for arguments to a function in a
- // program, or local variables of a function is __private. All function
- // arguments shall be in the __private address space.
- if (State.getSema().getLangOpts().OpenCLVersion <= 120) {
- ImpAddr = LangAS::opencl_private;
- } else {
- // If address space is not set, OpenCL 2.0 defines non private default
- // address spaces for some cases:
- // OpenCL 2.0, section 6.5:
- // The address space for a variable at program scope or a static variable
- // inside a function can either be __global or __constant, but defaults to
- // __global if not specified.
- // (...)
- // Pointers that are declared without pointing to a named address space
- // point to the generic address space.
- if (IsPointee) {
- ImpAddr = LangAS::opencl_generic;
- } else {
- if (D.getContext() == DeclaratorContext::FileContext) {
- ImpAddr = LangAS::opencl_global;
- } else {
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) {
- ImpAddr = LangAS::opencl_global;
- } else {
- ImpAddr = LangAS::opencl_private;
- }
- }
- }
- }
- T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
- }
- static void processTypeAttrs(TypeProcessingState &state, QualType &type,
- TypeAttrLocation TAL, AttributeList *attrs) {
- // Scan through and apply attributes to this type where it makes sense. Some
- // attributes (such as __address_space__, __vector_size__, etc) apply to the
- // type, but others can be present in the type specifiers even though they
- // apply to the decl. Here we apply type attributes and ignore the rest.
- while (attrs) {
- AttributeList &attr = *attrs;
- attrs = attr.getNext(); // reset to the next here due to early loop continue
- // stmts
- // Skip attributes that were marked to be invalid.
- if (attr.isInvalid())
- continue;
- if (attr.isCXX11Attribute()) {
- // [[gnu::...]] attributes are treated as declaration attributes, so may
- // not appertain to a DeclaratorChunk, even if we handle them as type
- // attributes.
- if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
- if (TAL == TAL_DeclChunk) {
- state.getSema().Diag(attr.getLoc(),
- diag::warn_cxx11_gnu_attribute_on_type)
- << attr.getName();
- continue;
- }
- } else if (TAL != TAL_DeclChunk) {
- // Otherwise, only consider type processing for a C++11 attribute if
- // it's actually been applied to a type.
- continue;
- }
- }
- // If this is an attribute we can handle, do so now,
- // otherwise, add it to the FnAttrs list for rechaining.
- switch (attr.getKind()) {
- default:
- // A C++11 attribute on a declarator chunk must appertain to a type.
- if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) {
- state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
- << attr.getName();
- attr.setUsedAsTypeAttr();
- }
- break;
- case AttributeList::UnknownAttribute:
- if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
- state.getSema().Diag(attr.getLoc(),
- diag::warn_unknown_attribute_ignored)
- << attr.getName();
- break;
- case AttributeList::IgnoredAttribute:
- break;
- case AttributeList::AT_MayAlias:
- // FIXME: This attribute needs to actually be handled, but if we ignore
- // it it breaks large amounts of Linux software.
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_OpenCLPrivateAddressSpace:
- case AttributeList::AT_OpenCLGlobalAddressSpace:
- case AttributeList::AT_OpenCLLocalAddressSpace:
- case AttributeList::AT_OpenCLConstantAddressSpace:
- case AttributeList::AT_OpenCLGenericAddressSpace:
- case AttributeList::AT_AddressSpace:
- HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- OBJC_POINTER_TYPE_ATTRS_CASELIST:
- if (!handleObjCPointerTypeAttr(state, attr, type))
- distributeObjCPointerTypeAttr(state, attr, type);
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_VectorSize:
- HandleVectorSizeAttr(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_ExtVectorType:
- HandleExtVectorTypeAttr(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_NeonVectorType:
- HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonVector);
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_NeonPolyVectorType:
- HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonPolyVector);
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_OpenCLAccess:
- HandleOpenCLAccessAttr(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- MS_TYPE_ATTRS_CASELIST:
- if (!handleMSPointerTypeQualifierAttr(state, attr, type))
- attr.setUsedAsTypeAttr();
- break;
- NULLABILITY_TYPE_ATTRS_CASELIST:
- // Either add nullability here or try to distribute it. We
- // don't want to distribute the nullability specifier past any
- // dependent type, because that complicates the user model.
- if (type->canHaveNullability() || type->isDependentType() ||
- type->isArrayType() ||
- !distributeNullabilityTypeAttr(state, type, attr)) {
- unsigned endIndex;
- if (TAL == TAL_DeclChunk)
- endIndex = state.getCurrentChunkIndex();
- else
- endIndex = state.getDeclarator().getNumTypeObjects();
- bool allowOnArrayType =
- state.getDeclarator().isPrototypeContext() &&
- !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
- if (state.getSema().checkNullabilityTypeSpecifier(
- type,
- mapNullabilityAttrKind(attr.getKind()),
- attr.getLoc(),
- attr.isContextSensitiveKeywordAttribute(),
- allowOnArrayType)) {
- attr.setInvalid();
- }
- attr.setUsedAsTypeAttr();
- }
- break;
- case AttributeList::AT_ObjCKindOf:
- // '__kindof' must be part of the decl-specifiers.
- switch (TAL) {
- case TAL_DeclSpec:
- break;
- case TAL_DeclChunk:
- case TAL_DeclName:
- state.getSema().Diag(attr.getLoc(),
- diag::err_objc_kindof_wrong_position)
- << FixItHint::CreateRemoval(attr.getLoc())
- << FixItHint::CreateInsertion(
- state.getDeclarator().getDeclSpec().getLocStart(), "__kindof ");
- break;
- }
- // Apply it regardless.
- if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
- attr.setInvalid();
- attr.setUsedAsTypeAttr();
- break;
- FUNCTION_TYPE_ATTRS_CASELIST:
- attr.setUsedAsTypeAttr();
- // Never process function type attributes as part of the
- // declaration-specifiers.
- if (TAL == TAL_DeclSpec)
- distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
- // Otherwise, handle the possible delays.
- else if (!handleFunctionTypeAttr(state, attr, type))
- distributeFunctionTypeAttr(state, attr, type);
- break;
- }
- }
- if (!state.getSema().getLangOpts().OpenCL ||
- type.getAddressSpace() != LangAS::Default)
- return;
- deduceOpenCLImplicitAddrSpace(state, type, TAL);
- }
- void Sema::completeExprArrayBound(Expr *E) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
- auto *Def = Var->getDefinition();
- if (!Def) {
- SourceLocation PointOfInstantiation = E->getExprLoc();
- InstantiateVariableDefinition(PointOfInstantiation, Var);
- Def = Var->getDefinition();
- // If we don't already have a point of instantiation, and we managed
- // to instantiate a definition, this is the point of instantiation.
- // Otherwise, we don't request an end-of-TU instantiation, so this is
- // not a point of instantiation.
- // FIXME: Is this really the right behavior?
- if (Var->getPointOfInstantiation().isInvalid() && Def) {
- assert(Var->getTemplateSpecializationKind() ==
- TSK_ImplicitInstantiation &&
- "explicit instantiation with no point of instantiation");
- Var->setTemplateSpecializationKind(
- Var->getTemplateSpecializationKind(), PointOfInstantiation);
- }
- }
- // Update the type to the definition's type both here and within the
- // expression.
- if (Def) {
- DRE->setDecl(Def);
- QualType T = Def->getType();
- DRE->setType(T);
- // FIXME: Update the type on all intervening expressions.
- E->setType(T);
- }
- // We still go on to try to complete the type independently, as it
- // may also require instantiations or diagnostics if it remains
- // incomplete.
- }
- }
- }
- }
- /// \brief Ensure that the type of the given expression is complete.
- ///
- /// This routine checks whether the expression \p E has a complete type. If the
- /// expression refers to an instantiable construct, that instantiation is
- /// performed as needed to complete its type. Furthermore
- /// Sema::RequireCompleteType is called for the expression's type (or in the
- /// case of a reference type, the referred-to type).
- ///
- /// \param E The expression whose type is required to be complete.
- /// \param Diagnoser The object that will emit a diagnostic if the type is
- /// incomplete.
- ///
- /// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
- /// otherwise.
- bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser) {
- QualType T = E->getType();
- // Incomplete array types may be completed by the initializer attached to
- // their definitions. For static data members of class templates and for
- // variable templates, we need to instantiate the definition to get this
- // initializer and complete the type.
- if (T->isIncompleteArrayType()) {
- completeExprArrayBound(E);
- T = E->getType();
- }
- // FIXME: Are there other cases which require instantiating something other
- // than the type to complete the type of an expression?
- return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
- }
- bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
- BoundTypeDiagnoser<> Diagnoser(DiagID);
- return RequireCompleteExprType(E, Diagnoser);
- }
- /// @brief Ensure that the type T is a complete type.
- ///
- /// This routine checks whether the type @p T is complete in any
- /// context where a complete type is required. If @p T is a complete
- /// type, returns false. If @p T is a class template specialization,
- /// this routine then attempts to perform class template
- /// instantiation. If instantiation fails, or if @p T is incomplete
- /// and cannot be completed, issues the diagnostic @p diag (giving it
- /// the type @p T) and returns true.
- ///
- /// @param Loc The location in the source that the incomplete type
- /// diagnostic should refer to.
- ///
- /// @param T The type that this routine is examining for completeness.
- ///
- /// @returns @c true if @p T is incomplete and a diagnostic was emitted,
- /// @c false otherwise.
- bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser) {
- if (RequireCompleteTypeImpl(Loc, T, &Diagnoser))
- return true;
- if (const TagType *Tag = T->getAs<TagType>()) {
- if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
- Tag->getDecl()->setCompleteDefinitionRequired();
- Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl());
- }
- }
- return false;
- }
- bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
- llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
- if (!Suggested)
- return false;
- // FIXME: Add a specific mode for C11 6.2.7/1 in StructuralEquivalenceContext
- // and isolate from other C++ specific checks.
- StructuralEquivalenceContext Ctx(
- D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls,
- false /*StrictTypeSpelling*/, true /*Complain*/,
- true /*ErrorOnTagTypeMismatch*/);
- return Ctx.IsStructurallyEquivalent(D, Suggested);
- }
- /// \brief Determine whether there is any declaration of \p D that was ever a
- /// definition (perhaps before module merging) and is currently visible.
- /// \param D The definition of the entity.
- /// \param Suggested Filled in with the declaration that should be made visible
- /// in order to provide a definition of this entity.
- /// \param OnlyNeedComplete If \c true, we only need the type to be complete,
- /// not defined. This only matters for enums with a fixed underlying
- /// type, since in all other cases, a type is complete if and only if it
- /// is defined.
- bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
- bool OnlyNeedComplete) {
- // Easy case: if we don't have modules, all declarations are visible.
- if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility)
- return true;
- // If this definition was instantiated from a template, map back to the
- // pattern from which it was instantiated.
- if (isa<TagDecl>(D) && cast<TagDecl>(D)->isBeingDefined()) {
- // We're in the middle of defining it; this definition should be treated
- // as visible.
- return true;
- } else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (auto *Pattern = RD->getTemplateInstantiationPattern())
- RD = Pattern;
- D = RD->getDefinition();
- } else if (auto *ED = dyn_cast<EnumDecl>(D)) {
- if (auto *Pattern = ED->getTemplateInstantiationPattern())
- ED = Pattern;
- if (OnlyNeedComplete && ED->isFixed()) {
- // If the enum has a fixed underlying type, and we're only looking for a
- // complete type (not a definition), any visible declaration of it will
- // do.
- *Suggested = nullptr;
- for (auto *Redecl : ED->redecls()) {
- if (isVisible(Redecl))
- return true;
- if (Redecl->isThisDeclarationADefinition() ||
- (Redecl->isCanonicalDecl() && !*Suggested))
- *Suggested = Redecl;
- }
- return false;
- }
- D = ED->getDefinition();
- } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (auto *Pattern = FD->getTemplateInstantiationPattern())
- FD = Pattern;
- D = FD->getDefinition();
- } else if (auto *VD = dyn_cast<VarDecl>(D)) {
- if (auto *Pattern = VD->getTemplateInstantiationPattern())
- VD = Pattern;
- D = VD->getDefinition();
- }
- assert(D && "missing definition for pattern of instantiated definition");
- *Suggested = D;
- if (isVisible(D))
- return true;
- // The external source may have additional definitions of this entity that are
- // visible, so complete the redeclaration chain now and ask again.
- if (auto *Source = Context.getExternalSource()) {
- Source->CompleteRedeclChain(D);
- return isVisible(D);
- }
- return false;
- }
- /// Locks in the inheritance model for the given class and all of its bases.
- static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
- RD = RD->getMostRecentDecl();
- if (!RD->hasAttr<MSInheritanceAttr>()) {
- MSInheritanceAttr::Spelling IM;
- switch (S.MSPointerToMemberRepresentationMethod) {
- case LangOptions::PPTMK_BestCase:
- IM = RD->calculateInheritanceModel();
- break;
- case LangOptions::PPTMK_FullGeneralitySingleInheritance:
- IM = MSInheritanceAttr::Keyword_single_inheritance;
- break;
- case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
- IM = MSInheritanceAttr::Keyword_multiple_inheritance;
- break;
- case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
- IM = MSInheritanceAttr::Keyword_unspecified_inheritance;
- break;
- }
- RD->addAttr(MSInheritanceAttr::CreateImplicit(
- S.getASTContext(), IM,
- /*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
- LangOptions::PPTMK_BestCase,
- S.ImplicitMSInheritanceAttrLoc.isValid()
- ? S.ImplicitMSInheritanceAttrLoc
- : RD->getSourceRange()));
- S.Consumer.AssignInheritanceModel(RD);
- }
- }
- /// \brief The implementation of RequireCompleteType
- bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
- TypeDiagnoser *Diagnoser) {
- // FIXME: Add this assertion to make sure we always get instantiation points.
- // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
- // FIXME: Add this assertion to help us flush out problems with
- // checking for dependent types and type-dependent expressions.
- //
- // assert(!T->isDependentType() &&
- // "Can't ask whether a dependent type is complete");
- // We lock in the inheritance model once somebody has asked us to ensure
- // that a pointer-to-member type is complete.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
- (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
- assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
- }
- }
- }
- NamedDecl *Def = nullptr;
- bool Incomplete = T->isIncompleteType(&Def);
- // Check that any necessary explicit specializations are visible. For an
- // enum, we just need the declaration, so don't check this.
- if (Def && !isa<EnumDecl>(Def))
- checkSpecializationVisibility(Loc, Def);
- // If we have a complete type, we're done.
- if (!Incomplete) {
- // If we know about the definition but it is not visible, complain.
- NamedDecl *SuggestedDef = nullptr;
- if (Def &&
- !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) {
- // If the user is going to see an error here, recover by making the
- // definition visible.
- bool TreatAsComplete = Diagnoser && !isSFINAEContext();
- if (Diagnoser)
- diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
- /*Recover*/TreatAsComplete);
- return !TreatAsComplete;
- } else if (Def && !TemplateInstCallbacks.empty()) {
- CodeSynthesisContext TempInst;
- TempInst.Kind = CodeSynthesisContext::Memoization;
- TempInst.Template = Def;
- TempInst.Entity = Def;
- TempInst.PointOfInstantiation = Loc;
- atTemplateBegin(TemplateInstCallbacks, *this, TempInst);
- atTemplateEnd(TemplateInstCallbacks, *this, TempInst);
- }
- return false;
- }
- const TagType *Tag = T->getAs<TagType>();
- const ObjCInterfaceType *IFace = T->getAs<ObjCInterfaceType>();
- // If there's an unimported definition of this type in a module (for
- // instance, because we forward declared it, then imported the definition),
- // import that definition now.
- //
- // FIXME: What about other cases where an import extends a redeclaration
- // chain for a declaration that can be accessed through a mechanism other
- // than name lookup (eg, referenced in a template, or a variable whose type
- // could be completed by the module)?
- //
- // FIXME: Should we map through to the base array element type before
- // checking for a tag type?
- if (Tag || IFace) {
- NamedDecl *D =
- Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
- // Avoid diagnosing invalid decls as incomplete.
- if (D->isInvalidDecl())
- return true;
- // Give the external AST source a chance to complete the type.
- if (auto *Source = Context.getExternalSource()) {
- if (Tag) {
- TagDecl *TagD = Tag->getDecl();
- if (TagD->hasExternalLexicalStorage())
- Source->CompleteType(TagD);
- } else {
- ObjCInterfaceDecl *IFaceD = IFace->getDecl();
- if (IFaceD->hasExternalLexicalStorage())
- Source->CompleteType(IFace->getDecl());
- }
- // If the external source completed the type, go through the motions
- // again to ensure we're allowed to use the completed type.
- if (!T->isIncompleteType())
- return RequireCompleteTypeImpl(Loc, T, Diagnoser);
- }
- }
- // If we have a class template specialization or a class member of a
- // class template specialization, or an array with known size of such,
- // try to instantiate it.
- QualType MaybeTemplate = T;
- while (const ConstantArrayType *Array
- = Context.getAsConstantArrayType(MaybeTemplate))
- MaybeTemplate = Array->getElementType();
- if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
- bool Instantiated = false;
- bool Diagnosed = false;
- if (ClassTemplateSpecializationDecl *ClassTemplateSpec
- = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
- if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
- Diagnosed = InstantiateClassTemplateSpecialization(
- Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
- /*Complain=*/Diagnoser);
- Instantiated = true;
- }
- } else if (CXXRecordDecl *Rec
- = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
- CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
- if (!Rec->isBeingDefined() && Pattern) {
- MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
- assert(MSI && "Missing member specialization information?");
- // This record was instantiated from a class within a template.
- if (MSI->getTemplateSpecializationKind() !=
- TSK_ExplicitSpecialization) {
- Diagnosed = InstantiateClass(Loc, Rec, Pattern,
- getTemplateInstantiationArgs(Rec),
- TSK_ImplicitInstantiation,
- /*Complain=*/Diagnoser);
- Instantiated = true;
- }
- }
- }
- if (Instantiated) {
- // Instantiate* might have already complained that the template is not
- // defined, if we asked it to.
- if (Diagnoser && Diagnosed)
- return true;
- // If we instantiated a definition, check that it's usable, even if
- // instantiation produced an error, so that repeated calls to this
- // function give consistent answers.
- if (!T->isIncompleteType())
- return RequireCompleteTypeImpl(Loc, T, Diagnoser);
- }
- }
- // FIXME: If we didn't instantiate a definition because of an explicit
- // specialization declaration, check that it's visible.
- if (!Diagnoser)
- return true;
- Diagnoser->diagnose(*this, Loc, T);
- // If the type was a forward declaration of a class/struct/union
- // type, produce a note.
- if (Tag && !Tag->getDecl()->isInvalidDecl())
- Diag(Tag->getDecl()->getLocation(),
- Tag->isBeingDefined() ? diag::note_type_being_defined
- : diag::note_forward_declaration)
- << QualType(Tag, 0);
- // If the Objective-C class was a forward declaration, produce a note.
- if (IFace && !IFace->getDecl()->isInvalidDecl())
- Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
- // If we have external information that we can use to suggest a fix,
- // produce a note.
- if (ExternalSource)
- ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
- return true;
- }
- bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- unsigned DiagID) {
- BoundTypeDiagnoser<> Diagnoser(DiagID);
- return RequireCompleteType(Loc, T, Diagnoser);
- }
- /// \brief Get diagnostic %select index for tag kind for
- /// literal type diagnostic message.
- /// WARNING: Indexes apply to particular diagnostics only!
- ///
- /// \returns diagnostic %select index.
- static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) {
- switch (Tag) {
- case TTK_Struct: return 0;
- case TTK_Interface: return 1;
- case TTK_Class: return 2;
- default: llvm_unreachable("Invalid tag kind for literal type diagnostic!");
- }
- }
- /// @brief Ensure that the type T is a literal type.
- ///
- /// This routine checks whether the type @p T is a literal type. If @p T is an
- /// incomplete type, an attempt is made to complete it. If @p T is a literal
- /// type, or @p AllowIncompleteType is true and @p T is an incomplete type,
- /// returns false. Otherwise, this routine issues the diagnostic @p PD (giving
- /// it the type @p T), along with notes explaining why the type is not a
- /// literal type, and returns true.
- ///
- /// @param Loc The location in the source that the non-literal type
- /// diagnostic should refer to.
- ///
- /// @param T The type that this routine is examining for literalness.
- ///
- /// @param Diagnoser Emits a diagnostic if T is not a literal type.
- ///
- /// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
- /// @c false otherwise.
- bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser) {
- assert(!T->isDependentType() && "type should not be dependent");
- QualType ElemType = Context.getBaseElementType(T);
- if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) &&
- T->isLiteralType(Context))
- return false;
- Diagnoser.diagnose(*this, Loc, T);
- if (T->isVariableArrayType())
- return true;
- const RecordType *RT = ElemType->getAs<RecordType>();
- if (!RT)
- return true;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- // A partially-defined class type can't be a literal type, because a literal
- // class type must have a trivial destructor (which can't be checked until
- // the class definition is complete).
- if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
- return true;
- // If the class has virtual base classes, then it's not an aggregate, and
- // cannot have any constexpr constructors or a trivial default constructor,
- // so is non-literal. This is better to diagnose than the resulting absence
- // of constexpr constructors.
- if (RD->getNumVBases()) {
- Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
- << getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
- for (const auto &I : RD->vbases())
- Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here)
- << I.getSourceRange();
- } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
- !RD->hasTrivialDefaultConstructor()) {
- Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
- } else if (RD->hasNonLiteralTypeFieldsOrBases()) {
- for (const auto &I : RD->bases()) {
- if (!I.getType()->isLiteralType(Context)) {
- Diag(I.getLocStart(),
- diag::note_non_literal_base_class)
- << RD << I.getType() << I.getSourceRange();
- return true;
- }
- }
- for (const auto *I : RD->fields()) {
- if (!I->getType()->isLiteralType(Context) ||
- I->getType().isVolatileQualified()) {
- Diag(I->getLocation(), diag::note_non_literal_field)
- << RD << I << I->getType()
- << I->getType().isVolatileQualified();
- return true;
- }
- }
- } else if (!RD->hasTrivialDestructor()) {
- // All fields and bases are of literal types, so have trivial destructors.
- // If this class's destructor is non-trivial it must be user-declared.
- CXXDestructorDecl *Dtor = RD->getDestructor();
- assert(Dtor && "class has literal fields and bases but no dtor?");
- if (!Dtor)
- return true;
- Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
- diag::note_non_literal_user_provided_dtor :
- diag::note_non_literal_nontrivial_dtor) << RD;
- if (!Dtor->isUserProvided())
- SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI,
- /*Diagnose*/true);
- }
- return true;
- }
- bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
- BoundTypeDiagnoser<> Diagnoser(DiagID);
- return RequireLiteralType(Loc, T, Diagnoser);
- }
- /// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
- /// and qualified by the nested-name-specifier contained in SS.
- QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T) {
- if (T.isNull())
- return T;
- NestedNameSpecifier *NNS;
- if (SS.isValid())
- NNS = SS.getScopeRep();
- else {
- if (Keyword == ETK_None)
- return T;
- NNS = nullptr;
- }
- return Context.getElaboratedType(Keyword, NNS, T);
- }
- QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
- ExprResult ER = CheckPlaceholderExpr(E);
- if (ER.isInvalid()) return QualType();
- E = ER.get();
- if (!getLangOpts().CPlusPlus && E->refersToBitField())
- Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
- if (!E->isTypeDependent()) {
- QualType T = E->getType();
- if (const TagType *TT = T->getAs<TagType>())
- DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
- }
- return Context.getTypeOfExprType(E);
- }
- /// getDecltypeForExpr - Given an expr, will return the decltype for
- /// that expression, according to the rules in C++11
- /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
- static QualType getDecltypeForExpr(Sema &S, Expr *E) {
- if (E->isTypeDependent())
- return S.Context.DependentTy;
- // C++11 [dcl.type.simple]p4:
- // The type denoted by decltype(e) is defined as follows:
- //
- // - if e is an unparenthesized id-expression or an unparenthesized class
- // member access (5.2.5), decltype(e) is the type of the entity named
- // by e. If there is no such entity, or if e names a set of overloaded
- // functions, the program is ill-formed;
- //
- // We apply the same rules for Objective-C ivar and property references.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
- return VD->getType();
- } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- return FD->getType();
- } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
- return IR->getDecl()->getType();
- } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
- if (PR->isExplicitProperty())
- return PR->getExplicitProperty()->getType();
- } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
- return PE->getType();
- }
-
- // C++11 [expr.lambda.prim]p18:
- // Every occurrence of decltype((x)) where x is a possibly
- // parenthesized id-expression that names an entity of automatic
- // storage duration is treated as if x were transformed into an
- // access to a corresponding data member of the closure type that
- // would have been declared if x were an odr-use of the denoted
- // entity.
- using namespace sema;
- if (S.getCurLambda()) {
- if (isa<ParenExpr>(E)) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
- if (!T.isNull())
- return S.Context.getLValueReferenceType(T);
- }
- }
- }
- }
- // C++11 [dcl.type.simple]p4:
- // [...]
- QualType T = E->getType();
- switch (E->getValueKind()) {
- // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
- // type of e;
- case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
- // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
- // type of e;
- case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
- // - otherwise, decltype(e) is the type of e.
- case VK_RValue: break;
- }
- return T;
- }
- QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
- bool AsUnevaluated) {
- ExprResult ER = CheckPlaceholderExpr(E);
- if (ER.isInvalid()) return QualType();
- E = ER.get();
- if (AsUnevaluated && CodeSynthesisContexts.empty() &&
- E->HasSideEffects(Context, false)) {
- // The expression operand for decltype is in an unevaluated expression
- // context, so side effects could result in unintended consequences.
- Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
- }
- return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
- }
- QualType Sema::BuildUnaryTransformType(QualType BaseType,
- UnaryTransformType::UTTKind UKind,
- SourceLocation Loc) {
- switch (UKind) {
- case UnaryTransformType::EnumUnderlyingType:
- if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
- Diag(Loc, diag::err_only_enums_have_underlying_types);
- return QualType();
- } else {
- QualType Underlying = BaseType;
- if (!BaseType->isDependentType()) {
- // The enum could be incomplete if we're parsing its definition or
- // recovering from an error.
- NamedDecl *FwdDecl = nullptr;
- if (BaseType->isIncompleteType(&FwdDecl)) {
- Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
- Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
- return QualType();
- }
- EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
- assert(ED && "EnumType has no EnumDecl");
- DiagnoseUseOfDecl(ED, Loc);
- Underlying = ED->getIntegerType();
- assert(!Underlying.isNull());
- }
- return Context.getUnaryTransformType(BaseType, Underlying,
- UnaryTransformType::EnumUnderlyingType);
- }
- }
- llvm_unreachable("unknown unary transform type");
- }
- QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
- if (!T->isDependentType()) {
- // FIXME: It isn't entirely clear whether incomplete atomic types
- // are allowed or not; for simplicity, ban them for the moment.
- if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
- return QualType();
- int DisallowedKind = -1;
- if (T->isArrayType())
- DisallowedKind = 1;
- else if (T->isFunctionType())
- DisallowedKind = 2;
- else if (T->isReferenceType())
- DisallowedKind = 3;
- else if (T->isAtomicType())
- DisallowedKind = 4;
- else if (T.hasQualifiers())
- DisallowedKind = 5;
- else if (!T.isTriviallyCopyableType(Context))
- // Some other non-trivially-copyable type (probably a C++ class)
- DisallowedKind = 6;
- if (DisallowedKind != -1) {
- Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
- return QualType();
- }
- // FIXME: Do we need any handling for ARC here?
- }
- // Build the pointer type.
- return Context.getAtomicType(T);
- }
|