1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612 |
- /* Perform -*- C++ -*- constant expression evaluation, including calls to
- constexpr functions. These routines are used both during actual parsing
- and during the instantiation of template functions.
- Copyright (C) 1998-2015 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "options.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "varasm.h"
- #include "cp-tree.h"
- #include "c-family/c-objc.h"
- #include "tree-iterator.h"
- #include "gimplify.h"
- #include "builtins.h"
- #include "tree-inline.h"
- #include "ubsan.h"
- static bool verify_constant (tree, bool, bool *, bool *);
- #define VERIFY_CONSTANT(X) \
- do { \
- if (verify_constant ((X), ctx->quiet, non_constant_p, overflow_p)) \
- return t; \
- } while (0)
- /* Returns true iff FUN is an instantiation of a constexpr function
- template or a defaulted constexpr function. */
- bool
- is_instantiation_of_constexpr (tree fun)
- {
- return ((DECL_TEMPLOID_INSTANTIATION (fun)
- && DECL_DECLARED_CONSTEXPR_P (DECL_TI_TEMPLATE (fun)))
- || (DECL_DEFAULTED_FN (fun)
- && DECL_DECLARED_CONSTEXPR_P (fun)));
- }
- /* Return true if T is a literal type. */
- bool
- literal_type_p (tree t)
- {
- if (SCALAR_TYPE_P (t)
- || TREE_CODE (t) == VECTOR_TYPE
- || TREE_CODE (t) == REFERENCE_TYPE
- || (VOID_TYPE_P (t) && cxx_dialect >= cxx14))
- return true;
- if (CLASS_TYPE_P (t))
- {
- t = complete_type (t);
- gcc_assert (COMPLETE_TYPE_P (t) || errorcount);
- return CLASSTYPE_LITERAL_P (t);
- }
- if (TREE_CODE (t) == ARRAY_TYPE)
- return literal_type_p (strip_array_types (t));
- return false;
- }
- /* If DECL is a variable declared `constexpr', require its type
- be literal. Return the DECL if OK, otherwise NULL. */
- tree
- ensure_literal_type_for_constexpr_object (tree decl)
- {
- tree type = TREE_TYPE (decl);
- if (VAR_P (decl)
- && (DECL_DECLARED_CONSTEXPR_P (decl)
- || var_in_constexpr_fn (decl))
- && !processing_template_decl)
- {
- tree stype = strip_array_types (type);
- if (CLASS_TYPE_P (stype) && !COMPLETE_TYPE_P (complete_type (stype)))
- /* Don't complain here, we'll complain about incompleteness
- when we try to initialize the variable. */;
- else if (!literal_type_p (type))
- {
- if (DECL_DECLARED_CONSTEXPR_P (decl))
- {
- error ("the type %qT of constexpr variable %qD is not literal",
- type, decl);
- explain_non_literal_class (type);
- }
- else
- {
- if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
- {
- error ("variable %qD of non-literal type %qT in %<constexpr%> "
- "function", decl, type);
- explain_non_literal_class (type);
- }
- cp_function_chain->invalid_constexpr = true;
- }
- return NULL;
- }
- }
- return decl;
- }
- /* Representation of entries in the constexpr function definition table. */
- struct GTY((for_user)) constexpr_fundef {
- tree decl;
- tree body;
- };
- struct constexpr_fundef_hasher : ggc_hasher<constexpr_fundef *>
- {
- static hashval_t hash (constexpr_fundef *);
- static bool equal (constexpr_fundef *, constexpr_fundef *);
- };
- /* This table holds all constexpr function definitions seen in
- the current translation unit. */
- static GTY (()) hash_table<constexpr_fundef_hasher> *constexpr_fundef_table;
- /* Utility function used for managing the constexpr function table.
- Return true if the entries pointed to by P and Q are for the
- same constexpr function. */
- inline bool
- constexpr_fundef_hasher::equal (constexpr_fundef *lhs, constexpr_fundef *rhs)
- {
- return lhs->decl == rhs->decl;
- }
- /* Utility function used for managing the constexpr function table.
- Return a hash value for the entry pointed to by Q. */
- inline hashval_t
- constexpr_fundef_hasher::hash (constexpr_fundef *fundef)
- {
- return DECL_UID (fundef->decl);
- }
- /* Return a previously saved definition of function FUN. */
- static constexpr_fundef *
- retrieve_constexpr_fundef (tree fun)
- {
- constexpr_fundef fundef = { NULL, NULL };
- if (constexpr_fundef_table == NULL)
- return NULL;
- fundef.decl = fun;
- return constexpr_fundef_table->find (&fundef);
- }
- /* Check whether the parameter and return types of FUN are valid for a
- constexpr function, and complain if COMPLAIN. */
- static bool
- is_valid_constexpr_fn (tree fun, bool complain)
- {
- bool ret = true;
- if (DECL_INHERITED_CTOR_BASE (fun)
- && TREE_CODE (fun) == TEMPLATE_DECL)
- {
- ret = false;
- if (complain)
- error ("inherited constructor %qD is not constexpr",
- get_inherited_ctor (fun));
- }
- else
- {
- for (tree parm = FUNCTION_FIRST_USER_PARM (fun);
- parm != NULL_TREE; parm = TREE_CHAIN (parm))
- if (!literal_type_p (TREE_TYPE (parm)))
- {
- ret = false;
- if (complain)
- {
- error ("invalid type for parameter %d of constexpr "
- "function %q+#D", DECL_PARM_INDEX (parm), fun);
- explain_non_literal_class (TREE_TYPE (parm));
- }
- }
- }
- if (!DECL_CONSTRUCTOR_P (fun))
- {
- tree rettype = TREE_TYPE (TREE_TYPE (fun));
- if (!literal_type_p (rettype))
- {
- ret = false;
- if (complain)
- {
- error ("invalid return type %qT of constexpr function %q+D",
- rettype, fun);
- explain_non_literal_class (rettype);
- }
- }
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
- && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
- {
- ret = false;
- if (complain)
- {
- error ("enclosing class of constexpr non-static member "
- "function %q+#D is not a literal type", fun);
- explain_non_literal_class (DECL_CONTEXT (fun));
- }
- }
- }
- else if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun)))
- {
- ret = false;
- if (complain)
- error ("%q#T has virtual base classes", DECL_CONTEXT (fun));
- }
- return ret;
- }
- /* Subroutine of build_data_member_initialization. MEMBER is a COMPONENT_REF
- for a member of an anonymous aggregate, INIT is the initializer for that
- member, and VEC_OUTER is the vector of constructor elements for the class
- whose constructor we are processing. Add the initializer to the vector
- and return true to indicate success. */
- static bool
- build_anon_member_initialization (tree member, tree init,
- vec<constructor_elt, va_gc> **vec_outer)
- {
- /* MEMBER presents the relevant fields from the inside out, but we need
- to build up the initializer from the outside in so that we can reuse
- previously built CONSTRUCTORs if this is, say, the second field in an
- anonymous struct. So we use a vec as a stack. */
- auto_vec<tree, 2> fields;
- do
- {
- fields.safe_push (TREE_OPERAND (member, 1));
- member = TREE_OPERAND (member, 0);
- }
- while (ANON_AGGR_TYPE_P (TREE_TYPE (member))
- && TREE_CODE (member) == COMPONENT_REF);
- /* VEC has the constructor elements vector for the context of FIELD.
- If FIELD is an anonymous aggregate, we will push inside it. */
- vec<constructor_elt, va_gc> **vec = vec_outer;
- tree field;
- while (field = fields.pop(),
- ANON_AGGR_TYPE_P (TREE_TYPE (field)))
- {
- tree ctor;
- /* If there is already an outer constructor entry for the anonymous
- aggregate FIELD, use it; otherwise, insert one. */
- if (vec_safe_is_empty (*vec)
- || (*vec)->last().index != field)
- {
- ctor = build_constructor (TREE_TYPE (field), NULL);
- CONSTRUCTOR_APPEND_ELT (*vec, field, ctor);
- }
- else
- ctor = (*vec)->last().value;
- vec = &CONSTRUCTOR_ELTS (ctor);
- }
- /* Now we're at the innermost field, the one that isn't an anonymous
- aggregate. Add its initializer to the CONSTRUCTOR and we're done. */
- gcc_assert (fields.is_empty());
- CONSTRUCTOR_APPEND_ELT (*vec, field, init);
- return true;
- }
- /* Subroutine of build_constexpr_constructor_member_initializers.
- The expression tree T represents a data member initialization
- in a (constexpr) constructor definition. Build a pairing of
- the data member with its initializer, and prepend that pair
- to the existing initialization pair INITS. */
- static bool
- build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
- {
- tree member, init;
- if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
- t = TREE_OPERAND (t, 0);
- if (TREE_CODE (t) == EXPR_STMT)
- t = TREE_OPERAND (t, 0);
- if (t == error_mark_node)
- return false;
- if (TREE_CODE (t) == STATEMENT_LIST)
- {
- tree_stmt_iterator i;
- for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- {
- if (! build_data_member_initialization (tsi_stmt (i), vec))
- return false;
- }
- return true;
- }
- if (TREE_CODE (t) == CLEANUP_STMT)
- {
- /* We can't see a CLEANUP_STMT in a constructor for a literal class,
- but we can in a constexpr constructor for a non-literal class. Just
- ignore it; either all the initialization will be constant, in which
- case the cleanup can't run, or it can't be constexpr.
- Still recurse into CLEANUP_BODY. */
- return build_data_member_initialization (CLEANUP_BODY (t), vec);
- }
- if (TREE_CODE (t) == CONVERT_EXPR)
- t = TREE_OPERAND (t, 0);
- if (TREE_CODE (t) == INIT_EXPR
- /* vptr initialization shows up as a MODIFY_EXPR. In C++14 we only
- use what this function builds for cx_check_missing_mem_inits, and
- assignment in the ctor body doesn't count. */
- || (cxx_dialect < cxx14 && TREE_CODE (t) == MODIFY_EXPR))
- {
- member = TREE_OPERAND (t, 0);
- init = break_out_target_exprs (TREE_OPERAND (t, 1));
- }
- else if (TREE_CODE (t) == CALL_EXPR)
- {
- tree fn = get_callee_fndecl (t);
- if (!fn || !DECL_CONSTRUCTOR_P (fn))
- /* We're only interested in calls to subobject constructors. */
- return true;
- member = CALL_EXPR_ARG (t, 0);
- /* We don't use build_cplus_new here because it complains about
- abstract bases. Leaving the call unwrapped means that it has the
- wrong type, but cxx_eval_constant_expression doesn't care. */
- init = break_out_target_exprs (t);
- }
- else if (TREE_CODE (t) == BIND_EXPR)
- return build_data_member_initialization (BIND_EXPR_BODY (t), vec);
- else
- /* Don't add anything else to the CONSTRUCTOR. */
- return true;
- if (INDIRECT_REF_P (member))
- member = TREE_OPERAND (member, 0);
- if (TREE_CODE (member) == NOP_EXPR)
- {
- tree op = member;
- STRIP_NOPS (op);
- if (TREE_CODE (op) == ADDR_EXPR)
- {
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (TREE_TYPE (op)),
- TREE_TYPE (TREE_TYPE (member))));
- /* Initializing a cv-qualified member; we need to look through
- the const_cast. */
- member = op;
- }
- else if (op == current_class_ptr
- && (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (TREE_TYPE (member)),
- current_class_type)))
- /* Delegating constructor. */
- member = op;
- else
- {
- /* This is an initializer for an empty base; keep it for now so
- we can check it in cxx_eval_bare_aggregate. */
- gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
- }
- }
- if (TREE_CODE (member) == ADDR_EXPR)
- member = TREE_OPERAND (member, 0);
- if (TREE_CODE (member) == COMPONENT_REF)
- {
- tree aggr = TREE_OPERAND (member, 0);
- if (TREE_CODE (aggr) != COMPONENT_REF)
- /* Normal member initialization. */
- member = TREE_OPERAND (member, 1);
- else if (ANON_AGGR_TYPE_P (TREE_TYPE (aggr)))
- /* Initializing a member of an anonymous union. */
- return build_anon_member_initialization (member, init, vec);
- else
- /* We're initializing a vtable pointer in a base. Leave it as
- COMPONENT_REF so we remember the path to get to the vfield. */
- gcc_assert (TREE_TYPE (member) == vtbl_ptr_type_node);
- }
- CONSTRUCTOR_APPEND_ELT (*vec, member, init);
- return true;
- }
- /* Subroutine of check_constexpr_ctor_body_1 and constexpr_fn_retval.
- In C++11 mode checks that the TYPE_DECLs in the BIND_EXPR_VARS of a
- BIND_EXPR conform to 7.1.5/3/4 on typedef and alias declarations. */
- static bool
- check_constexpr_bind_expr_vars (tree t)
- {
- gcc_assert (TREE_CODE (t) == BIND_EXPR);
- for (tree var = BIND_EXPR_VARS (t); var; var = DECL_CHAIN (var))
- if (TREE_CODE (var) == TYPE_DECL
- && DECL_IMPLICIT_TYPEDEF_P (var)
- && !LAMBDA_TYPE_P (TREE_TYPE (var)))
- return false;
- return true;
- }
- /* Subroutine of check_constexpr_ctor_body. */
- static bool
- check_constexpr_ctor_body_1 (tree last, tree list)
- {
- switch (TREE_CODE (list))
- {
- case DECL_EXPR:
- if (TREE_CODE (DECL_EXPR_DECL (list)) == USING_DECL)
- return true;
- return false;
- case CLEANUP_POINT_EXPR:
- return check_constexpr_ctor_body (last, TREE_OPERAND (list, 0),
- /*complain=*/false);
- case BIND_EXPR:
- if (!check_constexpr_bind_expr_vars (list)
- || !check_constexpr_ctor_body (last, BIND_EXPR_BODY (list),
- /*complain=*/false))
- return false;
- return true;
- case USING_STMT:
- case STATIC_ASSERT:
- return true;
- default:
- return false;
- }
- }
- /* Make sure that there are no statements after LAST in the constructor
- body represented by LIST. */
- bool
- check_constexpr_ctor_body (tree last, tree list, bool complain)
- {
- /* C++14 doesn't require a constexpr ctor to have an empty body. */
- if (cxx_dialect >= cxx14)
- return true;
- bool ok = true;
- if (TREE_CODE (list) == STATEMENT_LIST)
- {
- tree_stmt_iterator i = tsi_last (list);
- for (; !tsi_end_p (i); tsi_prev (&i))
- {
- tree t = tsi_stmt (i);
- if (t == last)
- break;
- if (!check_constexpr_ctor_body_1 (last, t))
- {
- ok = false;
- break;
- }
- }
- }
- else if (list != last
- && !check_constexpr_ctor_body_1 (last, list))
- ok = false;
- if (!ok)
- {
- if (complain)
- error ("constexpr constructor does not have empty body");
- DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
- }
- return ok;
- }
- /* V is a vector of constructor elements built up for the base and member
- initializers of a constructor for TYPE. They need to be in increasing
- offset order, which they might not be yet if TYPE has a primary base
- which is not first in the base-clause or a vptr and at least one base
- all of which are non-primary. */
- static vec<constructor_elt, va_gc> *
- sort_constexpr_mem_initializers (tree type, vec<constructor_elt, va_gc> *v)
- {
- tree pri = CLASSTYPE_PRIMARY_BINFO (type);
- tree field_type;
- unsigned i;
- constructor_elt *ce;
- if (pri)
- field_type = BINFO_TYPE (pri);
- else if (TYPE_CONTAINS_VPTR_P (type))
- field_type = vtbl_ptr_type_node;
- else
- return v;
- /* Find the element for the primary base or vptr and move it to the
- beginning of the vec. */
- for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
- if (TREE_TYPE (ce->index) == field_type)
- break;
- if (i > 0 && i < vec_safe_length (v))
- {
- vec<constructor_elt, va_gc> &vref = *v;
- constructor_elt elt = vref[i];
- for (; i > 0; --i)
- vref[i] = vref[i-1];
- vref[0] = elt;
- }
- return v;
- }
- /* Build compile-time evalable representations of member-initializer list
- for a constexpr constructor. */
- static tree
- build_constexpr_constructor_member_initializers (tree type, tree body)
- {
- vec<constructor_elt, va_gc> *vec = NULL;
- bool ok = true;
- if (TREE_CODE (body) == MUST_NOT_THROW_EXPR
- || TREE_CODE (body) == EH_SPEC_BLOCK)
- body = TREE_OPERAND (body, 0);
- if (TREE_CODE (body) == STATEMENT_LIST)
- {
- for (tree_stmt_iterator i = tsi_start (body);
- !tsi_end_p (i); tsi_next (&i))
- {
- body = tsi_stmt (i);
- if (TREE_CODE (body) == BIND_EXPR)
- break;
- }
- }
- if (TREE_CODE (body) == BIND_EXPR)
- body = BIND_EXPR_BODY (body);
- if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
- {
- body = TREE_OPERAND (body, 0);
- if (TREE_CODE (body) == EXPR_STMT)
- body = TREE_OPERAND (body, 0);
- if (TREE_CODE (body) == INIT_EXPR
- && (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (TREE_OPERAND (body, 0)),
- current_class_type)))
- {
- /* Trivial copy. */
- return TREE_OPERAND (body, 1);
- }
- ok = build_data_member_initialization (body, &vec);
- }
- else if (TREE_CODE (body) == STATEMENT_LIST)
- {
- tree_stmt_iterator i;
- for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
- {
- ok = build_data_member_initialization (tsi_stmt (i), &vec);
- if (!ok)
- break;
- }
- }
- else if (TREE_CODE (body) == TRY_BLOCK)
- {
- error ("body of %<constexpr%> constructor cannot be "
- "a function-try-block");
- return error_mark_node;
- }
- else if (EXPR_P (body))
- ok = build_data_member_initialization (body, &vec);
- else
- gcc_assert (errorcount > 0);
- if (ok)
- {
- if (vec_safe_length (vec) > 0)
- {
- /* In a delegating constructor, return the target. */
- constructor_elt *ce = &(*vec)[0];
- if (ce->index == current_class_ptr)
- {
- body = ce->value;
- vec_free (vec);
- return body;
- }
- }
- vec = sort_constexpr_mem_initializers (type, vec);
- return build_constructor (type, vec);
- }
- else
- return error_mark_node;
- }
- /* Subroutine of register_constexpr_fundef. BODY is the body of a function
- declared to be constexpr, or a sub-statement thereof. Returns the
- return value if suitable, error_mark_node for a statement not allowed in
- a constexpr function, or NULL_TREE if no return value was found. */
- static tree
- constexpr_fn_retval (tree body)
- {
- switch (TREE_CODE (body))
- {
- case STATEMENT_LIST:
- {
- tree_stmt_iterator i;
- tree expr = NULL_TREE;
- for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
- {
- tree s = constexpr_fn_retval (tsi_stmt (i));
- if (s == error_mark_node)
- return error_mark_node;
- else if (s == NULL_TREE)
- /* Keep iterating. */;
- else if (expr)
- /* Multiple return statements. */
- return error_mark_node;
- else
- expr = s;
- }
- return expr;
- }
- case RETURN_EXPR:
- return break_out_target_exprs (TREE_OPERAND (body, 0));
- case DECL_EXPR:
- {
- tree decl = DECL_EXPR_DECL (body);
- if (TREE_CODE (decl) == USING_DECL
- /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */
- || DECL_ARTIFICIAL (decl))
- return NULL_TREE;
- return error_mark_node;
- }
- case CLEANUP_POINT_EXPR:
- return constexpr_fn_retval (TREE_OPERAND (body, 0));
- case BIND_EXPR:
- if (!check_constexpr_bind_expr_vars (body))
- return error_mark_node;
- return constexpr_fn_retval (BIND_EXPR_BODY (body));
- case USING_STMT:
- return NULL_TREE;
- default:
- return error_mark_node;
- }
- }
- /* Subroutine of register_constexpr_fundef. BODY is the DECL_SAVED_TREE of
- FUN; do the necessary transformations to turn it into a single expression
- that we can store in the hash table. */
- static tree
- massage_constexpr_body (tree fun, tree body)
- {
- if (DECL_CONSTRUCTOR_P (fun))
- body = build_constexpr_constructor_member_initializers
- (DECL_CONTEXT (fun), body);
- else if (cxx_dialect < cxx14)
- {
- if (TREE_CODE (body) == EH_SPEC_BLOCK)
- body = EH_SPEC_STMTS (body);
- if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
- body = TREE_OPERAND (body, 0);
- body = constexpr_fn_retval (body);
- }
- return body;
- }
- /* FUN is a constexpr constructor with massaged body BODY. Return true
- if some bases/fields are uninitialized, and complain if COMPLAIN. */
- static bool
- cx_check_missing_mem_inits (tree fun, tree body, bool complain)
- {
- bool bad;
- tree field;
- unsigned i, nelts;
- tree ctype;
- if (TREE_CODE (body) != CONSTRUCTOR)
- return false;
- nelts = CONSTRUCTOR_NELTS (body);
- ctype = DECL_CONTEXT (fun);
- field = TYPE_FIELDS (ctype);
- if (TREE_CODE (ctype) == UNION_TYPE)
- {
- if (nelts == 0 && next_initializable_field (field))
- {
- if (complain)
- error ("%<constexpr%> constructor for union %qT must "
- "initialize exactly one non-static data member", ctype);
- return true;
- }
- return false;
- }
- bad = false;
- for (i = 0; i <= nelts; ++i)
- {
- tree index;
- if (i == nelts)
- index = NULL_TREE;
- else
- {
- index = CONSTRUCTOR_ELT (body, i)->index;
- /* Skip base and vtable inits. */
- if (TREE_CODE (index) != FIELD_DECL
- || DECL_ARTIFICIAL (index))
- continue;
- }
- for (; field != index; field = DECL_CHAIN (field))
- {
- tree ftype;
- if (TREE_CODE (field) != FIELD_DECL
- || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
- || DECL_ARTIFICIAL (field))
- continue;
- ftype = strip_array_types (TREE_TYPE (field));
- if (type_has_constexpr_default_constructor (ftype))
- {
- /* It's OK to skip a member with a trivial constexpr ctor.
- A constexpr ctor that isn't trivial should have been
- added in by now. */
- gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype)
- || errorcount != 0);
- continue;
- }
- if (!complain)
- return true;
- error ("member %qD must be initialized by mem-initializer "
- "in %<constexpr%> constructor", field);
- inform (DECL_SOURCE_LOCATION (field), "declared here");
- bad = true;
- }
- if (field == NULL_TREE)
- break;
- field = DECL_CHAIN (field);
- }
- return bad;
- }
- /* We are processing the definition of the constexpr function FUN.
- Check that its BODY fulfills the propriate requirements and
- enter it in the constexpr function definition table.
- For constructor BODY is actually the TREE_LIST of the
- member-initializer list. */
- tree
- register_constexpr_fundef (tree fun, tree body)
- {
- constexpr_fundef entry;
- constexpr_fundef **slot;
- if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
- return NULL;
- body = massage_constexpr_body (fun, body);
- if (body == NULL_TREE || body == error_mark_node)
- {
- if (!DECL_CONSTRUCTOR_P (fun))
- error ("body of constexpr function %qD not a return-statement", fun);
- return NULL;
- }
- if (!potential_rvalue_constant_expression (body))
- {
- if (!DECL_GENERATED_P (fun))
- require_potential_rvalue_constant_expression (body);
- return NULL;
- }
- if (DECL_CONSTRUCTOR_P (fun)
- && cx_check_missing_mem_inits (fun, body, !DECL_GENERATED_P (fun)))
- return NULL;
- /* Create the constexpr function table if necessary. */
- if (constexpr_fundef_table == NULL)
- constexpr_fundef_table
- = hash_table<constexpr_fundef_hasher>::create_ggc (101);
- entry.decl = fun;
- entry.body = body;
- slot = constexpr_fundef_table->find_slot (&entry, INSERT);
- gcc_assert (*slot == NULL);
- *slot = ggc_alloc<constexpr_fundef> ();
- **slot = entry;
- return fun;
- }
- /* FUN is a non-constexpr function called in a context that requires a
- constant expression. If it comes from a constexpr template, explain why
- the instantiation isn't constexpr. */
- void
- explain_invalid_constexpr_fn (tree fun)
- {
- static hash_set<tree> *diagnosed;
- tree body;
- location_t save_loc;
- /* Only diagnose defaulted functions or instantiations. */
- if (!DECL_DEFAULTED_FN (fun)
- && !is_instantiation_of_constexpr (fun))
- return;
- if (diagnosed == NULL)
- diagnosed = new hash_set<tree>;
- if (diagnosed->add (fun))
- /* Already explained. */
- return;
- save_loc = input_location;
- input_location = DECL_SOURCE_LOCATION (fun);
- inform (0, "%q+D is not usable as a constexpr function because:", fun);
- /* First check the declaration. */
- if (is_valid_constexpr_fn (fun, true))
- {
- /* Then if it's OK, the body. */
- if (!DECL_DECLARED_CONSTEXPR_P (fun))
- explain_implicit_non_constexpr (fun);
- else
- {
- body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
- require_potential_rvalue_constant_expression (body);
- if (DECL_CONSTRUCTOR_P (fun))
- cx_check_missing_mem_inits (fun, body, true);
- }
- }
- input_location = save_loc;
- }
- /* Objects of this type represent calls to constexpr functions
- along with the bindings of parameters to their arguments, for
- the purpose of compile time evaluation. */
- struct GTY((for_user)) constexpr_call {
- /* Description of the constexpr function definition. */
- constexpr_fundef *fundef;
- /* Parameter bindings environment. A TREE_LIST where each TREE_PURPOSE
- is a parameter _DECL and the TREE_VALUE is the value of the parameter.
- Note: This arrangement is made to accommodate the use of
- iterative_hash_template_arg (see pt.c). If you change this
- representation, also change the hash calculation in
- cxx_eval_call_expression. */
- tree bindings;
- /* Result of the call.
- NULL means the call is being evaluated.
- error_mark_node means that the evaluation was erroneous;
- otherwise, the actuall value of the call. */
- tree result;
- /* The hash of this call; we remember it here to avoid having to
- recalculate it when expanding the hash table. */
- hashval_t hash;
- };
- struct constexpr_call_hasher : ggc_hasher<constexpr_call *>
- {
- static hashval_t hash (constexpr_call *);
- static bool equal (constexpr_call *, constexpr_call *);
- };
- /* The constexpr expansion context. CALL is the current function
- expansion, CTOR is the current aggregate initializer, OBJECT is the
- object being initialized by CTOR, either a VAR_DECL or a _REF. VALUES
- is a map of values of variables initialized within the expression. */
- struct constexpr_ctx {
- /* The innermost call we're evaluating. */
- constexpr_call *call;
- /* Values for any temporaries or local variables within the
- constant-expression. */
- hash_map<tree,tree> *values;
- /* The CONSTRUCTOR we're currently building up for an aggregate
- initializer. */
- tree ctor;
- /* The object we're building the CONSTRUCTOR for. */
- tree object;
- /* Whether we should error on a non-constant expression or fail quietly. */
- bool quiet;
- /* Whether we are strictly conforming to constant expression rules or
- trying harder to get a constant value. */
- bool strict;
- };
- /* A table of all constexpr calls that have been evaluated by the
- compiler in this translation unit. */
- static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table;
- static tree cxx_eval_constant_expression (const constexpr_ctx *, tree,
- bool, bool *, bool *, tree * = NULL);
- /* Compute a hash value for a constexpr call representation. */
- inline hashval_t
- constexpr_call_hasher::hash (constexpr_call *info)
- {
- return info->hash;
- }
- /* Return true if the objects pointed to by P and Q represent calls
- to the same constexpr function with the same arguments.
- Otherwise, return false. */
- bool
- constexpr_call_hasher::equal (constexpr_call *lhs, constexpr_call *rhs)
- {
- tree lhs_bindings;
- tree rhs_bindings;
- if (lhs == rhs)
- return 1;
- if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
- return 0;
- lhs_bindings = lhs->bindings;
- rhs_bindings = rhs->bindings;
- while (lhs_bindings != NULL && rhs_bindings != NULL)
- {
- tree lhs_arg = TREE_VALUE (lhs_bindings);
- tree rhs_arg = TREE_VALUE (rhs_bindings);
- gcc_assert (TREE_TYPE (lhs_arg) == TREE_TYPE (rhs_arg));
- if (!cp_tree_equal (lhs_arg, rhs_arg))
- return 0;
- lhs_bindings = TREE_CHAIN (lhs_bindings);
- rhs_bindings = TREE_CHAIN (rhs_bindings);
- }
- return lhs_bindings == rhs_bindings;
- }
- /* Initialize the constexpr call table, if needed. */
- static void
- maybe_initialize_constexpr_call_table (void)
- {
- if (constexpr_call_table == NULL)
- constexpr_call_table = hash_table<constexpr_call_hasher>::create_ggc (101);
- }
- /* We have an expression tree T that represents a call, either CALL_EXPR
- or AGGR_INIT_EXPR. If the call is lexically to a named function,
- retrun the _DECL for that function. */
- static tree
- get_function_named_in_call (tree t)
- {
- tree fun = NULL;
- switch (TREE_CODE (t))
- {
- case CALL_EXPR:
- fun = CALL_EXPR_FN (t);
- break;
- case AGGR_INIT_EXPR:
- fun = AGGR_INIT_EXPR_FN (t);
- break;
- default:
- gcc_unreachable();
- break;
- }
- if (fun && TREE_CODE (fun) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
- fun = TREE_OPERAND (fun, 0);
- return fun;
- }
- /* We have an expression tree T that represents a call, either CALL_EXPR
- or AGGR_INIT_EXPR. Return the Nth argument. */
- static inline tree
- get_nth_callarg (tree t, int n)
- {
- switch (TREE_CODE (t))
- {
- case CALL_EXPR:
- return CALL_EXPR_ARG (t, n);
- case AGGR_INIT_EXPR:
- return AGGR_INIT_EXPR_ARG (t, n);
- default:
- gcc_unreachable ();
- return NULL;
- }
- }
- /* Look up the binding of the function parameter T in a constexpr
- function call context CALL. */
- static tree
- lookup_parameter_binding (const constexpr_call *call, tree t)
- {
- tree b = purpose_member (t, call->bindings);
- return TREE_VALUE (b);
- }
- /* Attempt to evaluate T which represents a call to a builtin function.
- We assume here that all builtin functions evaluate to scalar types
- represented by _CST nodes. */
- static tree
- cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- const int nargs = call_expr_nargs (t);
- tree *args = (tree *) alloca (nargs * sizeof (tree));
- tree new_call;
- int i;
- for (i = 0; i < nargs; ++i)
- {
- args[i] = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, i),
- lval,
- non_constant_p, overflow_p);
- if (ctx->quiet && *non_constant_p)
- return t;
- }
- if (*non_constant_p)
- return t;
- new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
- CALL_EXPR_FN (t), nargs, args);
- VERIFY_CONSTANT (new_call);
- return new_call;
- }
- /* TEMP is the constant value of a temporary object of type TYPE. Adjust
- the type of the value to match. */
- static tree
- adjust_temp_type (tree type, tree temp)
- {
- if (TREE_TYPE (temp) == type)
- return temp;
- /* Avoid wrapping an aggregate value in a NOP_EXPR. */
- if (TREE_CODE (temp) == CONSTRUCTOR)
- return build_constructor (type, CONSTRUCTOR_ELTS (temp));
- gcc_assert (scalarish_type_p (type));
- return cp_fold_convert (type, temp);
- }
- /* True if we want to use the new handling of constexpr calls based on
- DECL_SAVED_TREE. */
- #define use_new_call true
- /* Subroutine of cxx_eval_call_expression.
- We are processing a call expression (either CALL_EXPR or
- AGGR_INIT_EXPR) in the context of CTX. Evaluate
- all arguments and bind their values to correspondings
- parameters, making up the NEW_CALL context. */
- static void
- cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
- constexpr_call *new_call,
- bool *non_constant_p, bool *overflow_p,
- bool *non_constant_args)
- {
- const int nargs = call_expr_nargs (t);
- tree fun = new_call->fundef->decl;
- tree parms = DECL_ARGUMENTS (fun);
- int i;
- tree *p = &new_call->bindings;
- for (i = 0; i < nargs; ++i)
- {
- tree x, arg;
- tree type = parms ? TREE_TYPE (parms) : void_type_node;
- x = get_nth_callarg (t, i);
- /* For member function, the first argument is a pointer to the implied
- object. For a constructor, it might still be a dummy object, in
- which case we get the real argument from ctx. */
- if (i == 0 && DECL_CONSTRUCTOR_P (fun)
- && is_dummy_object (x))
- {
- x = ctx->object;
- x = cp_build_addr_expr (x, tf_warning_or_error);
- }
- bool lval = false;
- if (parms && DECL_BY_REFERENCE (parms) && !use_new_call)
- {
- /* cp_genericize made this a reference for argument passing, but
- we don't want to treat it like one for C++11 constexpr
- evaluation. C++14 constexpr evaluation uses the genericized
- DECL_SAVED_TREE. */
- gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
- gcc_assert (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE);
- type = TREE_TYPE (type);
- x = convert_from_reference (x);
- lval = true;
- }
- arg = cxx_eval_constant_expression (ctx, x, lval,
- non_constant_p, overflow_p);
- /* Don't VERIFY_CONSTANT here. */
- if (*non_constant_p && ctx->quiet)
- return;
- /* Just discard ellipsis args after checking their constantitude. */
- if (!parms)
- continue;
- if (*non_constant_p)
- /* Don't try to adjust the type of non-constant args. */
- goto next;
- /* Make sure the binding has the same type as the parm. */
- if (TREE_CODE (type) != REFERENCE_TYPE)
- arg = adjust_temp_type (type, arg);
- if (!TREE_CONSTANT (arg))
- *non_constant_args = true;
- *p = build_tree_list (parms, arg);
- p = &TREE_CHAIN (*p);
- next:
- parms = TREE_CHAIN (parms);
- }
- }
- /* Variables and functions to manage constexpr call expansion context.
- These do not need to be marked for PCH or GC. */
- /* FIXME remember and print actual constant arguments. */
- static vec<tree> call_stack = vNULL;
- static int call_stack_tick;
- static int last_cx_error_tick;
- static bool
- push_cx_call_context (tree call)
- {
- ++call_stack_tick;
- if (!EXPR_HAS_LOCATION (call))
- SET_EXPR_LOCATION (call, input_location);
- call_stack.safe_push (call);
- if (call_stack.length () > (unsigned) max_constexpr_depth)
- return false;
- return true;
- }
- static void
- pop_cx_call_context (void)
- {
- ++call_stack_tick;
- call_stack.pop ();
- }
- vec<tree>
- cx_error_context (void)
- {
- vec<tree> r = vNULL;
- if (call_stack_tick != last_cx_error_tick
- && !call_stack.is_empty ())
- r = call_stack;
- last_cx_error_tick = call_stack_tick;
- return r;
- }
- /* Subroutine of cxx_eval_constant_expression.
- Evaluate the call expression tree T in the context of OLD_CALL expression
- evaluation. */
- static tree
- cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- location_t loc = EXPR_LOC_OR_LOC (t, input_location);
- tree fun = get_function_named_in_call (t);
- constexpr_call new_call = { NULL, NULL, NULL, 0 };
- bool depth_ok;
- if (fun == NULL_TREE)
- switch (CALL_EXPR_IFN (t))
- {
- case IFN_UBSAN_NULL:
- case IFN_UBSAN_BOUNDS:
- case IFN_UBSAN_VPTR:
- return void_node;
- default:
- if (!ctx->quiet)
- error_at (loc, "call to internal function");
- *non_constant_p = true;
- return t;
- }
- if (TREE_CODE (fun) != FUNCTION_DECL)
- {
- /* Might be a constexpr function pointer. */
- fun = cxx_eval_constant_expression (ctx, fun,
- /*lval*/false, non_constant_p,
- overflow_p);
- STRIP_NOPS (fun);
- if (TREE_CODE (fun) == ADDR_EXPR)
- fun = TREE_OPERAND (fun, 0);
- }
- if (TREE_CODE (fun) != FUNCTION_DECL)
- {
- if (!ctx->quiet && !*non_constant_p)
- error_at (loc, "expression %qE does not designate a constexpr "
- "function", fun);
- *non_constant_p = true;
- return t;
- }
- if (DECL_CLONED_FUNCTION_P (fun))
- fun = DECL_CLONED_FUNCTION (fun);
- if (is_ubsan_builtin_p (fun))
- return void_node;
- if (is_builtin_fn (fun))
- return cxx_eval_builtin_function_call (ctx, t,
- lval, non_constant_p, overflow_p);
- if (!DECL_DECLARED_CONSTEXPR_P (fun))
- {
- if (!ctx->quiet)
- {
- error_at (loc, "call to non-constexpr function %qD", fun);
- explain_invalid_constexpr_fn (fun);
- }
- *non_constant_p = true;
- return t;
- }
- /* Shortcut trivial constructor/op=. */
- if (trivial_fn_p (fun))
- {
- if (call_expr_nargs (t) == 2)
- {
- tree arg = convert_from_reference (get_nth_callarg (t, 1));
- return cxx_eval_constant_expression (ctx, arg,
- lval, non_constant_p,
- overflow_p);
- }
- else if (TREE_CODE (t) == AGGR_INIT_EXPR
- && AGGR_INIT_ZERO_FIRST (t))
- return build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false);
- }
- /* We can't defer instantiating the function any longer. */
- if (!DECL_INITIAL (fun)
- && DECL_TEMPLOID_INSTANTIATION (fun))
- {
- ++function_depth;
- instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
- --function_depth;
- }
- /* If in direct recursive call, optimize definition search. */
- if (ctx && ctx->call && ctx->call->fundef->decl == fun)
- new_call.fundef = ctx->call->fundef;
- else
- {
- new_call.fundef = retrieve_constexpr_fundef (fun);
- if (new_call.fundef == NULL || new_call.fundef->body == NULL)
- {
- if (!ctx->quiet)
- {
- if (DECL_INITIAL (fun))
- {
- /* The definition of fun was somehow unsuitable. */
- error_at (loc, "%qD called in a constant expression", fun);
- explain_invalid_constexpr_fn (fun);
- }
- else
- error_at (loc, "%qD used before its definition", fun);
- }
- *non_constant_p = true;
- return t;
- }
- }
- constexpr_ctx new_ctx = *ctx;
- if (DECL_CONSTRUCTOR_P (fun) && !ctx->object
- && TREE_CODE (t) == AGGR_INIT_EXPR)
- {
- /* We want to have an initialization target for an AGGR_INIT_EXPR.
- If we don't already have one in CTX, use the AGGR_INIT_EXPR_SLOT. */
- new_ctx.object = AGGR_INIT_EXPR_SLOT (t);
- tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL);
- CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor) = true;
- ctx->values->put (new_ctx.object, ctor);
- ctx = &new_ctx;
- }
- bool non_constant_args = false;
- cxx_bind_parameters_in_call (ctx, t, &new_call,
- non_constant_p, overflow_p, &non_constant_args);
- if (*non_constant_p)
- return t;
- depth_ok = push_cx_call_context (t);
- tree result = NULL_TREE;
- constexpr_call *entry = NULL;
- if (!non_constant_args)
- {
- new_call.hash = iterative_hash_template_arg
- (new_call.bindings, constexpr_fundef_hasher::hash (new_call.fundef));
- /* If we have seen this call before, we are done. */
- maybe_initialize_constexpr_call_table ();
- constexpr_call **slot
- = constexpr_call_table->find_slot (&new_call, INSERT);
- entry = *slot;
- if (entry == NULL)
- {
- /* We need to keep a pointer to the entry, not just the slot, as the
- slot can move in the call to cxx_eval_builtin_function_call. */
- *slot = entry = ggc_alloc<constexpr_call> ();
- *entry = new_call;
- }
- /* Calls which are in progress have their result set to NULL
- so that we can detect circular dependencies. */
- else if (entry->result == NULL)
- {
- if (!ctx->quiet)
- error ("call has circular dependency");
- *non_constant_p = true;
- entry->result = result = error_mark_node;
- }
- else
- result = entry->result;
- }
- if (!depth_ok)
- {
- if (!ctx->quiet)
- error ("constexpr evaluation depth exceeds maximum of %d (use "
- "-fconstexpr-depth= to increase the maximum)",
- max_constexpr_depth);
- *non_constant_p = true;
- result = error_mark_node;
- }
- else
- {
- if (!result || result == error_mark_node)
- {
- if (!use_new_call)
- {
- new_ctx.call = &new_call;
- result = (cxx_eval_constant_expression
- (&new_ctx, new_call.fundef->body,
- lval,
- non_constant_p, overflow_p));
- }
- else
- {
- if (DECL_SAVED_TREE (fun) == NULL_TREE
- && (DECL_CONSTRUCTOR_P (fun) || DECL_DESTRUCTOR_P (fun)))
- /* The maybe-in-charge 'tor had its DECL_SAVED_TREE
- cleared, try a clone. */
- for (fun = DECL_CHAIN (fun);
- fun && DECL_CLONED_FUNCTION_P (fun);
- fun = DECL_CHAIN (fun))
- if (DECL_SAVED_TREE (fun))
- break;
- if (!DECL_SAVED_TREE (fun))
- {
- /* cgraph/gimplification have released the DECL_SAVED_TREE
- for this function. Fail gracefully. */
- gcc_assert (ctx->quiet);
- *non_constant_p = true;
- return t;
- }
- tree parms, res;
- /* Unshare the whole function body. */
- tree body = copy_fn (fun, parms, res);
- /* Associate the bindings with the remapped parms. */
- tree bound = new_call.bindings;
- tree remapped = parms;
- while (bound)
- {
- tree oparm = TREE_PURPOSE (bound);
- tree arg = TREE_VALUE (bound);
- gcc_assert (DECL_NAME (remapped) == DECL_NAME (oparm));
- ctx->values->put (remapped, arg);
- bound = TREE_CHAIN (bound);
- remapped = DECL_CHAIN (remapped);
- }
- /* Add the RESULT_DECL to the values map, too. */
- tree slot = NULL_TREE;
- if (DECL_BY_REFERENCE (res))
- {
- slot = AGGR_INIT_EXPR_SLOT (t);
- tree addr = build_address (slot);
- addr = build_nop (TREE_TYPE (res), addr);
- ctx->values->put (res, addr);
- ctx->values->put (slot, NULL_TREE);
- }
- else
- ctx->values->put (res, NULL_TREE);
- tree jump_target = NULL_TREE;
- cxx_eval_constant_expression (ctx, body,
- lval, non_constant_p, overflow_p,
- &jump_target);
- if (DECL_CONSTRUCTOR_P (fun))
- /* This can be null for a subobject constructor call, in
- which case what we care about is the initialization
- side-effects rather than the value. We could get at the
- value by evaluating *this, but we don't bother; there's
- no need to put such a call in the hash table. */
- result = lval ? ctx->object : ctx->ctor;
- else if (VOID_TYPE_P (TREE_TYPE (res)))
- result = void_node;
- else
- {
- result = *ctx->values->get (slot ? slot : res);
- if (result == NULL_TREE && !*non_constant_p)
- {
- if (!ctx->quiet)
- error ("constexpr call flows off the end "
- "of the function");
- *non_constant_p = true;
- }
- }
- /* Remove the parms/result from the values map. Is it worth
- bothering to do this when the map itself is only live for
- one constexpr evaluation? If so, maybe also clear out
- other vars from call, maybe in BIND_EXPR handling? */
- ctx->values->remove (res);
- if (slot)
- ctx->values->remove (slot);
- for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
- ctx->values->remove (parm);
- }
- }
- if (result == error_mark_node)
- *non_constant_p = true;
- if (*non_constant_p)
- result = error_mark_node;
- else if (result)
- {
- /* If this was a call to initialize an object, set the type of
- the CONSTRUCTOR to the type of that object. */
- if (DECL_CONSTRUCTOR_P (fun) && !use_new_call)
- {
- tree ob_arg = get_nth_callarg (t, 0);
- STRIP_NOPS (ob_arg);
- gcc_assert (TYPE_PTR_P (TREE_TYPE (ob_arg))
- && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (ob_arg))));
- result = adjust_temp_type (TREE_TYPE (TREE_TYPE (ob_arg)),
- result);
- }
- }
- else
- result = void_node;
- if (entry)
- entry->result = result;
- }
- pop_cx_call_context ();
- return unshare_expr (result);
- }
- /* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */
- bool
- reduced_constant_expression_p (tree t)
- {
- switch (TREE_CODE (t))
- {
- case PTRMEM_CST:
- /* Even if we can't lower this yet, it's constant. */
- return true;
- case CONSTRUCTOR:
- /* And we need to handle PTRMEM_CST wrapped in a CONSTRUCTOR. */
- tree elt; unsigned HOST_WIDE_INT idx;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), idx, elt)
- if (!reduced_constant_expression_p (elt))
- return false;
- return true;
- default:
- /* FIXME are we calling this too much? */
- return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE;
- }
- }
- /* Some expressions may have constant operands but are not constant
- themselves, such as 1/0. Call this function (or rather, the macro
- following it) to check for that condition.
- We only call this in places that require an arithmetic constant, not in
- places where we might have a non-constant expression that can be a
- component of a constant expression, such as the address of a constexpr
- variable that might be dereferenced later. */
- static bool
- verify_constant (tree t, bool allow_non_constant, bool *non_constant_p,
- bool *overflow_p)
- {
- if (!*non_constant_p && !reduced_constant_expression_p (t))
- {
- if (!allow_non_constant)
- error ("%q+E is not a constant expression", t);
- *non_constant_p = true;
- }
- if (TREE_OVERFLOW_P (t))
- {
- if (!allow_non_constant)
- {
- permerror (input_location, "overflow in constant expression");
- /* If we're being permissive (and are in an enforcing
- context), ignore the overflow. */
- if (flag_permissive)
- return *non_constant_p;
- }
- *overflow_p = true;
- }
- return *non_constant_p;
- }
- /* Check whether the shift operation with code CODE and type TYPE on LHS
- and RHS is undefined. If it is, give an error with an explanation,
- and return true; return false otherwise. */
- static bool
- cxx_eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
- enum tree_code code, tree type, tree lhs, tree rhs)
- {
- if ((code != LSHIFT_EXPR && code != RSHIFT_EXPR)
- || TREE_CODE (lhs) != INTEGER_CST
- || TREE_CODE (rhs) != INTEGER_CST)
- return false;
- tree lhstype = TREE_TYPE (lhs);
- unsigned HOST_WIDE_INT uprec = TYPE_PRECISION (TREE_TYPE (lhs));
- /* [expr.shift] The behavior is undefined if the right operand
- is negative, or greater than or equal to the length in bits
- of the promoted left operand. */
- if (tree_int_cst_sgn (rhs) == -1)
- {
- if (!ctx->quiet)
- error_at (loc, "right operand of shift expression %q+E is negative",
- build2_loc (loc, code, type, lhs, rhs));
- return true;
- }
- if (compare_tree_int (rhs, uprec) >= 0)
- {
- if (!ctx->quiet)
- error_at (loc, "right operand of shift expression %q+E is >= than "
- "the precision of the left operand",
- build2_loc (loc, code, type, lhs, rhs));
- return true;
- }
- /* The value of E1 << E2 is E1 left-shifted E2 bit positions; [...]
- if E1 has a signed type and non-negative value, and E1x2^E2 is
- representable in the corresponding unsigned type of the result type,
- then that value, converted to the result type, is the resulting value;
- otherwise, the behavior is undefined. */
- if (code == LSHIFT_EXPR && !TYPE_UNSIGNED (lhstype)
- && (cxx_dialect >= cxx11))
- {
- if (tree_int_cst_sgn (lhs) == -1)
- {
- if (!ctx->quiet)
- error_at (loc, "left operand of shift expression %q+E is negative",
- build2_loc (loc, code, type, lhs, rhs));
- return true;
- }
- /* For signed x << y the following:
- (unsigned) x >> ((prec (lhs) - 1) - y)
- if > 1, is undefined. The right-hand side of this formula
- is the highest bit of the LHS that can be set (starting from 0),
- so that the shift doesn't overflow. We then right-shift the LHS
- to see whether any other bit is set making the original shift
- undefined -- the result is not representable in the corresponding
- unsigned type. */
- tree t = build_int_cst (unsigned_type_node, uprec - 1);
- t = fold_build2 (MINUS_EXPR, unsigned_type_node, t, rhs);
- tree ulhs = fold_convert (unsigned_type_for (lhstype), lhs);
- t = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ulhs), ulhs, t);
- if (tree_int_cst_lt (integer_one_node, t))
- {
- if (!ctx->quiet)
- error_at (loc, "shift expression %q+E overflows",
- build2_loc (loc, code, type, lhs, rhs));
- return true;
- }
- }
- return false;
- }
- /* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce the unary expression tree T to a compile time value.
- If successful, return the value. Otherwise issue a diagnostic
- and return error_mark_node. */
- static tree
- cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t,
- bool /*lval*/,
- bool *non_constant_p, bool *overflow_p)
- {
- tree r;
- tree orig_arg = TREE_OPERAND (t, 0);
- tree arg = cxx_eval_constant_expression (ctx, orig_arg, /*lval*/false,
- non_constant_p, overflow_p);
- VERIFY_CONSTANT (arg);
- location_t loc = EXPR_LOCATION (t);
- enum tree_code code = TREE_CODE (t);
- tree type = TREE_TYPE (t);
- r = fold_unary_loc (loc, code, type, arg);
- if (r == NULL_TREE)
- {
- if (arg == orig_arg)
- r = t;
- else
- r = build1_loc (loc, code, type, arg);
- }
- VERIFY_CONSTANT (r);
- return r;
- }
- /* Subroutine of cxx_eval_constant_expression.
- Like cxx_eval_unary_expression, except for binary expressions. */
- static tree
- cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
- bool /*lval*/,
- bool *non_constant_p, bool *overflow_p)
- {
- tree r;
- tree orig_lhs = TREE_OPERAND (t, 0);
- tree orig_rhs = TREE_OPERAND (t, 1);
- tree lhs, rhs;
- lhs = cxx_eval_constant_expression (ctx, orig_lhs, /*lval*/false,
- non_constant_p, overflow_p);
- /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
- a local array in a constexpr function. */
- bool ptr = POINTER_TYPE_P (TREE_TYPE (lhs));
- if (!ptr)
- VERIFY_CONSTANT (lhs);
- rhs = cxx_eval_constant_expression (ctx, orig_rhs, /*lval*/false,
- non_constant_p, overflow_p);
- if (!ptr)
- VERIFY_CONSTANT (rhs);
- location_t loc = EXPR_LOCATION (t);
- enum tree_code code = TREE_CODE (t);
- tree type = TREE_TYPE (t);
- r = fold_binary_loc (loc, code, type, lhs, rhs);
- if (r == NULL_TREE)
- {
- if (lhs == orig_lhs && rhs == orig_rhs)
- r = t;
- else
- r = build2_loc (loc, code, type, lhs, rhs);
- }
- else if (cxx_eval_check_shift_p (loc, ctx, code, type, lhs, rhs))
- *non_constant_p = true;
- if (!ptr)
- VERIFY_CONSTANT (r);
- return r;
- }
- /* Subroutine of cxx_eval_constant_expression.
- Attempt to evaluate condition expressions. Dead branches are not
- looked into. */
- static tree
- cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target)
- {
- tree val = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
- /*lval*/false,
- non_constant_p, overflow_p);
- VERIFY_CONSTANT (val);
- /* Don't VERIFY_CONSTANT the other operands. */
- if (integer_zerop (val))
- return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2),
- lval,
- non_constant_p, overflow_p,
- jump_target);
- return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- lval,
- non_constant_p, overflow_p,
- jump_target);
- }
- /* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce a reference to an array slot. */
- static tree
- cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- tree oldary = TREE_OPERAND (t, 0);
- tree ary = cxx_eval_constant_expression (ctx, oldary,
- lval,
- non_constant_p, overflow_p);
- tree index, oldidx;
- HOST_WIDE_INT i;
- tree elem_type;
- unsigned len, elem_nchars = 1;
- if (*non_constant_p)
- return t;
- oldidx = TREE_OPERAND (t, 1);
- index = cxx_eval_constant_expression (ctx, oldidx,
- false,
- non_constant_p, overflow_p);
- VERIFY_CONSTANT (index);
- if (lval && ary == oldary && index == oldidx)
- return t;
- else if (lval)
- return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
- elem_type = TREE_TYPE (TREE_TYPE (ary));
- if (TREE_CODE (ary) == CONSTRUCTOR)
- len = CONSTRUCTOR_NELTS (ary);
- else if (TREE_CODE (ary) == STRING_CST)
- {
- elem_nchars = (TYPE_PRECISION (elem_type)
- / TYPE_PRECISION (char_type_node));
- len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
- }
- else
- {
- /* We can't do anything with other tree codes, so use
- VERIFY_CONSTANT to complain and fail. */
- VERIFY_CONSTANT (ary);
- gcc_unreachable ();
- }
- if (compare_tree_int (index, len) >= 0)
- {
- if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
- {
- /* If it's within the array bounds but doesn't have an explicit
- initializer, it's value-initialized. */
- tree val = build_value_init (elem_type, tf_warning_or_error);
- return cxx_eval_constant_expression (ctx, val,
- lval,
- non_constant_p, overflow_p);
- }
- if (!ctx->quiet)
- error ("array subscript out of bound");
- *non_constant_p = true;
- return t;
- }
- else if (tree_int_cst_lt (index, integer_zero_node))
- {
- if (!ctx->quiet)
- error ("negative array subscript");
- *non_constant_p = true;
- return t;
- }
- i = tree_to_shwi (index);
- if (TREE_CODE (ary) == CONSTRUCTOR)
- return (*CONSTRUCTOR_ELTS (ary))[i].value;
- else if (elem_nchars == 1)
- return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))),
- TREE_STRING_POINTER (ary)[i]);
- else
- {
- tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary)));
- return native_interpret_expr (type, (const unsigned char *)
- TREE_STRING_POINTER (ary)
- + i * elem_nchars, elem_nchars);
- }
- /* Don't VERIFY_CONSTANT here. */
- }
- /* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce a field access of a value of class type. */
- static tree
- cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- unsigned HOST_WIDE_INT i;
- tree field;
- tree value;
- tree part = TREE_OPERAND (t, 1);
- tree orig_whole = TREE_OPERAND (t, 0);
- tree whole = cxx_eval_constant_expression (ctx, orig_whole,
- lval,
- non_constant_p, overflow_p);
- if (whole == orig_whole)
- return t;
- if (lval)
- return fold_build3 (COMPONENT_REF, TREE_TYPE (t),
- whole, part, NULL_TREE);
- /* Don't VERIFY_CONSTANT here; we only want to check that we got a
- CONSTRUCTOR. */
- if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
- {
- if (!ctx->quiet)
- error ("%qE is not a constant expression", orig_whole);
- *non_constant_p = true;
- }
- if (DECL_MUTABLE_P (part))
- {
- if (!ctx->quiet)
- error ("mutable %qD is not usable in a constant expression", part);
- *non_constant_p = true;
- }
- if (*non_constant_p)
- return t;
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
- {
- if (field == part)
- {
- if (value)
- return value;
- else
- /* We're in the middle of initializing it. */
- break;
- }
- }
- if (TREE_CODE (TREE_TYPE (whole)) == UNION_TYPE
- && CONSTRUCTOR_NELTS (whole) > 0)
- {
- /* DR 1188 says we don't have to deal with this. */
- if (!ctx->quiet)
- error ("accessing %qD member instead of initialized %qD member in "
- "constant expression", part, CONSTRUCTOR_ELT (whole, 0)->index);
- *non_constant_p = true;
- return t;
- }
- if (CONSTRUCTOR_NO_IMPLICIT_ZERO (whole))
- {
- /* 'whole' is part of the aggregate initializer we're currently
- building; if there's no initializer for this member yet, that's an
- error. */
- if (!ctx->quiet)
- error ("accessing uninitialized member %qD", part);
- *non_constant_p = true;
- return t;
- }
- /* If there's no explicit init for this field, it's value-initialized. */
- value = build_value_init (TREE_TYPE (t), tf_warning_or_error);
- return cxx_eval_constant_expression (ctx, value,
- lval,
- non_constant_p, overflow_p);
- }
- /* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce a field access of a value of class type that is
- expressed as a BIT_FIELD_REF. */
- static tree
- cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- tree orig_whole = TREE_OPERAND (t, 0);
- tree retval, fldval, utype, mask;
- bool fld_seen = false;
- HOST_WIDE_INT istart, isize;
- tree whole = cxx_eval_constant_expression (ctx, orig_whole,
- lval,
- non_constant_p, overflow_p);
- tree start, field, value;
- unsigned HOST_WIDE_INT i;
- if (whole == orig_whole)
- return t;
- /* Don't VERIFY_CONSTANT here; we only want to check that we got a
- CONSTRUCTOR. */
- if (!*non_constant_p
- && TREE_CODE (whole) != VECTOR_CST
- && TREE_CODE (whole) != CONSTRUCTOR)
- {
- if (!ctx->quiet)
- error ("%qE is not a constant expression", orig_whole);
- *non_constant_p = true;
- }
- if (*non_constant_p)
- return t;
- if (TREE_CODE (whole) == VECTOR_CST)
- return fold_ternary (BIT_FIELD_REF, TREE_TYPE (t), whole,
- TREE_OPERAND (t, 1), TREE_OPERAND (t, 2));
- start = TREE_OPERAND (t, 2);
- istart = tree_to_shwi (start);
- isize = tree_to_shwi (TREE_OPERAND (t, 1));
- utype = TREE_TYPE (t);
- if (!TYPE_UNSIGNED (utype))
- utype = build_nonstandard_integer_type (TYPE_PRECISION (utype), 1);
- retval = build_int_cst (utype, 0);
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
- {
- tree bitpos = bit_position (field);
- if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1))
- return value;
- if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
- && TREE_CODE (value) == INTEGER_CST
- && tree_fits_shwi_p (bitpos)
- && tree_fits_shwi_p (DECL_SIZE (field)))
- {
- HOST_WIDE_INT bit = tree_to_shwi (bitpos);
- HOST_WIDE_INT sz = tree_to_shwi (DECL_SIZE (field));
- HOST_WIDE_INT shift;
- if (bit >= istart && bit + sz <= istart + isize)
- {
- fldval = fold_convert (utype, value);
- mask = build_int_cst_type (utype, -1);
- mask = fold_build2 (LSHIFT_EXPR, utype, mask,
- size_int (TYPE_PRECISION (utype) - sz));
- mask = fold_build2 (RSHIFT_EXPR, utype, mask,
- size_int (TYPE_PRECISION (utype) - sz));
- fldval = fold_build2 (BIT_AND_EXPR, utype, fldval, mask);
- shift = bit - istart;
- if (BYTES_BIG_ENDIAN)
- shift = TYPE_PRECISION (utype) - shift - sz;
- fldval = fold_build2 (LSHIFT_EXPR, utype, fldval,
- size_int (shift));
- retval = fold_build2 (BIT_IOR_EXPR, utype, retval, fldval);
- fld_seen = true;
- }
- }
- }
- if (fld_seen)
- return fold_convert (TREE_TYPE (t), retval);
- gcc_unreachable ();
- return error_mark_node;
- }
- /* Subroutine of cxx_eval_constant_expression.
- Evaluate a short-circuited logical expression T in the context
- of a given constexpr CALL. BAILOUT_VALUE is the value for
- early return. CONTINUE_VALUE is used here purely for
- sanity check purposes. */
- static tree
- cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t,
- tree bailout_value, tree continue_value,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- tree r;
- tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
- lval,
- non_constant_p, overflow_p);
- VERIFY_CONSTANT (lhs);
- if (tree_int_cst_equal (lhs, bailout_value))
- return lhs;
- gcc_assert (tree_int_cst_equal (lhs, continue_value));
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- lval, non_constant_p,
- overflow_p);
- VERIFY_CONSTANT (r);
- return r;
- }
- /* REF is a COMPONENT_REF designating a particular field. V is a vector of
- CONSTRUCTOR elements to initialize (part of) an object containing that
- field. Return a pointer to the constructor_elt corresponding to the
- initialization of the field. */
- static constructor_elt *
- base_field_constructor_elt (vec<constructor_elt, va_gc> *v, tree ref)
- {
- tree aggr = TREE_OPERAND (ref, 0);
- tree field = TREE_OPERAND (ref, 1);
- HOST_WIDE_INT i;
- constructor_elt *ce;
- gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
- if (TREE_CODE (aggr) == COMPONENT_REF)
- {
- constructor_elt *base_ce
- = base_field_constructor_elt (v, aggr);
- v = CONSTRUCTOR_ELTS (base_ce->value);
- }
- for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
- if (ce->index == field)
- return ce;
- gcc_unreachable ();
- return NULL;
- }
- /* Some of the expressions fed to the constexpr mechanism are calls to
- constructors, which have type void. In that case, return the type being
- initialized by the constructor. */
- static tree
- initialized_type (tree t)
- {
- if (TYPE_P (t))
- return t;
- tree type = cv_unqualified (TREE_TYPE (t));
- if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
- {
- /* A constructor call has void type, so we need to look deeper. */
- tree fn = get_function_named_in_call (t);
- if (fn && TREE_CODE (fn) == FUNCTION_DECL
- && DECL_CXX_CONSTRUCTOR_P (fn))
- type = DECL_CONTEXT (fn);
- }
- return type;
- }
- /* We're about to initialize element INDEX of an array or class from VALUE.
- Set up NEW_CTX appropriately by adjusting .object to refer to the
- subobject and creating a new CONSTRUCTOR if the element is itself
- a class or array. */
- static void
- init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx &new_ctx,
- tree index, tree &value)
- {
- new_ctx = *ctx;
- if (index && TREE_CODE (index) != INTEGER_CST
- && TREE_CODE (index) != FIELD_DECL)
- /* This won't have an element in the new CONSTRUCTOR. */
- return;
- tree type = initialized_type (value);
- if (!AGGREGATE_TYPE_P (type) && !VECTOR_TYPE_P (type))
- /* A non-aggregate member doesn't get its own CONSTRUCTOR. */
- return;
- /* The sub-aggregate initializer might contain a placeholder;
- update object to refer to the subobject and ctor to refer to
- the (newly created) sub-initializer. */
- if (ctx->object)
- new_ctx.object = build_ctor_subob_ref (index, type, ctx->object);
- tree elt = build_constructor (type, NULL);
- CONSTRUCTOR_NO_IMPLICIT_ZERO (elt) = true;
- new_ctx.ctor = elt;
- if (TREE_CODE (value) == TARGET_EXPR)
- /* Avoid creating another CONSTRUCTOR when we expand the TARGET_EXPR. */
- value = TARGET_EXPR_INITIAL (value);
- }
- /* We're about to process an initializer for a class or array TYPE. Make
- sure that CTX is set up appropriately. */
- static void
- verify_ctor_sanity (const constexpr_ctx *ctx, tree type)
- {
- /* We don't bother building a ctor for an empty base subobject. */
- if (is_empty_class (type))
- return;
- /* We're in the middle of an initializer that might involve placeholders;
- our caller should have created a CONSTRUCTOR for us to put the
- initializer into. We will either return that constructor or T. */
- gcc_assert (ctx->ctor);
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (ctx->ctor)));
- gcc_assert (CONSTRUCTOR_NELTS (ctx->ctor) == 0);
- if (ctx->object)
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (ctx->object)));
- gcc_assert (!ctx->object || !DECL_P (ctx->object)
- || *(ctx->values->get (ctx->object)) == ctx->ctor);
- }
- /* Subroutine of cxx_eval_constant_expression.
- The expression tree T denotes a C-style array or a C-style
- aggregate. Reduce it to a constant expression. */
- static tree
- cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
- bool changed = false;
- gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t));
- verify_ctor_sanity (ctx, TREE_TYPE (t));
- vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
- vec_alloc (*p, vec_safe_length (v));
- unsigned i; tree index, value;
- FOR_EACH_CONSTRUCTOR_ELT (v, i, index, value)
- {
- constexpr_ctx new_ctx;
- init_subob_ctx (ctx, new_ctx, index, value);
- if (new_ctx.ctor != ctx->ctor)
- /* If we built a new CONSTRUCTOR, attach it now so that other
- initializers can refer to it. */
- CONSTRUCTOR_APPEND_ELT (*p, index, new_ctx.ctor);
- tree elt = cxx_eval_constant_expression (&new_ctx, value,
- lval,
- non_constant_p, overflow_p);
- /* Don't VERIFY_CONSTANT here. */
- if (ctx->quiet && *non_constant_p)
- break;
- if (elt != value)
- changed = true;
- if (index && TREE_CODE (index) == COMPONENT_REF)
- {
- /* This is an initialization of a vfield inside a base
- subaggregate that we already initialized; push this
- initialization into the previous initialization. */
- constructor_elt *inner = base_field_constructor_elt (*p, index);
- inner->value = elt;
- changed = true;
- }
- else if (index
- && (TREE_CODE (index) == NOP_EXPR
- || TREE_CODE (index) == POINTER_PLUS_EXPR))
- {
- /* This is an initializer for an empty base; now that we've
- checked that it's constant, we can ignore it. */
- gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (index))));
- changed = true;
- }
- else if (new_ctx.ctor != ctx->ctor)
- {
- /* We appended this element above; update the value. */
- gcc_assert ((*p)->last().index == index);
- (*p)->last().value = elt;
- }
- else
- CONSTRUCTOR_APPEND_ELT (*p, index, elt);
- }
- if (*non_constant_p || !changed)
- return t;
- t = ctx->ctor;
- /* We're done building this CONSTRUCTOR, so now we can interpret an
- element without an explicit initializer as value-initialized. */
- CONSTRUCTOR_NO_IMPLICIT_ZERO (t) = false;
- if (TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
- t = fold (t);
- return t;
- }
- /* Subroutine of cxx_eval_constant_expression.
- The expression tree T is a VEC_INIT_EXPR which denotes the desired
- initialization of a non-static data member of array type. Reduce it to a
- CONSTRUCTOR.
- Note that apart from value-initialization (when VALUE_INIT is true),
- this is only intended to support value-initialization and the
- initializations done by defaulted constructors for classes with
- non-static data members of array type. In this case, VEC_INIT_EXPR_INIT
- will either be NULL_TREE for the default constructor, or a COMPONENT_REF
- for the copy/move constructor. */
- static tree
- cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
- bool value_init, bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- tree elttype = TREE_TYPE (atype);
- unsigned HOST_WIDE_INT max = tree_to_uhwi (array_type_nelts_top (atype));
- verify_ctor_sanity (ctx, atype);
- vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
- vec_alloc (*p, max + 1);
- bool pre_init = false;
- unsigned HOST_WIDE_INT i;
- /* For the default constructor, build up a call to the default
- constructor of the element type. We only need to handle class types
- here, as for a constructor to be constexpr, all members must be
- initialized, which for a defaulted default constructor means they must
- be of a class type with a constexpr default constructor. */
- if (TREE_CODE (elttype) == ARRAY_TYPE)
- /* We only do this at the lowest level. */;
- else if (value_init)
- {
- init = build_value_init (elttype, tf_warning_or_error);
- pre_init = true;
- }
- else if (!init)
- {
- vec<tree, va_gc> *argvec = make_tree_vector ();
- init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
- &argvec, elttype, LOOKUP_NORMAL,
- tf_warning_or_error);
- release_tree_vector (argvec);
- init = build_aggr_init_expr (TREE_TYPE (init), init);
- pre_init = true;
- }
- for (i = 0; i < max; ++i)
- {
- tree idx = build_int_cst (size_type_node, i);
- tree eltinit;
- constexpr_ctx new_ctx;
- init_subob_ctx (ctx, new_ctx, idx, pre_init ? init : elttype);
- if (new_ctx.ctor != ctx->ctor)
- CONSTRUCTOR_APPEND_ELT (*p, idx, new_ctx.ctor);
- if (TREE_CODE (elttype) == ARRAY_TYPE)
- {
- /* A multidimensional array; recurse. */
- if (value_init || init == NULL_TREE)
- eltinit = NULL_TREE;
- else
- eltinit = cp_build_array_ref (input_location, init, idx,
- tf_warning_or_error);
- eltinit = cxx_eval_vec_init_1 (&new_ctx, elttype, eltinit, value_init,
- lval,
- non_constant_p, overflow_p);
- }
- else if (pre_init)
- {
- /* Initializing an element using value or default initialization
- we just pre-built above. */
- eltinit = (cxx_eval_constant_expression
- (&new_ctx, init,
- lval, non_constant_p, overflow_p));
- }
- else
- {
- /* Copying an element. */
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (atype, TREE_TYPE (init)));
- eltinit = cp_build_array_ref (input_location, init, idx,
- tf_warning_or_error);
- if (!real_lvalue_p (init))
- eltinit = move (eltinit);
- eltinit = force_rvalue (eltinit, tf_warning_or_error);
- eltinit = (cxx_eval_constant_expression
- (&new_ctx, eltinit, lval,
- non_constant_p, overflow_p));
- }
- if (*non_constant_p && !ctx->quiet)
- break;
- if (new_ctx.ctor != ctx->ctor)
- {
- /* We appended this element above; update the value. */
- gcc_assert ((*p)->last().index == idx);
- (*p)->last().value = eltinit;
- }
- else
- CONSTRUCTOR_APPEND_ELT (*p, idx, eltinit);
- }
- if (!*non_constant_p)
- {
- init = ctx->ctor;
- CONSTRUCTOR_NO_IMPLICIT_ZERO (init) = false;
- }
- return init;
- }
- static tree
- cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- tree atype = TREE_TYPE (t);
- tree init = VEC_INIT_EXPR_INIT (t);
- tree r = cxx_eval_vec_init_1 (ctx, atype, init,
- VEC_INIT_EXPR_VALUE_INIT (t),
- lval, non_constant_p, overflow_p);
- if (*non_constant_p)
- return t;
- else
- return r;
- }
- /* A less strict version of fold_indirect_ref_1, which requires cv-quals to
- match. We want to be less strict for simple *& folding; if we have a
- non-const temporary that we access through a const pointer, that should
- work. We handle this here rather than change fold_indirect_ref_1
- because we're dealing with things like ADDR_EXPR of INTEGER_CST which
- don't really make sense outside of constant expression evaluation. Also
- we want to allow folding to COMPONENT_REF, which could cause trouble
- with TBAA in fold_indirect_ref_1.
- Try to keep this function synced with fold_indirect_ref_1. */
- static tree
- cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
- {
- tree sub, subtype;
- sub = op0;
- STRIP_NOPS (sub);
- subtype = TREE_TYPE (sub);
- if (!POINTER_TYPE_P (subtype))
- return NULL_TREE;
- if (TREE_CODE (sub) == ADDR_EXPR)
- {
- tree op = TREE_OPERAND (sub, 0);
- tree optype = TREE_TYPE (op);
- /* *&CONST_DECL -> to the value of the const decl. */
- if (TREE_CODE (op) == CONST_DECL)
- return DECL_INITIAL (op);
- /* *&p => p; make sure to handle *&"str"[cst] here. */
- if (same_type_ignoring_top_level_qualifiers_p (optype, type))
- {
- tree fop = fold_read_from_constant_string (op);
- if (fop)
- return fop;
- else
- return op;
- }
- /* *(foo *)&fooarray => fooarray[0] */
- else if (TREE_CODE (optype) == ARRAY_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (optype))))
- {
- tree type_domain = TYPE_DOMAIN (optype);
- tree min_val = size_zero_node;
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- return build4_loc (loc, ARRAY_REF, type, op, min_val,
- NULL_TREE, NULL_TREE);
- }
- /* *(foo *)&complexfoo => __real__ complexfoo */
- else if (TREE_CODE (optype) == COMPLEX_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (optype))))
- return fold_build1_loc (loc, REALPART_EXPR, type, op);
- /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
- else if (TREE_CODE (optype) == VECTOR_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (optype))))
- {
- tree part_width = TYPE_SIZE (type);
- tree index = bitsize_int (0);
- return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index);
- }
- /* Also handle conversion to an empty base class, which
- is represented with a NOP_EXPR. */
- else if (is_empty_class (type)
- && CLASS_TYPE_P (optype)
- && DERIVED_FROM_P (type, optype))
- {
- *empty_base = true;
- return op;
- }
- /* *(foo *)&struct_with_foo_field => COMPONENT_REF */
- else if (RECORD_OR_UNION_TYPE_P (optype))
- {
- tree field = TYPE_FIELDS (optype);
- for (; field; field = DECL_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL
- && integer_zerop (byte_position (field))
- && (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (field), type)))
- {
- return fold_build3 (COMPONENT_REF, type, op, field, NULL_TREE);
- break;
- }
- }
- }
- else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
- {
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- STRIP_NOPS (op00);
- if (TREE_CODE (op00) == ADDR_EXPR)
- {
- tree op00type;
- op00 = TREE_OPERAND (op00, 0);
- op00type = TREE_TYPE (op00);
- /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
- if (TREE_CODE (op00type) == VECTOR_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (op00type))))
- {
- HOST_WIDE_INT offset = tree_to_shwi (op01);
- tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi = tree_to_shwi (part_width)/BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
- if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type))
- return fold_build3_loc (loc,
- BIT_FIELD_REF, type, op00,
- part_width, index);
- }
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
- else if (TREE_CODE (op00type) == COMPLEX_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (op00type))))
- {
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, op01))
- return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
- }
- /* ((foo *)&fooarray)[1] => fooarray[1] */
- else if (TREE_CODE (op00type) == ARRAY_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (op00type))))
- {
- tree type_domain = TYPE_DOMAIN (op00type);
- tree min_val = size_zero_node;
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01,
- TYPE_SIZE_UNIT (type));
- op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val);
- return build4_loc (loc, ARRAY_REF, type, op00, op01,
- NULL_TREE, NULL_TREE);
- }
- /* Also handle conversion to an empty base class, which
- is represented with a NOP_EXPR. */
- else if (is_empty_class (type)
- && CLASS_TYPE_P (op00type)
- && DERIVED_FROM_P (type, op00type))
- {
- *empty_base = true;
- return op00;
- }
- /* ((foo *)&struct_with_foo_field)[1] => COMPONENT_REF */
- else if (RECORD_OR_UNION_TYPE_P (op00type))
- {
- tree field = TYPE_FIELDS (op00type);
- for (; field; field = DECL_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL
- && tree_int_cst_equal (byte_position (field), op01)
- && (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (field), type)))
- {
- return fold_build3 (COMPONENT_REF, type, op00,
- field, NULL_TREE);
- break;
- }
- }
- }
- }
- /* *(foo *)fooarrptr => (*fooarrptr)[0] */
- else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (TREE_TYPE (subtype)))))
- {
- tree type_domain;
- tree min_val = size_zero_node;
- tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
- if (newsub)
- sub = newsub;
- else
- sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub);
- type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- return build4_loc (loc, ARRAY_REF, type, sub, min_val, NULL_TREE,
- NULL_TREE);
- }
- return NULL_TREE;
- }
- static tree
- cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- tree orig_op0 = TREE_OPERAND (t, 0);
- tree op0 = cxx_eval_constant_expression (ctx, orig_op0,
- /*lval*/false, non_constant_p,
- overflow_p);
- bool empty_base = false;
- tree r;
- /* Don't VERIFY_CONSTANT here. */
- if (*non_constant_p)
- return t;
- r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0,
- &empty_base);
- if (r)
- r = cxx_eval_constant_expression (ctx, r,
- lval, non_constant_p, overflow_p);
- else
- {
- tree sub = op0;
- STRIP_NOPS (sub);
- if (TREE_CODE (sub) == ADDR_EXPR)
- {
- /* We couldn't fold to a constant value. Make sure it's not
- something we should have been able to fold. */
- gcc_assert (!same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
- /* DR 1188 says we don't have to deal with this. */
- if (!ctx->quiet)
- error ("accessing value of %qE through a %qT glvalue in a "
- "constant expression", build_fold_indirect_ref (sub),
- TREE_TYPE (t));
- *non_constant_p = true;
- return t;
- }
- }
- /* If we're pulling out the value of an empty base, make sure
- that the whole object is constant and then return an empty
- CONSTRUCTOR. */
- if (empty_base && !lval)
- {
- VERIFY_CONSTANT (r);
- r = build_constructor (TREE_TYPE (t), NULL);
- TREE_CONSTANT (r) = true;
- }
- if (r == NULL_TREE)
- {
- if (lval && op0 != orig_op0)
- return build1 (INDIRECT_REF, TREE_TYPE (t), op0);
- if (!lval)
- VERIFY_CONSTANT (t);
- return t;
- }
- return r;
- }
- /* Complain about R, a VAR_DECL, not being usable in a constant expression.
- Shared between potential_constant_expression and
- cxx_eval_constant_expression. */
- static void
- non_const_var_error (tree r)
- {
- tree type = TREE_TYPE (r);
- error ("the value of %qD is not usable in a constant "
- "expression", r);
- /* Avoid error cascade. */
- if (DECL_INITIAL (r) == error_mark_node)
- return;
- if (DECL_DECLARED_CONSTEXPR_P (r))
- inform (DECL_SOURCE_LOCATION (r),
- "%qD used in its own initializer", r);
- else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
- {
- if (!CP_TYPE_CONST_P (type))
- inform (DECL_SOURCE_LOCATION (r),
- "%q#D is not const", r);
- else if (CP_TYPE_VOLATILE_P (type))
- inform (DECL_SOURCE_LOCATION (r),
- "%q#D is volatile", r);
- else if (!DECL_INITIAL (r)
- || !TREE_CONSTANT (DECL_INITIAL (r)))
- inform (DECL_SOURCE_LOCATION (r),
- "%qD was not initialized with a constant "
- "expression", r);
- else
- gcc_unreachable ();
- }
- else
- {
- if (cxx_dialect >= cxx11 && !DECL_DECLARED_CONSTEXPR_P (r))
- inform (DECL_SOURCE_LOCATION (r),
- "%qD was not declared %<constexpr%>", r);
- else
- inform (DECL_SOURCE_LOCATION (r),
- "%qD does not have integral or enumeration type",
- r);
- }
- }
- /* Subroutine of cxx_eval_constant_expression.
- Like cxx_eval_unary_expression, except for trinary expressions. */
- static tree
- cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- int i;
- tree args[3];
- tree val;
- for (i = 0; i < 3; i++)
- {
- args[i] = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, i),
- lval,
- non_constant_p, overflow_p);
- VERIFY_CONSTANT (args[i]);
- }
- val = fold_ternary_loc (EXPR_LOCATION (t), TREE_CODE (t), TREE_TYPE (t),
- args[0], args[1], args[2]);
- if (val == NULL_TREE)
- return t;
- VERIFY_CONSTANT (val);
- return val;
- }
- bool
- var_in_constexpr_fn (tree t)
- {
- tree ctx = DECL_CONTEXT (t);
- return (cxx_dialect >= cxx14 && ctx && TREE_CODE (ctx) == FUNCTION_DECL
- && DECL_DECLARED_CONSTEXPR_P (ctx));
- }
- /* Evaluate an INIT_EXPR or MODIFY_EXPR. */
- static tree
- cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- constexpr_ctx new_ctx = *ctx;
- tree init = TREE_OPERAND (t, 1);
- /* First we figure out where we're storing to. */
- tree target = TREE_OPERAND (t, 0);
- tree type = TREE_TYPE (target);
- target = cxx_eval_constant_expression (ctx, target,
- true,
- non_constant_p, overflow_p);
- if (*non_constant_p)
- return t;
- if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type)
- && is_empty_class (type))
- {
- /* For initialization of an empty base, the original target will be
- *(base*)this, which the above evaluation resolves to the object
- argument, which has the derived type rather than the base type. In
- this situation, just evaluate the initializer and return, since
- there's no actual data to store. */
- return cxx_eval_constant_expression (ctx, init, false,
- non_constant_p, overflow_p);
- }
- /* And then find the underlying variable. */
- vec<tree,va_gc> *refs = make_tree_vector();
- tree object = NULL_TREE;
- for (tree probe = target; object == NULL_TREE; )
- {
- switch (TREE_CODE (probe))
- {
- case BIT_FIELD_REF:
- case COMPONENT_REF:
- case ARRAY_REF:
- vec_safe_push (refs, TREE_OPERAND (probe, 1));
- vec_safe_push (refs, TREE_TYPE (probe));
- probe = TREE_OPERAND (probe, 0);
- break;
- default:
- object = probe;
- }
- }
- /* And then find/build up our initializer for the path to the subobject
- we're initializing. */
- tree *valp;
- if (DECL_P (object))
- valp = ctx->values->get (object);
- else
- valp = NULL;
- if (!valp)
- {
- /* A constant-expression cannot modify objects from outside the
- constant-expression. */
- if (!ctx->quiet)
- error ("modification of %qE is not a constant-expression", object);
- *non_constant_p = true;
- return t;
- }
- type = TREE_TYPE (object);
- while (!refs->is_empty())
- {
- if (*valp == NULL_TREE)
- {
- *valp = build_constructor (type, NULL);
- CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = true;
- }
- constructor_elt ce;
- type = refs->pop();
- ce.index = refs->pop();
- ce.value = NULL_TREE;
- unsigned HOST_WIDE_INT idx = 0;
- constructor_elt *cep = NULL;
- for (idx = 0;
- vec_safe_iterate (CONSTRUCTOR_ELTS (*valp), idx, &cep);
- idx++)
- /* ??? slow */
- if (cp_tree_equal (ce.index, cep->index))
- break;
- if (!cep)
- cep = vec_safe_push (CONSTRUCTOR_ELTS (*valp), ce);
- valp = &cep->value;
- }
- release_tree_vector (refs);
- if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
- {
- /* Create a new CONSTRUCTOR in case evaluation of the initializer
- wants to modify it. */
- new_ctx.ctor = build_constructor (type, NULL);
- if (*valp == NULL_TREE)
- *valp = new_ctx.ctor;
- CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true;
- new_ctx.object = target;
- }
- init = cxx_eval_constant_expression (&new_ctx, init, false,
- non_constant_p, overflow_p);
- if (target == object)
- {
- /* The hash table might have moved since the get earlier. */
- valp = ctx->values->get (object);
- if (TREE_CODE (init) == CONSTRUCTOR)
- /* An outer ctx->ctor might be pointing to *valp, so just replace
- its contents. */
- CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
- else
- *valp = init;
- }
- else
- *valp = init;
- if (*non_constant_p)
- return t;
- else if (lval)
- return target;
- else
- return init;
- }
- /* Evaluate a ++ or -- expression. */
- static tree
- cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
- {
- enum tree_code code = TREE_CODE (t);
- tree type = TREE_TYPE (t);
- tree op = TREE_OPERAND (t, 0);
- tree offset = TREE_OPERAND (t, 1);
- gcc_assert (TREE_CONSTANT (offset));
- /* The operand as an lvalue. */
- op = cxx_eval_constant_expression (ctx, op, true,
- non_constant_p, overflow_p);
- /* The operand as an rvalue. */
- tree val = rvalue (op);
- val = cxx_eval_constant_expression (ctx, val, false,
- non_constant_p, overflow_p);
- /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
- a local array in a constexpr function. */
- bool ptr = POINTER_TYPE_P (TREE_TYPE (val));
- if (!ptr)
- VERIFY_CONSTANT (val);
- /* The modified value. */
- bool inc = (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR);
- tree mod;
- if (POINTER_TYPE_P (type))
- {
- /* The middle end requires pointers to use POINTER_PLUS_EXPR. */
- offset = convert_to_ptrofftype (offset);
- if (!inc)
- offset = fold_build1 (NEGATE_EXPR, TREE_TYPE (offset), offset);
- mod = fold_build2 (POINTER_PLUS_EXPR, type, val, offset);
- }
- else
- mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, type, val, offset);
- if (!ptr)
- VERIFY_CONSTANT (mod);
- /* Storing the modified value. */
- tree store = build2 (MODIFY_EXPR, type, op, mod);
- cxx_eval_constant_expression (ctx, store,
- true, non_constant_p, overflow_p);
- /* And the value of the expression. */
- if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
- {
- /* Prefix ops are lvalues. */
- if (lval)
- return op;
- else
- /* But we optimize when the caller wants an rvalue. */
- return mod;
- }
- else
- /* Postfix ops are rvalues. */
- return val;
- }
- /* Predicates for the meaning of *jump_target. */
- static bool
- returns (tree *jump_target)
- {
- return *jump_target
- && TREE_CODE (*jump_target) == RETURN_EXPR;
- }
- static bool
- breaks (tree *jump_target)
- {
- return *jump_target
- && TREE_CODE (*jump_target) == LABEL_DECL
- && LABEL_DECL_BREAK (*jump_target);
- }
- static bool
- continues (tree *jump_target)
- {
- return *jump_target
- && TREE_CODE (*jump_target) == LABEL_DECL
- && LABEL_DECL_CONTINUE (*jump_target);
- }
- static bool
- switches (tree *jump_target)
- {
- return *jump_target
- && TREE_CODE (*jump_target) == INTEGER_CST;
- }
- /* Subroutine of cxx_eval_statement_list. Determine whether the statement
- at I matches *jump_target. If we're looking for a case label and we see
- the default label, copy I into DEFAULT_LABEL. */
- static bool
- label_matches (tree *jump_target, tree_stmt_iterator i,
- tree_stmt_iterator& default_label)
- {
- tree stmt = tsi_stmt (i);
- switch (TREE_CODE (*jump_target))
- {
- case LABEL_DECL:
- if (TREE_CODE (stmt) == LABEL_EXPR
- && LABEL_EXPR_LABEL (stmt) == *jump_target)
- return true;
- break;
- case INTEGER_CST:
- if (TREE_CODE (stmt) == CASE_LABEL_EXPR)
- {
- if (!CASE_LOW (stmt))
- default_label = i;
- else if (tree_int_cst_equal (*jump_target, CASE_LOW (stmt)))
- return true;
- }
- break;
- default:
- gcc_unreachable ();
- }
- return false;
- }
- /* Evaluate a STATEMENT_LIST for side-effects. Handles various jump
- semantics, for switch, break, continue, and return. */
- static tree
- cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target)
- {
- tree_stmt_iterator i;
- tree_stmt_iterator default_label = tree_stmt_iterator();
- tree local_target;
- /* In a statement-expression we want to return the last value. */
- tree r = NULL_TREE;
- if (!jump_target)
- {
- local_target = NULL_TREE;
- jump_target = &local_target;
- }
- for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- {
- reenter:
- tree stmt = tsi_stmt (i);
- if (*jump_target)
- {
- if (TREE_CODE (stmt) == STATEMENT_LIST)
- /* The label we want might be inside. */;
- else if (label_matches (jump_target, i, default_label))
- /* Found it. */
- *jump_target = NULL_TREE;
- else
- continue;
- }
- r = cxx_eval_constant_expression (ctx, stmt, false,
- non_constant_p, overflow_p,
- jump_target);
- if (*non_constant_p)
- break;
- if (returns (jump_target) || breaks (jump_target))
- break;
- }
- if (switches (jump_target) && !tsi_end_p (default_label))
- {
- i = default_label;
- *jump_target = NULL_TREE;
- goto reenter;
- }
- return r;
- }
- /* Evaluate a LOOP_EXPR for side-effects. Handles break and return
- semantics; continue semantics are covered by cxx_eval_statement_list. */
- static tree
- cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target)
- {
- tree body = TREE_OPERAND (t, 0);
- while (true)
- {
- cxx_eval_statement_list (ctx, body,
- non_constant_p, overflow_p, jump_target);
- if (returns (jump_target) || breaks (jump_target) || *non_constant_p)
- break;
- }
- if (breaks (jump_target))
- *jump_target = NULL_TREE;
- return NULL_TREE;
- }
- /* Evaluate a SWITCH_EXPR for side-effects. Handles switch and break jump
- semantics. */
- static tree
- cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target)
- {
- tree cond = TREE_OPERAND (t, 0);
- cond = cxx_eval_constant_expression (ctx, cond, false,
- non_constant_p, overflow_p);
- VERIFY_CONSTANT (cond);
- *jump_target = cond;
- tree body = TREE_OPERAND (t, 1);
- cxx_eval_statement_list (ctx, body,
- non_constant_p, overflow_p, jump_target);
- if (breaks (jump_target) || switches (jump_target))
- *jump_target = NULL_TREE;
- return NULL_TREE;
- }
- /* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce a POINTER_PLUS_EXPR expression T. */
- static tree
- cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
- bool lval, bool *non_constant_p,
- bool *overflow_p)
- {
- tree orig_type = TREE_TYPE (t);
- tree op00 = TREE_OPERAND (t, 0);
- tree op01 = TREE_OPERAND (t, 1);
- location_t loc = EXPR_LOCATION (t);
- op00 = cxx_eval_constant_expression (ctx, op00, lval,
- non_constant_p, overflow_p);
- STRIP_NOPS (op00);
- if (TREE_CODE (op00) != ADDR_EXPR)
- return NULL_TREE;
- op00 = TREE_OPERAND (op00, 0);
- /* &A[i] p+ j => &A[i + j] */
- if (TREE_CODE (op00) == ARRAY_REF
- && TREE_CODE (TREE_OPERAND (op00, 1)) == INTEGER_CST
- && TREE_CODE (op01) == INTEGER_CST
- && TYPE_SIZE_UNIT (TREE_TYPE (op00))
- && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (op00))) == INTEGER_CST)
- {
- tree type = TREE_TYPE (op00);
- t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (op00, 1));
- tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (op00, 0)));
- /* Don't fold an out-of-bound access. */
- if (!tree_int_cst_le (t, nelts))
- return NULL_TREE;
- op01 = cp_fold_convert (ssizetype, op01);
- /* Don't fold if op01 can't be divided exactly by TYPE_SIZE_UNIT.
- constexpr int A[1]; ... (char *)&A[0] + 1 */
- if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype,
- op01, TYPE_SIZE_UNIT (type))))
- return NULL_TREE;
- /* Make sure to treat the second operand of POINTER_PLUS_EXPR
- as signed. */
- op01 = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, op01,
- TYPE_SIZE_UNIT (type));
- t = size_binop_loc (loc, PLUS_EXPR, op01, t);
- t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (op00, 0),
- t, NULL_TREE, NULL_TREE);
- t = cp_build_addr_expr (t, tf_warning_or_error);
- t = cp_fold_convert (orig_type, t);
- return cxx_eval_constant_expression (ctx, t, lval, non_constant_p,
- overflow_p);
- }
- return NULL_TREE;
- }
- /* Attempt to reduce the expression T to a constant value.
- On failure, issue diagnostic and return error_mark_node. */
- /* FIXME unify with c_fully_fold */
- /* FIXME overflow_p is too global */
- static tree
- cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target)
- {
- constexpr_ctx new_ctx;
- tree r = t;
- if (t == error_mark_node)
- {
- *non_constant_p = true;
- return t;
- }
- if (CONSTANT_CLASS_P (t))
- {
- if (TREE_CODE (t) == PTRMEM_CST)
- t = cplus_expand_constant (t);
- else if (TREE_OVERFLOW (t) && (!flag_permissive || ctx->quiet))
- *overflow_p = true;
- return t;
- }
- switch (TREE_CODE (t))
- {
- case RESULT_DECL:
- if (lval)
- return t;
- /* We ask for an rvalue for the RESULT_DECL when indirecting
- through an invisible reference, or in named return value
- optimization. */
- return (*ctx->values->get (t));
- case VAR_DECL:
- case CONST_DECL:
- /* We used to not check lval for CONST_DECL, but darwin.c uses
- CONST_DECL for aggregate constants. */
- if (lval)
- return t;
- if (ctx->strict)
- r = decl_really_constant_value (t);
- else
- r = decl_constant_value (t);
- if (TREE_CODE (r) == TARGET_EXPR
- && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
- r = TARGET_EXPR_INITIAL (r);
- if (TREE_CODE (r) == VAR_DECL)
- if (tree *p = ctx->values->get (r))
- r = *p;
- if (DECL_P (r))
- {
- if (!ctx->quiet)
- non_const_var_error (r);
- *non_constant_p = true;
- }
- break;
- case FUNCTION_DECL:
- case TEMPLATE_DECL:
- case LABEL_DECL:
- case LABEL_EXPR:
- case CASE_LABEL_EXPR:
- return t;
- case PARM_DECL:
- if (!use_new_call && ctx
- && ctx->call && DECL_CONTEXT (t) == ctx->call->fundef->decl)
- r = lookup_parameter_binding (ctx->call, t);
- else if (lval && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
- /* glvalue use. */;
- else if (tree *p = ctx->values->get (r))
- r = *p;
- else if (lval)
- /* Defer in case this is only used for its type. */;
- else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
- /* Defer, there's no lvalue->rvalue conversion. */;
- else if (is_empty_class (TREE_TYPE (t)))
- {
- /* If the class is empty, we aren't actually loading anything. */
- r = build_constructor (TREE_TYPE (t), NULL);
- TREE_CONSTANT (r) = true;
- }
- else
- {
- if (!ctx->quiet)
- error ("%qE is not a constant expression", t);
- *non_constant_p = true;
- }
- break;
- case CALL_EXPR:
- case AGGR_INIT_EXPR:
- r = cxx_eval_call_expression (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case DECL_EXPR:
- {
- r = DECL_EXPR_DECL (t);
- if (AGGREGATE_TYPE_P (TREE_TYPE (r))
- || VECTOR_TYPE_P (TREE_TYPE (r)))
- {
- new_ctx = *ctx;
- new_ctx.object = r;
- new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
- CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true;
- new_ctx.values->put (r, new_ctx.ctor);
- ctx = &new_ctx;
- }
- if (tree init = DECL_INITIAL (r))
- {
- init = cxx_eval_constant_expression (ctx, init,
- false,
- non_constant_p, overflow_p);
- ctx->values->put (r, init);
- }
- else if (ctx == &new_ctx)
- /* We gave it a CONSTRUCTOR above. */;
- else
- ctx->values->put (r, NULL_TREE);
- }
- break;
- case TARGET_EXPR:
- if (!literal_type_p (TREE_TYPE (t)))
- {
- if (!ctx->quiet)
- {
- error ("temporary of non-literal type %qT in a "
- "constant expression", TREE_TYPE (t));
- explain_non_literal_class (TREE_TYPE (t));
- }
- *non_constant_p = true;
- break;
- }
- if ((AGGREGATE_TYPE_P (TREE_TYPE (t)) || VECTOR_TYPE_P (TREE_TYPE (t))))
- {
- /* We're being expanded without an explicit target, so start
- initializing a new object; expansion with an explicit target
- strips the TARGET_EXPR before we get here. */
- new_ctx = *ctx;
- new_ctx.ctor = build_constructor (TREE_TYPE (t), NULL);
- CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true;
- new_ctx.object = TARGET_EXPR_SLOT (t);
- ctx->values->put (new_ctx.object, new_ctx.ctor);
- ctx = &new_ctx;
- }
- /* Pass false for 'lval' because this indicates
- initialization of a temporary. */
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- false,
- non_constant_p, overflow_p);
- if (!*non_constant_p)
- /* Adjust the type of the result to the type of the temporary. */
- r = adjust_temp_type (TREE_TYPE (t), r);
- if (lval)
- {
- tree slot = TARGET_EXPR_SLOT (t);
- ctx->values->put (slot, r);
- return slot;
- }
- break;
- case INIT_EXPR:
- if (!use_new_call)
- {
- /* In C++11 constexpr evaluation we are looking for the value,
- not the side-effect of the initialization. */
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- false,
- non_constant_p, overflow_p);
- break;
- }
- /* else fall through */
- case MODIFY_EXPR:
- r = cxx_eval_store_expression (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case SCOPE_REF:
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
- lval,
- non_constant_p, overflow_p);
- break;
- case RETURN_EXPR:
- if (TREE_OPERAND (t, 0) != NULL_TREE)
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
- lval,
- non_constant_p, overflow_p);
- *jump_target = t;
- break;
- case SAVE_EXPR:
- /* Avoid evaluating a SAVE_EXPR more than once. */
- if (tree *p = ctx->values->get (t))
- r = *p;
- else
- {
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
- non_constant_p, overflow_p);
- ctx->values->put (t, r);
- }
- break;
- case NON_LVALUE_EXPR:
- case TRY_CATCH_EXPR:
- case TRY_BLOCK:
- case CLEANUP_POINT_EXPR:
- case MUST_NOT_THROW_EXPR:
- case EXPR_STMT:
- case EH_SPEC_BLOCK:
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
- lval,
- non_constant_p, overflow_p,
- jump_target);
- break;
- case TRY_FINALLY_EXPR:
- r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
- non_constant_p, overflow_p,
- jump_target);
- if (!*non_constant_p)
- /* Also evaluate the cleanup. */
- cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
- non_constant_p, overflow_p,
- jump_target);
- break;
- /* These differ from cxx_eval_unary_expression in that this doesn't
- check for a constant operand or result; an address can be
- constant without its operand being, and vice versa. */
- case INDIRECT_REF:
- r = cxx_eval_indirect_ref (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case ADDR_EXPR:
- {
- tree oldop = TREE_OPERAND (t, 0);
- tree op = cxx_eval_constant_expression (ctx, oldop,
- /*lval*/true,
- non_constant_p, overflow_p);
- /* Don't VERIFY_CONSTANT here. */
- if (*non_constant_p)
- return t;
- gcc_checking_assert (TREE_CODE (op) != CONSTRUCTOR);
- /* This function does more aggressive folding than fold itself. */
- r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
- if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop)
- return t;
- break;
- }
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- case CONJ_EXPR:
- case FIX_TRUNC_EXPR:
- case FLOAT_EXPR:
- case NEGATE_EXPR:
- case ABS_EXPR:
- case BIT_NOT_EXPR:
- case TRUTH_NOT_EXPR:
- case FIXED_CONVERT_EXPR:
- r = cxx_eval_unary_expression (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case SIZEOF_EXPR:
- if (SIZEOF_EXPR_TYPE_P (t))
- r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
- SIZEOF_EXPR, false);
- else if (TYPE_P (TREE_OPERAND (t, 0)))
- r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
- false);
- else
- r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
- false);
- if (r == error_mark_node)
- r = size_one_node;
- VERIFY_CONSTANT (r);
- break;
- case COMPOUND_EXPR:
- {
- /* check_return_expr sometimes wraps a TARGET_EXPR in a
- COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR
- introduced by build_call_a. */
- tree op0 = TREE_OPERAND (t, 0);
- tree op1 = TREE_OPERAND (t, 1);
- STRIP_NOPS (op1);
- if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
- || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
- r = cxx_eval_constant_expression (ctx, op0,
- lval, non_constant_p, overflow_p,
- jump_target);
- else
- {
- /* Check that the LHS is constant and then discard it. */
- cxx_eval_constant_expression (ctx, op0,
- true, non_constant_p, overflow_p,
- jump_target);
- op1 = TREE_OPERAND (t, 1);
- r = cxx_eval_constant_expression (ctx, op1,
- lval, non_constant_p, overflow_p,
- jump_target);
- }
- }
- break;
- case POINTER_PLUS_EXPR:
- r = cxx_eval_pointer_plus_expression (ctx, t, lval, non_constant_p,
- overflow_p);
- if (r)
- break;
- /* else fall through */
- case PLUS_EXPR:
- case MINUS_EXPR:
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case RDIV_EXPR:
- case EXACT_DIV_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
- case TRUTH_XOR_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- case UNORDERED_EXPR:
- case ORDERED_EXPR:
- case UNLT_EXPR:
- case UNLE_EXPR:
- case UNGT_EXPR:
- case UNGE_EXPR:
- case UNEQ_EXPR:
- case LTGT_EXPR:
- case RANGE_EXPR:
- case COMPLEX_EXPR:
- r = cxx_eval_binary_expression (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- /* fold can introduce non-IF versions of these; still treat them as
- short-circuiting. */
- case TRUTH_AND_EXPR:
- case TRUTH_ANDIF_EXPR:
- r = cxx_eval_logical_expression (ctx, t, boolean_false_node,
- boolean_true_node,
- lval,
- non_constant_p, overflow_p);
- break;
- case TRUTH_OR_EXPR:
- case TRUTH_ORIF_EXPR:
- r = cxx_eval_logical_expression (ctx, t, boolean_true_node,
- boolean_false_node,
- lval,
- non_constant_p, overflow_p);
- break;
- case ARRAY_REF:
- r = cxx_eval_array_reference (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case COMPONENT_REF:
- if (is_overloaded_fn (t))
- {
- /* We can only get here in checking mode via
- build_non_dependent_expr, because any expression that
- calls or takes the address of the function will have
- pulled a FUNCTION_DECL out of the COMPONENT_REF. */
- gcc_checking_assert (ctx->quiet || errorcount);
- *non_constant_p = true;
- return t;
- }
- r = cxx_eval_component_reference (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case BIT_FIELD_REF:
- r = cxx_eval_bit_field_ref (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case COND_EXPR:
- case VEC_COND_EXPR:
- r = cxx_eval_conditional_expression (ctx, t, lval,
- non_constant_p, overflow_p,
- jump_target);
- break;
- case CONSTRUCTOR:
- if (TREE_CONSTANT (t))
- /* Don't re-process a constant CONSTRUCTOR, but do fold it to
- VECTOR_CST if applicable. */
- return fold (t);
- r = cxx_eval_bare_aggregate (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case VEC_INIT_EXPR:
- /* We can get this in a defaulted constructor for a class with a
- non-static data member of array type. Either the initializer will
- be NULL, meaning default-initialization, or it will be an lvalue
- or xvalue of the same type, meaning direct-initialization from the
- corresponding member. */
- r = cxx_eval_vec_init (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case FMA_EXPR:
- case VEC_PERM_EXPR:
- r = cxx_eval_trinary_expression (ctx, t, lval,
- non_constant_p, overflow_p);
- break;
- case CONVERT_EXPR:
- case VIEW_CONVERT_EXPR:
- case NOP_EXPR:
- {
- tree oldop = TREE_OPERAND (t, 0);
- tree op = cxx_eval_constant_expression (ctx, oldop,
- lval,
- non_constant_p, overflow_p);
- if (*non_constant_p)
- return t;
- if (POINTER_TYPE_P (TREE_TYPE (t))
- && TREE_CODE (op) == INTEGER_CST
- && !integer_zerop (op))
- {
- if (!ctx->quiet)
- error_at (EXPR_LOC_OR_LOC (t, input_location),
- "reinterpret_cast from integer to pointer");
- *non_constant_p = true;
- return t;
- }
- if (op == oldop)
- /* We didn't fold at the top so we could check for ptr-int
- conversion. */
- return fold (t);
- r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), op);
- /* Conversion of an out-of-range value has implementation-defined
- behavior; the language considers it different from arithmetic
- overflow, which is undefined. */
- if (TREE_OVERFLOW_P (r) && !TREE_OVERFLOW_P (op))
- TREE_OVERFLOW (r) = false;
- }
- break;
- case EMPTY_CLASS_EXPR:
- /* This is good enough for a function argument that might not get
- used, and they can't do anything with it, so just return it. */
- return t;
- case STATEMENT_LIST:
- new_ctx = *ctx;
- new_ctx.ctor = new_ctx.object = NULL_TREE;
- return cxx_eval_statement_list (&new_ctx, t,
- non_constant_p, overflow_p, jump_target);
- case BIND_EXPR:
- return cxx_eval_constant_expression (ctx, BIND_EXPR_BODY (t),
- lval,
- non_constant_p, overflow_p,
- jump_target);
- case PREINCREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- return cxx_eval_increment_expression (ctx, t,
- lval, non_constant_p, overflow_p);
- case LAMBDA_EXPR:
- case NEW_EXPR:
- case VEC_NEW_EXPR:
- case DELETE_EXPR:
- case VEC_DELETE_EXPR:
- case THROW_EXPR:
- case MODOP_EXPR:
- /* GCC internal stuff. */
- case VA_ARG_EXPR:
- case OBJ_TYPE_REF:
- case WITH_CLEANUP_EXPR:
- case NON_DEPENDENT_EXPR:
- case BASELINK:
- case OFFSET_REF:
- if (!ctx->quiet)
- error_at (EXPR_LOC_OR_LOC (t, input_location),
- "expression %qE is not a constant-expression", t);
- *non_constant_p = true;
- break;
- case PLACEHOLDER_EXPR:
- if (!ctx || !ctx->ctor || (lval && !ctx->object)
- || !(same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (t), TREE_TYPE (ctx->ctor))))
- {
- /* A placeholder without a referent. We can get here when
- checking whether NSDMIs are noexcept, or in massage_init_elt;
- just say it's non-constant for now. */
- gcc_assert (ctx->quiet);
- *non_constant_p = true;
- break;
- }
- else
- {
- /* Use of the value or address of the current object. We could
- use ctx->object unconditionally, but using ctx->ctor when we
- can is a minor optimization. */
- tree ctor = lval ? ctx->object : ctx->ctor;
- return cxx_eval_constant_expression
- (ctx, ctor, lval,
- non_constant_p, overflow_p);
- }
- break;
- case GOTO_EXPR:
- *jump_target = TREE_OPERAND (t, 0);
- gcc_assert (breaks (jump_target) || continues (jump_target));
- break;
- case LOOP_EXPR:
- cxx_eval_loop_expr (ctx, t,
- non_constant_p, overflow_p, jump_target);
- break;
- case SWITCH_EXPR:
- cxx_eval_switch_expr (ctx, t,
- non_constant_p, overflow_p, jump_target);
- break;
- default:
- if (STATEMENT_CODE_P (TREE_CODE (t)))
- {
- /* This function doesn't know how to deal with pre-genericize
- statements; this can only happen with statement-expressions,
- so for now just fail. */
- if (!ctx->quiet)
- error_at (EXPR_LOCATION (t),
- "statement is not a constant-expression");
- }
- else
- internal_error ("unexpected expression %qE of kind %s", t,
- get_tree_code_name (TREE_CODE (t)));
- *non_constant_p = true;
- break;
- }
- if (r == error_mark_node)
- *non_constant_p = true;
- if (*non_constant_p)
- return t;
- else
- return r;
- }
- static tree
- cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
- bool strict = true, tree object = NULL_TREE)
- {
- bool non_constant_p = false;
- bool overflow_p = false;
- hash_map<tree,tree> map;
- constexpr_ctx ctx = { NULL, &map, NULL, NULL, allow_non_constant, strict };
- tree type = initialized_type (t);
- tree r = t;
- if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
- {
- /* In C++14 an NSDMI can participate in aggregate initialization,
- and can refer to the address of the object being initialized, so
- we need to pass in the relevant VAR_DECL if we want to do the
- evaluation in a single pass. The evaluation will dynamically
- update ctx.values for the VAR_DECL. We use the same strategy
- for C++11 constexpr constructors that refer to the object being
- initialized. */
- ctx.ctor = build_constructor (type, NULL);
- CONSTRUCTOR_NO_IMPLICIT_ZERO (ctx.ctor) = true;
- if (!object)
- {
- if (TREE_CODE (t) == TARGET_EXPR)
- object = TARGET_EXPR_SLOT (t);
- else if (TREE_CODE (t) == AGGR_INIT_EXPR)
- object = AGGR_INIT_EXPR_SLOT (t);
- }
- ctx.object = object;
- if (object)
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (object)));
- if (object && DECL_P (object))
- map.put (object, ctx.ctor);
- if (TREE_CODE (r) == TARGET_EXPR)
- /* Avoid creating another CONSTRUCTOR when we expand the
- TARGET_EXPR. */
- r = TARGET_EXPR_INITIAL (r);
- }
- r = cxx_eval_constant_expression (&ctx, r,
- false, &non_constant_p, &overflow_p);
- verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
- /* Mutable logic is a bit tricky: we want to allow initialization of
- constexpr variables with mutable members, but we can't copy those
- members to another constexpr variable. */
- if (TREE_CODE (r) == CONSTRUCTOR
- && CONSTRUCTOR_MUTABLE_POISON (r))
- {
- if (!allow_non_constant)
- error ("%qE is not a constant expression because it refers to "
- "mutable subobjects of %qT", t, type);
- non_constant_p = true;
- }
- /* Technically we should check this for all subexpressions, but that
- runs into problems with our internal representation of pointer
- subtraction and the 5.19 rules are still in flux. */
- if (CONVERT_EXPR_CODE_P (TREE_CODE (r))
- && ARITHMETIC_TYPE_P (TREE_TYPE (r))
- && TREE_CODE (TREE_OPERAND (r, 0)) == ADDR_EXPR)
- {
- if (!allow_non_constant)
- error ("conversion from pointer type %qT "
- "to arithmetic type %qT in a constant-expression",
- TREE_TYPE (TREE_OPERAND (r, 0)), TREE_TYPE (r));
- non_constant_p = true;
- }
- if (!non_constant_p && overflow_p)
- non_constant_p = true;
- if (non_constant_p && !allow_non_constant)
- return error_mark_node;
- else if (non_constant_p && TREE_CONSTANT (r))
- {
- /* This isn't actually constant, so unset TREE_CONSTANT. */
- if (EXPR_P (r))
- r = copy_node (r);
- else if (TREE_CODE (r) == CONSTRUCTOR)
- r = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (r), r);
- else
- r = build_nop (TREE_TYPE (r), r);
- TREE_CONSTANT (r) = false;
- }
- else if (non_constant_p || r == t)
- return t;
- if (TREE_CODE (r) == CONSTRUCTOR && CLASS_TYPE_P (TREE_TYPE (r)))
- {
- if (TREE_CODE (t) == TARGET_EXPR
- && TARGET_EXPR_INITIAL (t) == r)
- return t;
- else
- {
- r = get_target_expr (r);
- TREE_CONSTANT (r) = true;
- return r;
- }
- }
- else
- return r;
- }
- /* Returns true if T is a valid subexpression of a constant expression,
- even if it isn't itself a constant expression. */
- bool
- is_sub_constant_expr (tree t)
- {
- bool non_constant_p = false;
- bool overflow_p = false;
- hash_map <tree, tree> map;
- constexpr_ctx ctx = { NULL, &map, NULL, NULL, true, true };
- cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
- &overflow_p);
- return !non_constant_p && !overflow_p;
- }
- /* If T represents a constant expression returns its reduced value.
- Otherwise return error_mark_node. If T is dependent, then
- return NULL. */
- tree
- cxx_constant_value (tree t, tree decl)
- {
- return cxx_eval_outermost_constant_expr (t, false, true, decl);
- }
- /* If T is a constant expression, returns its reduced value.
- Otherwise, if T does not have TREE_CONSTANT set, returns T.
- Otherwise, returns a version of T without TREE_CONSTANT. */
- tree
- maybe_constant_value (tree t, tree decl)
- {
- tree r;
- if (instantiation_dependent_expression_p (t)
- || type_unknown_p (t)
- || BRACE_ENCLOSED_INITIALIZER_P (t)
- || !potential_constant_expression (t))
- {
- if (TREE_OVERFLOW_P (t))
- {
- t = build_nop (TREE_TYPE (t), t);
- TREE_CONSTANT (t) = false;
- }
- return t;
- }
- r = cxx_eval_outermost_constant_expr (t, true, true, decl);
- #ifdef ENABLE_CHECKING
- gcc_assert (r == t
- || CONVERT_EXPR_P (t)
- || TREE_CODE (t) == VIEW_CONVERT_EXPR
- || (TREE_CONSTANT (t) && !TREE_CONSTANT (r))
- || !cp_tree_equal (r, t));
- #endif
- return r;
- }
- /* Like maybe_constant_value but first fully instantiate the argument.
- Note: this is equivalent to instantiate_non_dependent_expr_sfinae
- (t, tf_none) followed by maybe_constant_value but is more efficient,
- because calls instantiation_dependent_expression_p and
- potential_constant_expression at most once. */
- tree
- fold_non_dependent_expr (tree t)
- {
- if (t == NULL_TREE)
- return NULL_TREE;
- /* If we're in a template, but T isn't value dependent, simplify
- it. We're supposed to treat:
- template <typename T> void f(T[1 + 1]);
- template <typename T> void f(T[2]);
- as two declarations of the same function, for example. */
- if (processing_template_decl)
- {
- if (!instantiation_dependent_expression_p (t)
- && potential_constant_expression (t))
- {
- processing_template_decl_sentinel s;
- t = instantiate_non_dependent_expr_internal (t, tf_none);
- if (type_unknown_p (t)
- || BRACE_ENCLOSED_INITIALIZER_P (t))
- {
- if (TREE_OVERFLOW_P (t))
- {
- t = build_nop (TREE_TYPE (t), t);
- TREE_CONSTANT (t) = false;
- }
- return t;
- }
- tree r = cxx_eval_outermost_constant_expr (t, true, true, NULL_TREE);
- #ifdef ENABLE_CHECKING
- /* cp_tree_equal looks through NOPs, so allow them. */
- gcc_assert (r == t
- || CONVERT_EXPR_P (t)
- || TREE_CODE (t) == VIEW_CONVERT_EXPR
- || (TREE_CONSTANT (t) && !TREE_CONSTANT (r))
- || !cp_tree_equal (r, t));
- #endif
- return r;
- }
- else if (TREE_OVERFLOW_P (t))
- {
- t = build_nop (TREE_TYPE (t), t);
- TREE_CONSTANT (t) = false;
- }
- return t;
- }
- return maybe_constant_value (t);
- }
- /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
- than wrapped in a TARGET_EXPR. */
- tree
- maybe_constant_init (tree t, tree decl)
- {
- if (TREE_CODE (t) == EXPR_STMT)
- t = TREE_OPERAND (t, 0);
- if (TREE_CODE (t) == CONVERT_EXPR
- && VOID_TYPE_P (TREE_TYPE (t)))
- t = TREE_OPERAND (t, 0);
- if (TREE_CODE (t) == INIT_EXPR)
- t = TREE_OPERAND (t, 1);
- if (instantiation_dependent_expression_p (t)
- || type_unknown_p (t)
- || BRACE_ENCLOSED_INITIALIZER_P (t)
- || !potential_static_init_expression (t))
- /* Don't try to evaluate it. */;
- else
- t = cxx_eval_outermost_constant_expr (t, true, false, decl);
- if (TREE_CODE (t) == TARGET_EXPR)
- {
- tree init = TARGET_EXPR_INITIAL (t);
- if (TREE_CODE (init) == CONSTRUCTOR)
- t = init;
- }
- return t;
- }
- #if 0
- /* FIXME see ADDR_EXPR section in potential_constant_expression_1. */
- /* Return true if the object referred to by REF has automatic or thread
- local storage. */
- enum { ck_ok, ck_bad, ck_unknown };
- static int
- check_automatic_or_tls (tree ref)
- {
- machine_mode mode;
- HOST_WIDE_INT bitsize, bitpos;
- tree offset;
- int volatilep = 0, unsignedp = 0;
- tree decl = get_inner_reference (ref, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
- duration_kind dk;
- /* If there isn't a decl in the middle, we don't know the linkage here,
- and this isn't a constant expression anyway. */
- if (!DECL_P (decl))
- return ck_unknown;
- dk = decl_storage_duration (decl);
- return (dk == dk_auto || dk == dk_thread) ? ck_bad : ck_ok;
- }
- #endif
- /* Return true if T denotes a potentially constant expression. Issue
- diagnostic as appropriate under control of FLAGS. If WANT_RVAL is true,
- an lvalue-rvalue conversion is implied.
- C++0x [expr.const] used to say
- 6 An expression is a potential constant expression if it is
- a constant expression where all occurrences of function
- parameters are replaced by arbitrary constant expressions
- of the appropriate type.
- 2 A conditional expression is a constant expression unless it
- involves one of the following as a potentially evaluated
- subexpression (3.2), but subexpressions of logical AND (5.14),
- logical OR (5.15), and conditional (5.16) operations that are
- not evaluated are not considered. */
- static bool
- potential_constant_expression_1 (tree t, bool want_rval, bool strict,
- tsubst_flags_t flags)
- {
- #define RECUR(T,RV) potential_constant_expression_1 ((T), (RV), strict, flags)
- enum { any = false, rval = true };
- int i;
- tree tmp;
- if (t == error_mark_node)
- return false;
- if (t == NULL_TREE)
- return true;
- if (TREE_THIS_VOLATILE (t))
- {
- if (flags & tf_error)
- error ("expression %qE has side-effects", t);
- return false;
- }
- if (CONSTANT_CLASS_P (t))
- return true;
- switch (TREE_CODE (t))
- {
- case FUNCTION_DECL:
- case BASELINK:
- case TEMPLATE_DECL:
- case OVERLOAD:
- case TEMPLATE_ID_EXPR:
- case LABEL_DECL:
- case LABEL_EXPR:
- case CASE_LABEL_EXPR:
- case CONST_DECL:
- case SIZEOF_EXPR:
- case ALIGNOF_EXPR:
- case OFFSETOF_EXPR:
- case NOEXCEPT_EXPR:
- case TEMPLATE_PARM_INDEX:
- case TRAIT_EXPR:
- case IDENTIFIER_NODE:
- case USERDEF_LITERAL:
- /* We can see a FIELD_DECL in a pointer-to-member expression. */
- case FIELD_DECL:
- case PARM_DECL:
- case USING_DECL:
- case USING_STMT:
- case PLACEHOLDER_EXPR:
- case BREAK_STMT:
- case CONTINUE_STMT:
- return true;
- case AGGR_INIT_EXPR:
- case CALL_EXPR:
- /* -- an invocation of a function other than a constexpr function
- or a constexpr constructor. */
- {
- tree fun = get_function_named_in_call (t);
- const int nargs = call_expr_nargs (t);
- i = 0;
- if (fun == NULL_TREE)
- {
- if (TREE_CODE (t) == CALL_EXPR
- && CALL_EXPR_FN (t) == NULL_TREE)
- switch (CALL_EXPR_IFN (t))
- {
- /* These should be ignored, they are optimized away from
- constexpr functions. */
- case IFN_UBSAN_NULL:
- case IFN_UBSAN_BOUNDS:
- case IFN_UBSAN_VPTR:
- return true;
- default:
- break;
- }
- /* fold_call_expr can't do anything with IFN calls. */
- if (flags & tf_error)
- error_at (EXPR_LOC_OR_LOC (t, input_location),
- "call to internal function");
- return false;
- }
- if (is_overloaded_fn (fun))
- {
- if (TREE_CODE (fun) == FUNCTION_DECL)
- {
- if (builtin_valid_in_constant_expr_p (fun))
- return true;
- if (!DECL_DECLARED_CONSTEXPR_P (fun)
- /* Allow any built-in function; if the expansion
- isn't constant, we'll deal with that then. */
- && !is_builtin_fn (fun))
- {
- if (flags & tf_error)
- {
- error_at (EXPR_LOC_OR_LOC (t, input_location),
- "call to non-constexpr function %qD", fun);
- explain_invalid_constexpr_fn (fun);
- }
- return false;
- }
- /* A call to a non-static member function takes the address
- of the object as the first argument. But in a constant
- expression the address will be folded away, so look
- through it now. */
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
- && !DECL_CONSTRUCTOR_P (fun))
- {
- tree x = get_nth_callarg (t, 0);
- if (is_this_parameter (x))
- return true;
- else if (!RECUR (x, rval))
- return false;
- i = 1;
- }
- }
- else
- {
- if (!RECUR (fun, true))
- return false;
- fun = get_first_fn (fun);
- }
- /* Skip initial arguments to base constructors. */
- if (DECL_BASE_CONSTRUCTOR_P (fun))
- i = num_artificial_parms_for (fun);
- fun = DECL_ORIGIN (fun);
- }
- else
- {
- if (RECUR (fun, rval))
- /* Might end up being a constant function pointer. */;
- else
- return false;
- }
- for (; i < nargs; ++i)
- {
- tree x = get_nth_callarg (t, i);
- /* In a template, reference arguments haven't been converted to
- REFERENCE_TYPE and we might not even know if the parameter
- is a reference, so accept lvalue constants too. */
- bool rv = processing_template_decl ? any : rval;
- if (!RECUR (x, rv))
- return false;
- }
- return true;
- }
- case NON_LVALUE_EXPR:
- /* -- an lvalue-to-rvalue conversion (4.1) unless it is applied to
- -- an lvalue of integral type that refers to a non-volatile
- const variable or static data member initialized with
- constant expressions, or
- -- an lvalue of literal type that refers to non-volatile
- object defined with constexpr, or that refers to a
- sub-object of such an object; */
- return RECUR (TREE_OPERAND (t, 0), rval);
- case VAR_DECL:
- if (want_rval
- && !decl_constant_var_p (t)
- && (strict
- || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
- || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))
- && !var_in_constexpr_fn (t)
- && !type_dependent_expression_p (t))
- {
- if (flags & tf_error)
- non_const_var_error (t);
- return false;
- }
- return true;
- case NOP_EXPR:
- case CONVERT_EXPR:
- case VIEW_CONVERT_EXPR:
- /* -- a reinterpret_cast. FIXME not implemented, and this rule
- may change to something more specific to type-punning (DR 1312). */
- {
- tree from = TREE_OPERAND (t, 0);
- if (POINTER_TYPE_P (TREE_TYPE (t))
- && TREE_CODE (from) == INTEGER_CST
- && !integer_zerop (from))
- {
- if (flags & tf_error)
- error_at (EXPR_LOC_OR_LOC (t, input_location),
- "reinterpret_cast from integer to pointer");
- return false;
- }
- return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
- }
- case ADDR_EXPR:
- /* -- a unary operator & that is applied to an lvalue that
- designates an object with thread or automatic storage
- duration; */
- t = TREE_OPERAND (t, 0);
- if (TREE_CODE (t) == OFFSET_REF && PTRMEM_OK_P (t))
- /* A pointer-to-member constant. */
- return true;
- #if 0
- /* FIXME adjust when issue 1197 is fully resolved. For now don't do
- any checking here, as we might dereference the pointer later. If
- we remove this code, also remove check_automatic_or_tls. */
- i = check_automatic_or_tls (t);
- if (i == ck_ok)
- return true;
- if (i == ck_bad)
- {
- if (flags & tf_error)
- error ("address-of an object %qE with thread local or "
- "automatic storage is not a constant expression", t);
- return false;
- }
- #endif
- return RECUR (t, any);
- case COMPONENT_REF:
- case BIT_FIELD_REF:
- case ARROW_EXPR:
- case OFFSET_REF:
- /* -- a class member access unless its postfix-expression is
- of literal type or of pointer to literal type. */
- /* This test would be redundant, as it follows from the
- postfix-expression being a potential constant expression. */
- return RECUR (TREE_OPERAND (t, 0), want_rval);
- case EXPR_PACK_EXPANSION:
- return RECUR (PACK_EXPANSION_PATTERN (t), want_rval);
- case INDIRECT_REF:
- {
- tree x = TREE_OPERAND (t, 0);
- STRIP_NOPS (x);
- if (is_this_parameter (x))
- {
- if (DECL_CONTEXT (x)
- && !DECL_DECLARED_CONSTEXPR_P (DECL_CONTEXT (x)))
- {
- if (flags & tf_error)
- error ("use of %<this%> in a constant expression");
- return false;
- }
- return true;
- }
- return RECUR (x, rval);
- }
- case STATEMENT_LIST:
- {
- tree_stmt_iterator i;
- for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- {
- if (!RECUR (tsi_stmt (i), any))
- return false;
- }
- return true;
- }
- break;
- case MODIFY_EXPR:
- if (cxx_dialect < cxx14)
- goto fail;
- if (!RECUR (TREE_OPERAND (t, 0), any))
- return false;
- if (!RECUR (TREE_OPERAND (t, 1), rval))
- return false;
- return true;
- case MODOP_EXPR:
- if (cxx_dialect < cxx14)
- goto fail;
- if (!RECUR (TREE_OPERAND (t, 0), rval))
- return false;
- if (!RECUR (TREE_OPERAND (t, 2), rval))
- return false;
- return true;
- case IF_STMT:
- if (!RECUR (IF_COND (t), rval))
- return false;
- if (!RECUR (THEN_CLAUSE (t), any))
- return false;
- if (!RECUR (ELSE_CLAUSE (t), any))
- return false;
- return true;
- case DO_STMT:
- if (!RECUR (DO_COND (t), rval))
- return false;
- if (!RECUR (DO_BODY (t), any))
- return false;
- return true;
- case FOR_STMT:
- if (!RECUR (FOR_INIT_STMT (t), any))
- return false;
- if (!RECUR (FOR_COND (t), rval))
- return false;
- if (!RECUR (FOR_EXPR (t), any))
- return false;
- if (!RECUR (FOR_BODY (t), any))
- return false;
- return true;
- case WHILE_STMT:
- if (!RECUR (WHILE_COND (t), rval))
- return false;
- if (!RECUR (WHILE_BODY (t), any))
- return false;
- return true;
- case SWITCH_STMT:
- if (!RECUR (SWITCH_STMT_COND (t), rval))
- return false;
- if (!RECUR (SWITCH_STMT_BODY (t), any))
- return false;
- return true;
- case STMT_EXPR:
- return RECUR (STMT_EXPR_STMT (t), rval);
- case LAMBDA_EXPR:
- case DYNAMIC_CAST_EXPR:
- case PSEUDO_DTOR_EXPR:
- case NEW_EXPR:
- case VEC_NEW_EXPR:
- case DELETE_EXPR:
- case VEC_DELETE_EXPR:
- case THROW_EXPR:
- case OMP_ATOMIC:
- case OMP_ATOMIC_READ:
- case OMP_ATOMIC_CAPTURE_OLD:
- case OMP_ATOMIC_CAPTURE_NEW:
- /* GCC internal stuff. */
- case VA_ARG_EXPR:
- case OBJ_TYPE_REF:
- case TRANSACTION_EXPR:
- case ASM_EXPR:
- fail:
- if (flags & tf_error)
- error ("expression %qE is not a constant-expression", t);
- return false;
- case TYPEID_EXPR:
- /* -- a typeid expression whose operand is of polymorphic
- class type; */
- {
- tree e = TREE_OPERAND (t, 0);
- if (!TYPE_P (e) && !type_dependent_expression_p (e)
- && TYPE_POLYMORPHIC_P (TREE_TYPE (e)))
- {
- if (flags & tf_error)
- error ("typeid-expression is not a constant expression "
- "because %qE is of polymorphic type", e);
- return false;
- }
- return true;
- }
- case MINUS_EXPR:
- /* -- a subtraction where both operands are pointers. */
- if (TYPE_PTR_P (TREE_OPERAND (t, 0))
- && TYPE_PTR_P (TREE_OPERAND (t, 1)))
- {
- if (flags & tf_error)
- error ("difference of two pointer expressions is not "
- "a constant expression");
- return false;
- }
- want_rval = true;
- goto binary;
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- /* -- a relational or equality operator where at least
- one of the operands is a pointer. */
- if (TYPE_PTR_P (TREE_OPERAND (t, 0))
- || TYPE_PTR_P (TREE_OPERAND (t, 1)))
- {
- if (flags & tf_error)
- error ("pointer comparison expression is not a "
- "constant expression");
- return false;
- }
- want_rval = true;
- goto binary;
- case PREINCREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- if (cxx_dialect < cxx14)
- goto fail;
- goto unary;
- case BIT_NOT_EXPR:
- /* A destructor. */
- if (TYPE_P (TREE_OPERAND (t, 0)))
- return true;
- /* else fall through. */
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- case CONJ_EXPR:
- case SAVE_EXPR:
- case FIX_TRUNC_EXPR:
- case FLOAT_EXPR:
- case NEGATE_EXPR:
- case ABS_EXPR:
- case TRUTH_NOT_EXPR:
- case FIXED_CONVERT_EXPR:
- case UNARY_PLUS_EXPR:
- unary:
- return RECUR (TREE_OPERAND (t, 0), rval);
- case CAST_EXPR:
- case CONST_CAST_EXPR:
- case STATIC_CAST_EXPR:
- case REINTERPRET_CAST_EXPR:
- case IMPLICIT_CONV_EXPR:
- if (cxx_dialect < cxx11
- && !dependent_type_p (TREE_TYPE (t))
- && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)))
- /* In C++98, a conversion to non-integral type can't be part of a
- constant expression. */
- {
- if (flags & tf_error)
- error ("cast to non-integral type %qT in a constant expression",
- TREE_TYPE (t));
- return false;
- }
- return (RECUR (TREE_OPERAND (t, 0),
- TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE));
- case BIND_EXPR:
- return RECUR (BIND_EXPR_BODY (t), want_rval);
- case WITH_CLEANUP_EXPR:
- case CLEANUP_POINT_EXPR:
- case MUST_NOT_THROW_EXPR:
- case TRY_CATCH_EXPR:
- case TRY_BLOCK:
- case EH_SPEC_BLOCK:
- case EXPR_STMT:
- case PAREN_EXPR:
- case DECL_EXPR:
- case NON_DEPENDENT_EXPR:
- /* For convenience. */
- case RETURN_EXPR:
- return RECUR (TREE_OPERAND (t, 0), want_rval);
- case TRY_FINALLY_EXPR:
- return (RECUR (TREE_OPERAND (t, 0), want_rval)
- && RECUR (TREE_OPERAND (t, 1), any));
- case SCOPE_REF:
- return RECUR (TREE_OPERAND (t, 1), want_rval);
- case TARGET_EXPR:
- if (!literal_type_p (TREE_TYPE (t)))
- {
- if (flags & tf_error)
- {
- error ("temporary of non-literal type %qT in a "
- "constant expression", TREE_TYPE (t));
- explain_non_literal_class (TREE_TYPE (t));
- }
- return false;
- }
- case INIT_EXPR:
- return RECUR (TREE_OPERAND (t, 1), rval);
- case CONSTRUCTOR:
- {
- vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
- constructor_elt *ce;
- for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
- if (!RECUR (ce->value, want_rval))
- return false;
- return true;
- }
- case TREE_LIST:
- {
- gcc_assert (TREE_PURPOSE (t) == NULL_TREE
- || DECL_P (TREE_PURPOSE (t)));
- if (!RECUR (TREE_VALUE (t), want_rval))
- return false;
- if (TREE_CHAIN (t) == NULL_TREE)
- return true;
- return RECUR (TREE_CHAIN (t), want_rval);
- }
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case ROUND_MOD_EXPR:
- {
- tree denom = TREE_OPERAND (t, 1);
- if (!RECUR (denom, rval))
- return false;
- /* We can't call cxx_eval_outermost_constant_expr on an expression
- that hasn't been through instantiate_non_dependent_expr yet. */
- if (!processing_template_decl)
- denom = cxx_eval_outermost_constant_expr (denom, true);
- if (integer_zerop (denom))
- {
- if (flags & tf_error)
- error ("division by zero is not a constant-expression");
- return false;
- }
- else
- {
- want_rval = true;
- return RECUR (TREE_OPERAND (t, 0), want_rval);
- }
- }
- case COMPOUND_EXPR:
- {
- /* check_return_expr sometimes wraps a TARGET_EXPR in a
- COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR
- introduced by build_call_a. */
- tree op0 = TREE_OPERAND (t, 0);
- tree op1 = TREE_OPERAND (t, 1);
- STRIP_NOPS (op1);
- if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
- || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
- return RECUR (op0, want_rval);
- else
- goto binary;
- }
- /* If the first operand is the non-short-circuit constant, look at
- the second operand; otherwise we only care about the first one for
- potentiality. */
- case TRUTH_AND_EXPR:
- case TRUTH_ANDIF_EXPR:
- tmp = boolean_true_node;
- goto truth;
- case TRUTH_OR_EXPR:
- case TRUTH_ORIF_EXPR:
- tmp = boolean_false_node;
- truth:
- {
- tree op = TREE_OPERAND (t, 0);
- if (!RECUR (op, rval))
- return false;
- if (!processing_template_decl)
- op = cxx_eval_outermost_constant_expr (op, true);
- if (tree_int_cst_equal (op, tmp))
- return RECUR (TREE_OPERAND (t, 1), rval);
- else
- return true;
- }
- case PLUS_EXPR:
- case MULT_EXPR:
- case POINTER_PLUS_EXPR:
- case RDIV_EXPR:
- case EXACT_DIV_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
- case TRUTH_XOR_EXPR:
- case UNORDERED_EXPR:
- case ORDERED_EXPR:
- case UNLT_EXPR:
- case UNLE_EXPR:
- case UNGT_EXPR:
- case UNGE_EXPR:
- case UNEQ_EXPR:
- case LTGT_EXPR:
- case RANGE_EXPR:
- case COMPLEX_EXPR:
- want_rval = true;
- /* Fall through. */
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- case MEMBER_REF:
- case DOTSTAR_EXPR:
- case MEM_REF:
- binary:
- for (i = 0; i < 2; ++i)
- if (!RECUR (TREE_OPERAND (t, i), want_rval))
- return false;
- return true;
- case CILK_SYNC_STMT:
- case CILK_SPAWN_STMT:
- case ARRAY_NOTATION_REF:
- return false;
- case FMA_EXPR:
- case VEC_PERM_EXPR:
- for (i = 0; i < 3; ++i)
- if (!RECUR (TREE_OPERAND (t, i), true))
- return false;
- return true;
- case COND_EXPR:
- case VEC_COND_EXPR:
- /* If the condition is a known constant, we know which of the legs we
- care about; otherwise we only require that the condition and
- either of the legs be potentially constant. */
- tmp = TREE_OPERAND (t, 0);
- if (!RECUR (tmp, rval))
- return false;
- if (!processing_template_decl)
- tmp = cxx_eval_outermost_constant_expr (tmp, true);
- if (integer_zerop (tmp))
- return RECUR (TREE_OPERAND (t, 2), want_rval);
- else if (TREE_CODE (tmp) == INTEGER_CST)
- return RECUR (TREE_OPERAND (t, 1), want_rval);
- for (i = 1; i < 3; ++i)
- if (potential_constant_expression_1 (TREE_OPERAND (t, i),
- want_rval, strict, tf_none))
- return true;
- if (flags & tf_error)
- error ("expression %qE is not a constant-expression", t);
- return false;
- case VEC_INIT_EXPR:
- if (VEC_INIT_EXPR_IS_CONSTEXPR (t))
- return true;
- if (flags & tf_error)
- {
- error ("non-constant array initialization");
- diagnose_non_constexpr_vec_init (t);
- }
- return false;
- case TYPE_DECL:
- case TAG_DEFN:
- /* We can see these in statement-expressions. */
- return true;
- default:
- if (objc_is_property_ref (t))
- return false;
- sorry ("unexpected AST of kind %s", get_tree_code_name (TREE_CODE (t)));
- gcc_unreachable();
- return false;
- }
- #undef RECUR
- }
- /* The main entry point to the above. */
- bool
- potential_constant_expression (tree t)
- {
- return potential_constant_expression_1 (t, false, true, tf_none);
- }
- bool
- potential_static_init_expression (tree t)
- {
- return potential_constant_expression_1 (t, false, false, tf_none);
- }
- /* As above, but require a constant rvalue. */
- bool
- potential_rvalue_constant_expression (tree t)
- {
- return potential_constant_expression_1 (t, true, true, tf_none);
- }
- /* Like above, but complain about non-constant expressions. */
- bool
- require_potential_constant_expression (tree t)
- {
- return potential_constant_expression_1 (t, false, true, tf_warning_or_error);
- }
- /* Cross product of the above. */
- bool
- require_potential_rvalue_constant_expression (tree t)
- {
- return potential_constant_expression_1 (t, true, true, tf_warning_or_error);
- }
- #include "gt-cp-constexpr.h"
|