12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367 |
- //===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements type-related semantic analysis.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Sema/SemaInternal.h"
- #include "clang/Sema/Template.h"
- #include "clang/Basic/OpenCL.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/ASTMutationListener.h"
- #include "clang/AST/CXXInheritance.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/TypeLoc.h"
- #include "clang/AST/TypeLocVisitor.h"
- #include "clang/AST/Expr.h"
- #include "clang/Basic/PartialDiagnostic.h"
- #include "clang/Basic/TargetInfo.h"
- #include "clang/Lex/Preprocessor.h"
- #include "clang/Sema/DeclSpec.h"
- #include "clang/Sema/DelayedDiagnostic.h"
- #include "llvm/ADT/SmallPtrSet.h"
- #include "llvm/Support/ErrorHandling.h"
- using namespace clang;
- /// isOmittedBlockReturnType - Return true if this declarator is missing a
- /// return type because this is a omitted return type on a block literal.
- static bool isOmittedBlockReturnType(const Declarator &D) {
- if (D.getContext() != Declarator::BlockLiteralContext ||
- D.getDeclSpec().hasTypeSpecifier())
- return false;
-
- if (D.getNumTypeObjects() == 0)
- return true; // ^{ ... }
-
- if (D.getNumTypeObjects() == 1 &&
- D.getTypeObject(0).Kind == DeclaratorChunk::Function)
- return true; // ^(int X, float Y) { ... }
-
- return false;
- }
- /// diagnoseBadTypeAttribute - Diagnoses a type attribute which
- /// doesn't apply to the given type.
- static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
- QualType type) {
- bool useExpansionLoc = false;
- unsigned diagID = 0;
- switch (attr.getKind()) {
- case AttributeList::AT_objc_gc:
- diagID = diag::warn_pointer_attribute_wrong_type;
- useExpansionLoc = true;
- break;
- case AttributeList::AT_objc_ownership:
- diagID = diag::warn_objc_object_attribute_wrong_type;
- useExpansionLoc = true;
- break;
- default:
- // Assume everything else was a function attribute.
- diagID = diag::warn_function_attribute_wrong_type;
- break;
- }
- SourceLocation loc = attr.getLoc();
- StringRef name = attr.getName()->getName();
- // The GC attributes are usually written with macros; special-case them.
- if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) {
- if (attr.getParameterName()->isStr("strong")) {
- if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
- } else if (attr.getParameterName()->isStr("weak")) {
- if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
- }
- }
- S.Diag(loc, diagID) << name << type;
- }
- // objc_gc applies to Objective-C pointers or, otherwise, to the
- // smallest available pointer type (i.e. 'void*' in 'void**').
- #define OBJC_POINTER_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_objc_gc: \
- case AttributeList::AT_objc_ownership
- // Function type attributes.
- #define FUNCTION_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_noreturn: \
- case AttributeList::AT_cdecl: \
- case AttributeList::AT_fastcall: \
- case AttributeList::AT_stdcall: \
- case AttributeList::AT_thiscall: \
- case AttributeList::AT_pascal: \
- case AttributeList::AT_regparm: \
- case AttributeList::AT_pcs \
- namespace {
- /// An object which stores processing state for the entire
- /// GetTypeForDeclarator process.
- class TypeProcessingState {
- Sema &sema;
- /// The declarator being processed.
- Declarator &declarator;
- /// The index of the declarator chunk we're currently processing.
- /// May be the total number of valid chunks, indicating the
- /// DeclSpec.
- unsigned chunkIndex;
- /// Whether there are non-trivial modifications to the decl spec.
- bool trivial;
- /// Whether we saved the attributes in the decl spec.
- bool hasSavedAttrs;
- /// The original set of attributes on the DeclSpec.
- SmallVector<AttributeList*, 2> savedAttrs;
- /// A list of attributes to diagnose the uselessness of when the
- /// processing is complete.
- SmallVector<AttributeList*, 2> ignoredTypeAttrs;
- public:
- TypeProcessingState(Sema &sema, Declarator &declarator)
- : sema(sema), declarator(declarator),
- chunkIndex(declarator.getNumTypeObjects()),
- trivial(true), hasSavedAttrs(false) {}
- Sema &getSema() const {
- return sema;
- }
- Declarator &getDeclarator() const {
- return declarator;
- }
- unsigned getCurrentChunkIndex() const {
- return chunkIndex;
- }
- void setCurrentChunkIndex(unsigned idx) {
- assert(idx <= declarator.getNumTypeObjects());
- chunkIndex = idx;
- }
- AttributeList *&getCurrentAttrListRef() const {
- assert(chunkIndex <= declarator.getNumTypeObjects());
- if (chunkIndex == declarator.getNumTypeObjects())
- return getMutableDeclSpec().getAttributes().getListRef();
- return declarator.getTypeObject(chunkIndex).getAttrListRef();
- }
- /// Save the current set of attributes on the DeclSpec.
- void saveDeclSpecAttrs() {
- // Don't try to save them multiple times.
- if (hasSavedAttrs) return;
- DeclSpec &spec = getMutableDeclSpec();
- for (AttributeList *attr = spec.getAttributes().getList(); attr;
- attr = attr->getNext())
- savedAttrs.push_back(attr);
- trivial &= savedAttrs.empty();
- hasSavedAttrs = true;
- }
- /// Record that we had nowhere to put the given type attribute.
- /// We will diagnose such attributes later.
- void addIgnoredTypeAttr(AttributeList &attr) {
- ignoredTypeAttrs.push_back(&attr);
- }
- /// Diagnose all the ignored type attributes, given that the
- /// declarator worked out to the given type.
- void diagnoseIgnoredTypeAttrs(QualType type) const {
- for (SmallVectorImpl<AttributeList*>::const_iterator
- i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
- i != e; ++i)
- diagnoseBadTypeAttribute(getSema(), **i, type);
- }
- ~TypeProcessingState() {
- if (trivial) return;
- restoreDeclSpecAttrs();
- }
- private:
- DeclSpec &getMutableDeclSpec() const {
- return const_cast<DeclSpec&>(declarator.getDeclSpec());
- }
- void restoreDeclSpecAttrs() {
- assert(hasSavedAttrs);
- if (savedAttrs.empty()) {
- getMutableDeclSpec().getAttributes().set(0);
- return;
- }
- getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
- for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
- savedAttrs[i]->setNext(savedAttrs[i+1]);
- savedAttrs.back()->setNext(0);
- }
- };
- /// Basically std::pair except that we really want to avoid an
- /// implicit operator= for safety concerns. It's also a minor
- /// link-time optimization for this to be a private type.
- struct AttrAndList {
- /// The attribute.
- AttributeList &first;
- /// The head of the list the attribute is currently in.
- AttributeList *&second;
- AttrAndList(AttributeList &attr, AttributeList *&head)
- : first(attr), second(head) {}
- };
- }
- namespace llvm {
- template <> struct isPodLike<AttrAndList> {
- static const bool value = true;
- };
- }
- static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
- attr.setNext(head);
- head = &attr;
- }
- static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
- if (head == &attr) {
- head = attr.getNext();
- return;
- }
- AttributeList *cur = head;
- while (true) {
- assert(cur && cur->getNext() && "ran out of attrs?");
- if (cur->getNext() == &attr) {
- cur->setNext(attr.getNext());
- return;
- }
- cur = cur->getNext();
- }
- }
- static void moveAttrFromListToList(AttributeList &attr,
- AttributeList *&fromList,
- AttributeList *&toList) {
- spliceAttrOutOfList(attr, fromList);
- spliceAttrIntoList(attr, toList);
- }
- static void processTypeAttrs(TypeProcessingState &state,
- QualType &type, bool isDeclSpec,
- AttributeList *attrs);
- static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type);
- static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
- static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type);
- static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr, QualType &type) {
- if (attr.getKind() == AttributeList::AT_objc_gc)
- return handleObjCGCTypeAttr(state, attr, type);
- assert(attr.getKind() == AttributeList::AT_objc_ownership);
- return handleObjCOwnershipTypeAttr(state, attr, type);
- }
- /// Given that an objc_gc attribute was written somewhere on a
- /// declaration *other* than on the declarator itself (for which, use
- /// distributeObjCPointerTypeAttrFromDeclarator), and given that it
- /// didn't apply in whatever position it was written in, try to move
- /// it to a more appropriate position.
- static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
- Declarator &declarator = state.getDeclarator();
- for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
- switch (chunk.Kind) {
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
- return;
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Array:
- continue;
- // Don't walk through these.
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Function:
- case DeclaratorChunk::MemberPointer:
- goto error;
- }
- }
- error:
- diagnoseBadTypeAttribute(state.getSema(), attr, type);
- }
- /// Distribute an objc_gc type attribute that was written on the
- /// declarator.
- static void
- distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // objc_gc goes on the innermost pointer to something that's not a
- // pointer.
- unsigned innermost = -1U;
- bool considerDeclSpec = true;
- for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i);
- switch (chunk.Kind) {
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- innermost = i;
- continue;
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Array:
- continue;
- case DeclaratorChunk::Function:
- considerDeclSpec = false;
- goto done;
- }
- }
- done:
- // That might actually be the decl spec if we weren't blocked by
- // anything in the declarator.
- if (considerDeclSpec) {
- if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
- // Splice the attribute into the decl spec. Prevents the
- // attribute from being applied multiple times and gives
- // the source-location-filler something to work with.
- state.saveDeclSpecAttrs();
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getMutableDeclSpec().getAttributes().getListRef());
- return;
- }
- }
- // Otherwise, if we found an appropriate chunk, splice the attribute
- // into it.
- if (innermost != -1U) {
- moveAttrFromListToList(attr, declarator.getAttrListRef(),
- declarator.getTypeObject(innermost).getAttrListRef());
- return;
- }
- // Otherwise, diagnose when we're done building the type.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
- state.addIgnoredTypeAttr(attr);
- }
- /// A function type attribute was written somewhere in a declaration
- /// *other* than on the declarator itself or in the decl spec. Given
- /// that it didn't apply in whatever position it was written in, try
- /// to move it to a more appropriate position.
- static void distributeFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType type) {
- Declarator &declarator = state.getDeclarator();
- // Try to push the attribute from the return type of a function to
- // the function itself.
- for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
- switch (chunk.Kind) {
- case DeclaratorChunk::Function:
- moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
- chunk.getAttrListRef());
- return;
- case DeclaratorChunk::Paren:
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- continue;
- }
- }
-
- diagnoseBadTypeAttribute(state.getSema(), attr, type);
- }
- /// Try to distribute a function type attribute to the innermost
- /// function chunk or type. Returns true if the attribute was
- /// distributed, false if no location was found.
- static bool
- distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
- AttributeList &attr,
- AttributeList *&attrList,
- QualType &declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // Put it on the innermost function chunk, if there is one.
- for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &chunk = declarator.getTypeObject(i);
- if (chunk.Kind != DeclaratorChunk::Function) continue;
- moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
- return true;
- }
- if (handleFunctionTypeAttr(state, attr, declSpecType)) {
- spliceAttrOutOfList(attr, attrList);
- return true;
- }
- return false;
- }
- /// A function type attribute was written in the decl spec. Try to
- /// apply it somewhere.
- static void
- distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
- state.saveDeclSpecAttrs();
- // Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- state.getCurrentAttrListRef(),
- declSpecType))
- return;
- // If that failed, diagnose the bad attribute when the declarator is
- // fully built.
- state.addIgnoredTypeAttr(attr);
- }
- /// A function type attribute was written on the declarator. Try to
- /// apply it somewhere.
- static void
- distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
- AttributeList &attr,
- QualType &declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // Try to distribute to the innermost.
- if (distributeFunctionTypeAttrToInnermost(state, attr,
- declarator.getAttrListRef(),
- declSpecType))
- return;
- // If that failed, diagnose the bad attribute when the declarator is
- // fully built.
- spliceAttrOutOfList(attr, declarator.getAttrListRef());
- state.addIgnoredTypeAttr(attr);
- }
- /// \brief Given that there are attributes written on the declarator
- /// itself, try to distribute any type attributes to the appropriate
- /// declarator chunk.
- ///
- /// These are attributes like the following:
- /// int f ATTR;
- /// int (f ATTR)();
- /// but not necessarily this:
- /// int f() ATTR;
- static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
- QualType &declSpecType) {
- // Collect all the type attributes from the declarator itself.
- assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
- AttributeList *attr = state.getDeclarator().getAttributes();
- AttributeList *next;
- do {
- next = attr->getNext();
- switch (attr->getKind()) {
- OBJC_POINTER_TYPE_ATTRS_CASELIST:
- distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
- break;
- case AttributeList::AT_ns_returns_retained:
- if (!state.getSema().getLangOptions().ObjCAutoRefCount)
- break;
- // fallthrough
- FUNCTION_TYPE_ATTRS_CASELIST:
- distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
- break;
- default:
- break;
- }
- } while ((attr = next));
- }
- /// Add a synthetic '()' to a block-literal declarator if it is
- /// required, given the return type.
- static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
- QualType declSpecType) {
- Declarator &declarator = state.getDeclarator();
- // First, check whether the declarator would produce a function,
- // i.e. whether the innermost semantic chunk is a function.
- if (declarator.isFunctionDeclarator()) {
- // If so, make that declarator a prototyped declarator.
- declarator.getFunctionTypeInfo().hasPrototype = true;
- return;
- }
- // If there are any type objects, the type as written won't name a
- // function, regardless of the decl spec type. This is because a
- // block signature declarator is always an abstract-declarator, and
- // abstract-declarators can't just be parentheses chunks. Therefore
- // we need to build a function chunk unless there are no type
- // objects and the decl spec type is a function.
- if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
- return;
- // Note that there *are* cases with invalid declarators where
- // declarators consist solely of parentheses. In general, these
- // occur only in failed efforts to make function declarators, so
- // faking up the function chunk is still the right thing to do.
- // Otherwise, we need to fake up a function declarator.
- SourceLocation loc = declarator.getSourceRange().getBegin();
- // ...and *prepend* it to the declarator.
- declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
- /*proto*/ true,
- /*variadic*/ false, SourceLocation(),
- /*args*/ 0, 0,
- /*type quals*/ 0,
- /*ref-qualifier*/true, SourceLocation(),
- /*const qualifier*/SourceLocation(),
- /*volatile qualifier*/SourceLocation(),
- /*mutable qualifier*/SourceLocation(),
- /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
- /*parens*/ loc, loc,
- declarator));
- // For consistency, make sure the state still has us as processing
- // the decl spec.
- assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
- state.setCurrentChunkIndex(declarator.getNumTypeObjects());
- }
- /// \brief Convert the specified declspec to the appropriate type
- /// object.
- /// \param D the declarator containing the declaration specifier.
- /// \returns The type described by the declaration specifiers. This function
- /// never returns null.
- static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
- // FIXME: Should move the logic from DeclSpec::Finish to here for validity
- // checking.
- Sema &S = state.getSema();
- Declarator &declarator = state.getDeclarator();
- const DeclSpec &DS = declarator.getDeclSpec();
- SourceLocation DeclLoc = declarator.getIdentifierLoc();
- if (DeclLoc.isInvalid())
- DeclLoc = DS.getSourceRange().getBegin();
-
- ASTContext &Context = S.Context;
- QualType Result;
- switch (DS.getTypeSpecType()) {
- case DeclSpec::TST_void:
- Result = Context.VoidTy;
- break;
- case DeclSpec::TST_char:
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
- Result = Context.CharTy;
- else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
- Result = Context.SignedCharTy;
- else {
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
- "Unknown TSS value");
- Result = Context.UnsignedCharTy;
- }
- break;
- case DeclSpec::TST_wchar:
- if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
- Result = Context.WCharTy;
- else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
- S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType());
- Result = Context.getSignedWCharType();
- } else {
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
- "Unknown TSS value");
- S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
- << DS.getSpecifierName(DS.getTypeSpecType());
- Result = Context.getUnsignedWCharType();
- }
- break;
- case DeclSpec::TST_char16:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char16Ty;
- break;
- case DeclSpec::TST_char32:
- assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
- "Unknown TSS value");
- Result = Context.Char32Ty;
- break;
- case DeclSpec::TST_unspecified:
- // "<proto1,proto2>" is an objc qualified ID with a missing id.
- if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
- Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl**)PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- break;
- }
-
- // If this is a missing declspec in a block literal return context, then it
- // is inferred from the return statements inside the block.
- if (isOmittedBlockReturnType(declarator)) {
- Result = Context.DependentTy;
- break;
- }
- // Unspecified typespec defaults to int in C90. However, the C90 grammar
- // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
- // type-qualifier, or storage-class-specifier. If not, emit an extwarn.
- // Note that the one exception to this is function definitions, which are
- // allowed to be completely missing a declspec. This is handled in the
- // parser already though by it pretending to have seen an 'int' in this
- // case.
- if (S.getLangOptions().ImplicitInt) {
- // In C89 mode, we only warn if there is a completely missing declspec
- // when one is not allowed.
- if (DS.isEmpty()) {
- S.Diag(DeclLoc, diag::ext_missing_declspec)
- << DS.getSourceRange()
- << FixItHint::CreateInsertion(DS.getSourceRange().getBegin(), "int");
- }
- } else if (!DS.hasTypeSpecifier()) {
- // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says:
- // "At least one type specifier shall be given in the declaration
- // specifiers in each declaration, and in the specifier-qualifier list in
- // each struct declaration and type name."
- // FIXME: Does Microsoft really have the implicit int extension in C++?
- if (S.getLangOptions().CPlusPlus &&
- !S.getLangOptions().MicrosoftExt) {
- S.Diag(DeclLoc, diag::err_missing_type_specifier)
- << DS.getSourceRange();
- // When this occurs in C++ code, often something is very broken with the
- // value being declared, poison it as invalid so we don't get chains of
- // errors.
- declarator.setInvalidType(true);
- } else {
- S.Diag(DeclLoc, diag::ext_missing_type_specifier)
- << DS.getSourceRange();
- }
- }
- // FALL THROUGH.
- case DeclSpec::TST_int: {
- if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
- switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
- case DeclSpec::TSW_short: Result = Context.ShortTy; break;
- case DeclSpec::TSW_long: Result = Context.LongTy; break;
- case DeclSpec::TSW_longlong:
- Result = Context.LongLongTy;
-
- // long long is a C99 feature.
- if (!S.getLangOptions().C99)
- S.Diag(DS.getTypeSpecWidthLoc(),
- S.getLangOptions().CPlusPlus0x ?
- diag::warn_cxx98_compat_longlong : diag::ext_longlong);
- break;
- }
- } else {
- switch (DS.getTypeSpecWidth()) {
- case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
- case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
- case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
- case DeclSpec::TSW_longlong:
- Result = Context.UnsignedLongLongTy;
-
- // long long is a C99 feature.
- if (!S.getLangOptions().C99)
- S.Diag(DS.getTypeSpecWidthLoc(),
- S.getLangOptions().CPlusPlus0x ?
- diag::warn_cxx98_compat_longlong : diag::ext_longlong);
- break;
- }
- }
- break;
- }
- case DeclSpec::TST_half: Result = Context.HalfTy; break;
- case DeclSpec::TST_float: Result = Context.FloatTy; break;
- case DeclSpec::TST_double:
- if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
- Result = Context.LongDoubleTy;
- else
- Result = Context.DoubleTy;
- if (S.getLangOptions().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64);
- declarator.setInvalidType(true);
- }
- break;
- case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
- case DeclSpec::TST_decimal32: // _Decimal32
- case DeclSpec::TST_decimal64: // _Decimal64
- case DeclSpec::TST_decimal128: // _Decimal128
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- break;
- case DeclSpec::TST_class:
- case DeclSpec::TST_enum:
- case DeclSpec::TST_union:
- case DeclSpec::TST_struct: {
- TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
- if (!D) {
- // This can happen in C++ with ambiguous lookups.
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- break;
- }
- // If the type is deprecated or unavailable, diagnose it.
- S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
-
- assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
-
- // TypeQuals handled by caller.
- Result = Context.getTypeDeclType(D);
- // In both C and C++, make an ElaboratedType.
- ElaboratedTypeKeyword Keyword
- = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
- Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
- if (D->isInvalidDecl())
- declarator.setInvalidType(true);
- break;
- }
- case DeclSpec::TST_typename: {
- assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
- DS.getTypeSpecSign() == 0 &&
- "Can't handle qualifiers on typedef names yet!");
- Result = S.GetTypeFromParser(DS.getRepAsType());
- if (Result.isNull())
- declarator.setInvalidType(true);
- else if (DeclSpec::ProtocolQualifierListTy PQ
- = DS.getProtocolQualifiers()) {
- if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
- // Silently drop any existing protocol qualifiers.
- // TODO: determine whether that's the right thing to do.
- if (ObjT->getNumProtocols())
- Result = ObjT->getBaseType();
- if (DS.getNumProtocolQualifiers())
- Result = Context.getObjCObjectType(Result,
- (ObjCProtocolDecl**) PQ,
- DS.getNumProtocolQualifiers());
- } else if (Result->isObjCIdType()) {
- // id<protocol-list>
- Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl**) PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- } else if (Result->isObjCClassType()) {
- // Class<protocol-list>
- Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
- (ObjCProtocolDecl**) PQ,
- DS.getNumProtocolQualifiers());
- Result = Context.getObjCObjectPointerType(Result);
- } else {
- S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
- << DS.getSourceRange();
- declarator.setInvalidType(true);
- }
- }
- // TypeQuals handled by caller.
- break;
- }
- case DeclSpec::TST_typeofType:
- // FIXME: Preserve type source info.
- Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for typeof?");
- if (!Result->isDependentType())
- if (const TagType *TT = Result->getAs<TagType>())
- S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
- // TypeQuals handled by caller.
- Result = Context.getTypeOfType(Result);
- break;
- case DeclSpec::TST_typeofExpr: {
- Expr *E = DS.getRepAsExpr();
- assert(E && "Didn't get an expression for typeof?");
- // TypeQuals handled by caller.
- Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- }
- case DeclSpec::TST_decltype: {
- Expr *E = DS.getRepAsExpr();
- assert(E && "Didn't get an expression for decltype?");
- // TypeQuals handled by caller.
- Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- }
- case DeclSpec::TST_underlyingType:
- Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
- Result = S.BuildUnaryTransformType(Result,
- UnaryTransformType::EnumUnderlyingType,
- DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- case DeclSpec::TST_auto: {
- // TypeQuals handled by caller.
- Result = Context.getAutoType(QualType());
- break;
- }
- case DeclSpec::TST_unknown_anytype:
- Result = Context.UnknownAnyTy;
- break;
- case DeclSpec::TST_atomic:
- Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for _Atomic?");
- Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
- if (Result.isNull()) {
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- }
- break;
- case DeclSpec::TST_error:
- Result = Context.IntTy;
- declarator.setInvalidType(true);
- break;
- }
- // Handle complex types.
- if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
- if (S.getLangOptions().Freestanding)
- S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
- Result = Context.getComplexType(Result);
- } else if (DS.isTypeAltiVecVector()) {
- unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
- assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
- VectorType::VectorKind VecKind = VectorType::AltiVecVector;
- if (DS.isTypeAltiVecPixel())
- VecKind = VectorType::AltiVecPixel;
- else if (DS.isTypeAltiVecBool())
- VecKind = VectorType::AltiVecBool;
- Result = Context.getVectorType(Result, 128/typeSize, VecKind);
- }
- // FIXME: Imaginary.
- if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
- S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
- // Before we process any type attributes, synthesize a block literal
- // function declarator if necessary.
- if (declarator.getContext() == Declarator::BlockLiteralContext)
- maybeSynthesizeBlockSignature(state, Result);
- // Apply any type attributes from the decl spec. This may cause the
- // list of type attributes to be temporarily saved while the type
- // attributes are pushed around.
- if (AttributeList *attrs = DS.getAttributes().getList())
- processTypeAttrs(state, Result, true, attrs);
- // Apply const/volatile/restrict qualifiers to T.
- if (unsigned TypeQuals = DS.getTypeQualifiers()) {
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
- // or incomplete types shall not be restrict-qualified." C++ also allows
- // restrict-qualified references.
- if (TypeQuals & DeclSpec::TQ_restrict) {
- if (Result->isAnyPointerType() || Result->isReferenceType()) {
- QualType EltTy;
- if (Result->isObjCObjectPointerType())
- EltTy = Result;
- else
- EltTy = Result->isPointerType() ?
- Result->getAs<PointerType>()->getPointeeType() :
- Result->getAs<ReferenceType>()->getPointeeType();
- // If we have a pointer or reference, the pointee must have an object
- // incomplete type.
- if (!EltTy->isIncompleteOrObjectType()) {
- S.Diag(DS.getRestrictSpecLoc(),
- diag::err_typecheck_invalid_restrict_invalid_pointee)
- << EltTy << DS.getSourceRange();
- TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
- }
- } else {
- S.Diag(DS.getRestrictSpecLoc(),
- diag::err_typecheck_invalid_restrict_not_pointer)
- << Result << DS.getSourceRange();
- TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
- }
- }
- // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
- // of a function type includes any type qualifiers, the behavior is
- // undefined."
- if (Result->isFunctionType() && TypeQuals) {
- // Get some location to point at, either the C or V location.
- SourceLocation Loc;
- if (TypeQuals & DeclSpec::TQ_const)
- Loc = DS.getConstSpecLoc();
- else if (TypeQuals & DeclSpec::TQ_volatile)
- Loc = DS.getVolatileSpecLoc();
- else {
- assert((TypeQuals & DeclSpec::TQ_restrict) &&
- "Has CVR quals but not C, V, or R?");
- Loc = DS.getRestrictSpecLoc();
- }
- S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
- }
- // C++ [dcl.ref]p1:
- // Cv-qualified references are ill-formed except when the
- // cv-qualifiers are introduced through the use of a typedef
- // (7.1.3) or of a template type argument (14.3), in which
- // case the cv-qualifiers are ignored.
- // FIXME: Shouldn't we be checking SCS_typedef here?
- if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
- TypeQuals && Result->isReferenceType()) {
- TypeQuals &= ~DeclSpec::TQ_const;
- TypeQuals &= ~DeclSpec::TQ_volatile;
- }
- Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
- Result = Context.getQualifiedType(Result, Quals);
- }
- return Result;
- }
- static std::string getPrintableNameForEntity(DeclarationName Entity) {
- if (Entity)
- return Entity.getAsString();
- return "type name";
- }
- QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
- Qualifiers Qs) {
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from
- // object or incomplete types shall not be restrict-qualified."
- if (Qs.hasRestrict()) {
- unsigned DiagID = 0;
- QualType ProblemTy;
- const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
- if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
- if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
- }
- } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<PointerType>()->getPointeeType();
- }
- } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
- if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<PointerType>()->getPointeeType();
- }
- } else if (!Ty->isDependentType()) {
- // FIXME: this deserves a proper diagnostic
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T;
- }
- if (DiagID) {
- Diag(Loc, DiagID) << ProblemTy;
- Qs.removeRestrict();
- }
- }
- return Context.getQualifiedType(T, Qs);
- }
- /// \brief Build a paren type including \p T.
- QualType Sema::BuildParenType(QualType T) {
- return Context.getParenType(T);
- }
- /// Given that we're building a pointer or reference to the given
- static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
- SourceLocation loc,
- bool isReference) {
- // Bail out if retention is unrequired or already specified.
- if (!type->isObjCLifetimeType() ||
- type.getObjCLifetime() != Qualifiers::OCL_None)
- return type;
- Qualifiers::ObjCLifetime implicitLifetime = Qualifiers::OCL_None;
- // If the object type is const-qualified, we can safely use
- // __unsafe_unretained. This is safe (because there are no read
- // barriers), and it'll be safe to coerce anything but __weak* to
- // the resulting type.
- if (type.isConstQualified()) {
- implicitLifetime = Qualifiers::OCL_ExplicitNone;
- // Otherwise, check whether the static type does not require
- // retaining. This currently only triggers for Class (possibly
- // protocol-qualifed, and arrays thereof).
- } else if (type->isObjCARCImplicitlyUnretainedType()) {
- implicitLifetime = Qualifiers::OCL_ExplicitNone;
- // If we are in an unevaluated context, like sizeof, assume ExplicitNone and
- // don't give error.
- } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated ||
- S.ExprEvalContexts.back().Context == Sema::ConstantEvaluated) {
- implicitLifetime = Qualifiers::OCL_ExplicitNone;
- // If that failed, give an error and recover using __autoreleasing.
- } else {
- // These types can show up in private ivars in system headers, so
- // we need this to not be an error in those cases. Instead we
- // want to delay.
- if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
- S.DelayedDiagnostics.add(
- sema::DelayedDiagnostic::makeForbiddenType(loc,
- diag::err_arc_indirect_no_ownership, type, isReference));
- } else {
- S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
- }
- implicitLifetime = Qualifiers::OCL_Autoreleasing;
- }
- assert(implicitLifetime && "didn't infer any lifetime!");
- Qualifiers qs;
- qs.addObjCLifetime(implicitLifetime);
- return S.Context.getQualifiedType(type, qs);
- }
- /// \brief Build a pointer type.
- ///
- /// \param T The type to which we'll be building a pointer.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// pointer type or, if there is no such entity, the location of the
- /// type that will have pointer type.
- ///
- /// \param Entity The name of the entity that involves the pointer
- /// type, if known.
- ///
- /// \returns A suitable pointer type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildPointerType(QualType T,
- SourceLocation Loc, DeclarationName Entity) {
- if (T->isReferenceType()) {
- // C++ 8.3.2p4: There shall be no ... pointers to references ...
- Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
- // In ARC, it is forbidden to build pointers to unqualified pointers.
- if (getLangOptions().ObjCAutoRefCount)
- T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
- // Build the pointer type.
- return Context.getPointerType(T);
- }
- /// \brief Build a reference type.
- ///
- /// \param T The type to which we'll be building a reference.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// reference type or, if there is no such entity, the location of the
- /// type that will have reference type.
- ///
- /// \param Entity The name of the entity that involves the reference
- /// type, if known.
- ///
- /// \returns A suitable reference type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
- SourceLocation Loc,
- DeclarationName Entity) {
- assert(Context.getCanonicalType(T) != Context.OverloadTy &&
- "Unresolved overloaded function type");
-
- // C++0x [dcl.ref]p6:
- // If a typedef (7.1.3), a type template-parameter (14.3.1), or a
- // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a
- // type T, an attempt to create the type "lvalue reference to cv TR" creates
- // the type "lvalue reference to T", while an attempt to create the type
- // "rvalue reference to cv TR" creates the type TR.
- bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
- // C++ [dcl.ref]p4: There shall be no references to references.
- //
- // According to C++ DR 106, references to references are only
- // diagnosed when they are written directly (e.g., "int & &"),
- // but not when they happen via a typedef:
- //
- // typedef int& intref;
- // typedef intref& intref2;
- //
- // Parser::ParseDeclaratorInternal diagnoses the case where
- // references are written directly; here, we handle the
- // collapsing of references-to-references as described in C++0x.
- // DR 106 and 540 introduce reference-collapsing into C++98/03.
- // C++ [dcl.ref]p1:
- // A declarator that specifies the type "reference to cv void"
- // is ill-formed.
- if (T->isVoidType()) {
- Diag(Loc, diag::err_reference_to_void);
- return QualType();
- }
- // In ARC, it is forbidden to build references to unqualified pointers.
- if (getLangOptions().ObjCAutoRefCount)
- T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
- // Handle restrict on references.
- if (LValueRef)
- return Context.getLValueReferenceType(T, SpelledAsLValue);
- return Context.getRValueReferenceType(T);
- }
- /// Check whether the specified array size makes the array type a VLA. If so,
- /// return true, if not, return the size of the array in SizeVal.
- static bool isArraySizeVLA(Expr *ArraySize, llvm::APSInt &SizeVal, Sema &S) {
- // If the size is an ICE, it certainly isn't a VLA.
- if (ArraySize->isIntegerConstantExpr(SizeVal, S.Context))
- return false;
-
- // If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable
- // value as an extension.
- if (S.LangOpts.GNUMode && ArraySize->EvaluateAsInt(SizeVal, S.Context)) {
- S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
- return false;
- }
- return true;
- }
- /// \brief Build an array type.
- ///
- /// \param T The type of each element in the array.
- ///
- /// \param ASM C99 array size modifier (e.g., '*', 'static').
- ///
- /// \param ArraySize Expression describing the size of the array.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// array type or, if there is no such entity, the location of the
- /// type that will have array type.
- ///
- /// \param Entity The name of the entity that involves the array
- /// type, if known.
- ///
- /// \returns A suitable array type, if there are no errors. Otherwise,
- /// returns a NULL type.
- QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
- Expr *ArraySize, unsigned Quals,
- SourceRange Brackets, DeclarationName Entity) {
- SourceLocation Loc = Brackets.getBegin();
- if (getLangOptions().CPlusPlus) {
- // C++ [dcl.array]p1:
- // T is called the array element type; this type shall not be a reference
- // type, the (possibly cv-qualified) type void, a function type or an
- // abstract class type.
- //
- // Note: function types are handled in the common path with C.
- if (T->isReferenceType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_references)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
-
- if (T->isVoidType()) {
- Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
- return QualType();
- }
-
- if (RequireNonAbstractType(Brackets.getBegin(), T,
- diag::err_array_of_abstract_type))
- return QualType();
-
- } else {
- // C99 6.7.5.2p1: If the element type is an incomplete or function type,
- // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- if (RequireCompleteType(Loc, T,
- diag::err_illegal_decl_array_incomplete_type))
- return QualType();
- }
- if (T->isFunctionType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_functions)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- if (T->getContainedAutoType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_auto)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
- if (const RecordType *EltTy = T->getAs<RecordType>()) {
- // If the element type is a struct or union that contains a variadic
- // array, accept it as a GNU extension: C99 6.7.2.1p2.
- if (EltTy->getDecl()->hasFlexibleArrayMember())
- Diag(Loc, diag::ext_flexible_array_in_array) << T;
- } else if (T->isObjCObjectType()) {
- Diag(Loc, diag::err_objc_array_of_interfaces) << T;
- return QualType();
- }
- // Do lvalue-to-rvalue conversions on the array size expression.
- if (ArraySize && !ArraySize->isRValue()) {
- ExprResult Result = DefaultLvalueConversion(ArraySize);
- if (Result.isInvalid())
- return QualType();
- ArraySize = Result.take();
- }
- // C99 6.7.5.2p1: The size expression shall have integer type.
- // TODO: in theory, if we were insane, we could allow contextual
- // conversions to integer type here.
- if (ArraySize && !ArraySize->isTypeDependent() &&
- !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
- Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
- << ArraySize->getType() << ArraySize->getSourceRange();
- return QualType();
- }
- llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
- if (!ArraySize) {
- if (ASM == ArrayType::Star)
- T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
- else
- T = Context.getIncompleteArrayType(T, ASM, Quals);
- } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
- T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else if (!T->isDependentType() && !T->isIncompleteType() &&
- !T->isConstantSizeType()) {
- // C99: an array with an element type that has a non-constant-size is a VLA.
- T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else if (isArraySizeVLA(ArraySize, ConstVal, *this)) {
- // C99: an array with a non-ICE size is a VLA. We accept any expression
- // that we can fold to a non-zero positive value as an extension.
- T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else {
- // C99 6.7.5.2p1: If the expression is a constant expression, it shall
- // have a value greater than zero.
- if (ConstVal.isSigned() && ConstVal.isNegative()) {
- if (Entity)
- Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
- << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
- else
- Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange();
- return QualType();
- }
- if (ConstVal == 0) {
- // GCC accepts zero sized static arrays. We allow them when
- // we're not in a SFINAE context.
- Diag(ArraySize->getLocStart(),
- isSFINAEContext()? diag::err_typecheck_zero_array_size
- : diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
- if (ASM == ArrayType::Static) {
- Diag(ArraySize->getLocStart(),
- diag::warn_typecheck_zero_static_array_size)
- << ArraySize->getSourceRange();
- ASM = ArrayType::Normal;
- }
- } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType()) {
- // Is the array too large?
- unsigned ActiveSizeBits
- = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
- if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
- Diag(ArraySize->getLocStart(), diag::err_array_too_large)
- << ConstVal.toString(10)
- << ArraySize->getSourceRange();
- }
-
- T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
- }
- // If this is not C99, extwarn about VLA's and C99 array size modifiers.
- if (!getLangOptions().C99) {
- if (T->isVariableArrayType()) {
- // Prohibit the use of non-POD types in VLAs.
- QualType BaseT = Context.getBaseElementType(T);
- if (!T->isDependentType() &&
- !BaseT.isPODType(Context) &&
- !BaseT->isObjCLifetimeType()) {
- Diag(Loc, diag::err_vla_non_pod)
- << BaseT;
- return QualType();
- }
- // Prohibit the use of VLAs during template argument deduction.
- else if (isSFINAEContext()) {
- Diag(Loc, diag::err_vla_in_sfinae);
- return QualType();
- }
- // Just extwarn about VLAs.
- else
- Diag(Loc, diag::ext_vla);
- } else if (ASM != ArrayType::Normal || Quals != 0)
- Diag(Loc,
- getLangOptions().CPlusPlus? diag::err_c99_array_usage_cxx
- : diag::ext_c99_array_usage) << ASM;
- }
- return T;
- }
- /// \brief Build an ext-vector type.
- ///
- /// Run the required checks for the extended vector type.
- QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
- SourceLocation AttrLoc) {
- // unlike gcc's vector_size attribute, we do not allow vectors to be defined
- // in conjunction with complex types (pointers, arrays, functions, etc.).
- if (!T->isDependentType() &&
- !T->isIntegerType() && !T->isRealFloatingType()) {
- Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
- return QualType();
- }
- if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
- llvm::APSInt vecSize(32);
- if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
- Diag(AttrLoc, diag::err_attribute_argument_not_int)
- << "ext_vector_type" << ArraySize->getSourceRange();
- return QualType();
- }
- // unlike gcc's vector_size attribute, the size is specified as the
- // number of elements, not the number of bytes.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
- if (vectorSize == 0) {
- Diag(AttrLoc, diag::err_attribute_zero_size)
- << ArraySize->getSourceRange();
- return QualType();
- }
- return Context.getExtVectorType(T, vectorSize);
- }
- return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
- }
- /// \brief Build a function type.
- ///
- /// This routine checks the function type according to C++ rules and
- /// under the assumption that the result type and parameter types have
- /// just been instantiated from a template. It therefore duplicates
- /// some of the behavior of GetTypeForDeclarator, but in a much
- /// simpler form that is only suitable for this narrow use case.
- ///
- /// \param T The return type of the function.
- ///
- /// \param ParamTypes The parameter types of the function. This array
- /// will be modified to account for adjustments to the types of the
- /// function parameters.
- ///
- /// \param NumParamTypes The number of parameter types in ParamTypes.
- ///
- /// \param Variadic Whether this is a variadic function type.
- ///
- /// \param Quals The cvr-qualifiers to be applied to the function type.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// function type or, if there is no such entity, the location of the
- /// type that will have function type.
- ///
- /// \param Entity The name of the entity that involves the function
- /// type, if known.
- ///
- /// \returns A suitable function type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildFunctionType(QualType T,
- QualType *ParamTypes,
- unsigned NumParamTypes,
- bool Variadic, unsigned Quals,
- RefQualifierKind RefQualifier,
- SourceLocation Loc, DeclarationName Entity,
- FunctionType::ExtInfo Info) {
- if (T->isArrayType() || T->isFunctionType()) {
- Diag(Loc, diag::err_func_returning_array_function)
- << T->isFunctionType() << T;
- return QualType();
- }
- // Functions cannot return half FP.
- if (T->isHalfType()) {
- Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
- FixItHint::CreateInsertion(Loc, "*");
- return QualType();
- }
- bool Invalid = false;
- for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
- // FIXME: Loc is too inprecise here, should use proper locations for args.
- QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
- if (ParamType->isVoidType()) {
- Diag(Loc, diag::err_param_with_void_type);
- Invalid = true;
- } else if (ParamType->isHalfType()) {
- // Disallow half FP arguments.
- Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
- FixItHint::CreateInsertion(Loc, "*");
- Invalid = true;
- }
- ParamTypes[Idx] = ParamType;
- }
- if (Invalid)
- return QualType();
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.Variadic = Variadic;
- EPI.TypeQuals = Quals;
- EPI.RefQualifier = RefQualifier;
- EPI.ExtInfo = Info;
- return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
- }
- /// \brief Build a member pointer type \c T Class::*.
- ///
- /// \param T the type to which the member pointer refers.
- /// \param Class the class type into which the member pointer points.
- /// \param CVR Qualifiers applied to the member pointer type
- /// \param Loc the location where this type begins
- /// \param Entity the name of the entity that will have this member pointer type
- ///
- /// \returns a member pointer type, if successful, or a NULL type if there was
- /// an error.
- QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
- SourceLocation Loc,
- DeclarationName Entity) {
- // Verify that we're not building a pointer to pointer to function with
- // exception specification.
- if (CheckDistantExceptionSpec(T)) {
- Diag(Loc, diag::err_distant_exception_spec);
- // FIXME: If we're doing this as part of template instantiation,
- // we should return immediately.
- // Build the type anyway, but use the canonical type so that the
- // exception specifiers are stripped off.
- T = Context.getCanonicalType(T);
- }
- // C++ 8.3.3p3: A pointer to member shall not point to ... a member
- // with reference type, or "cv void."
- if (T->isReferenceType()) {
- Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
- << (Entity? Entity.getAsString() : "type name") << T;
- return QualType();
- }
- if (T->isVoidType()) {
- Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
- << (Entity? Entity.getAsString() : "type name");
- return QualType();
- }
- if (!Class->isDependentType() && !Class->isRecordType()) {
- Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
- return QualType();
- }
- // In the Microsoft ABI, the class is allowed to be an incomplete
- // type. In such cases, the compiler makes a worst-case assumption.
- // We make no such assumption right now, so emit an error if the
- // class isn't a complete type.
- if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
- RequireCompleteType(Loc, Class, diag::err_incomplete_type))
- return QualType();
- return Context.getMemberPointerType(T, Class.getTypePtr());
- }
- /// \brief Build a block pointer type.
- ///
- /// \param T The type to which we'll be building a block pointer.
- ///
- /// \param CVR The cvr-qualifiers to be applied to the block pointer type.
- ///
- /// \param Loc The location of the entity whose type involves this
- /// block pointer type or, if there is no such entity, the location of the
- /// type that will have block pointer type.
- ///
- /// \param Entity The name of the entity that involves the block pointer
- /// type, if known.
- ///
- /// \returns A suitable block pointer type, if there are no
- /// errors. Otherwise, returns a NULL type.
- QualType Sema::BuildBlockPointerType(QualType T,
- SourceLocation Loc,
- DeclarationName Entity) {
- if (!T->isFunctionType()) {
- Diag(Loc, diag::err_nonfunction_block_type);
- return QualType();
- }
- return Context.getBlockPointerType(T);
- }
- QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
- QualType QT = Ty.get();
- if (QT.isNull()) {
- if (TInfo) *TInfo = 0;
- return QualType();
- }
- TypeSourceInfo *DI = 0;
- if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
- QT = LIT->getType();
- DI = LIT->getTypeSourceInfo();
- }
- if (TInfo) *TInfo = DI;
- return QT;
- }
- static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
- Qualifiers::ObjCLifetime ownership,
- unsigned chunkIndex);
- /// Given that this is the declaration of a parameter under ARC,
- /// attempt to infer attributes and such for pointer-to-whatever
- /// types.
- static void inferARCWriteback(TypeProcessingState &state,
- QualType &declSpecType) {
- Sema &S = state.getSema();
- Declarator &declarator = state.getDeclarator();
- // TODO: should we care about decl qualifiers?
- // Check whether the declarator has the expected form. We walk
- // from the inside out in order to make the block logic work.
- unsigned outermostPointerIndex = 0;
- bool isBlockPointer = false;
- unsigned numPointers = 0;
- for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
- unsigned chunkIndex = i;
- DeclaratorChunk &chunk = declarator.getTypeObject(chunkIndex);
- switch (chunk.Kind) {
- case DeclaratorChunk::Paren:
- // Ignore parens.
- break;
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Pointer:
- // Count the number of pointers. Treat references
- // interchangeably as pointers; if they're mis-ordered, normal
- // type building will discover that.
- outermostPointerIndex = chunkIndex;
- numPointers++;
- break;
- case DeclaratorChunk::BlockPointer:
- // If we have a pointer to block pointer, that's an acceptable
- // indirect reference; anything else is not an application of
- // the rules.
- if (numPointers != 1) return;
- numPointers++;
- outermostPointerIndex = chunkIndex;
- isBlockPointer = true;
- // We don't care about pointer structure in return values here.
- goto done;
- case DeclaratorChunk::Array: // suppress if written (id[])?
- case DeclaratorChunk::Function:
- case DeclaratorChunk::MemberPointer:
- return;
- }
- }
- done:
- // If we have *one* pointer, then we want to throw the qualifier on
- // the declaration-specifiers, which means that it needs to be a
- // retainable object type.
- if (numPointers == 1) {
- // If it's not a retainable object type, the rule doesn't apply.
- if (!declSpecType->isObjCRetainableType()) return;
- // If it already has lifetime, don't do anything.
- if (declSpecType.getObjCLifetime()) return;
- // Otherwise, modify the type in-place.
- Qualifiers qs;
-
- if (declSpecType->isObjCARCImplicitlyUnretainedType())
- qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
- else
- qs.addObjCLifetime(Qualifiers::OCL_Autoreleasing);
- declSpecType = S.Context.getQualifiedType(declSpecType, qs);
- // If we have *two* pointers, then we want to throw the qualifier on
- // the outermost pointer.
- } else if (numPointers == 2) {
- // If we don't have a block pointer, we need to check whether the
- // declaration-specifiers gave us something that will turn into a
- // retainable object pointer after we slap the first pointer on it.
- if (!isBlockPointer && !declSpecType->isObjCObjectType())
- return;
- // Look for an explicit lifetime attribute there.
- DeclaratorChunk &chunk = declarator.getTypeObject(outermostPointerIndex);
- if (chunk.Kind != DeclaratorChunk::Pointer &&
- chunk.Kind != DeclaratorChunk::BlockPointer)
- return;
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_objc_ownership)
- return;
- transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
- outermostPointerIndex);
- // Any other number of pointers/references does not trigger the rule.
- } else return;
- // TODO: mark whether we did this inference?
- }
- static void DiagnoseIgnoredQualifiers(unsigned Quals,
- SourceLocation ConstQualLoc,
- SourceLocation VolatileQualLoc,
- SourceLocation RestrictQualLoc,
- Sema& S) {
- std::string QualStr;
- unsigned NumQuals = 0;
- SourceLocation Loc;
- FixItHint ConstFixIt;
- FixItHint VolatileFixIt;
- FixItHint RestrictFixIt;
- const SourceManager &SM = S.getSourceManager();
- // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to
- // find a range and grow it to encompass all the qualifiers, regardless of
- // the order in which they textually appear.
- if (Quals & Qualifiers::Const) {
- ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
- QualStr = "const";
- ++NumQuals;
- if (!Loc.isValid() || SM.isBeforeInTranslationUnit(ConstQualLoc, Loc))
- Loc = ConstQualLoc;
- }
- if (Quals & Qualifiers::Volatile) {
- VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
- QualStr += (NumQuals == 0 ? "volatile" : " volatile");
- ++NumQuals;
- if (!Loc.isValid() || SM.isBeforeInTranslationUnit(VolatileQualLoc, Loc))
- Loc = VolatileQualLoc;
- }
- if (Quals & Qualifiers::Restrict) {
- RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
- QualStr += (NumQuals == 0 ? "restrict" : " restrict");
- ++NumQuals;
- if (!Loc.isValid() || SM.isBeforeInTranslationUnit(RestrictQualLoc, Loc))
- Loc = RestrictQualLoc;
- }
- assert(NumQuals > 0 && "No known qualifiers?");
- S.Diag(Loc, diag::warn_qual_return_type)
- << QualStr << NumQuals << ConstFixIt << VolatileFixIt << RestrictFixIt;
- }
- static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
- TypeSourceInfo *&ReturnTypeInfo) {
- Sema &SemaRef = state.getSema();
- Declarator &D = state.getDeclarator();
- QualType T;
- ReturnTypeInfo = 0;
- // The TagDecl owned by the DeclSpec.
- TagDecl *OwnedTagDecl = 0;
- switch (D.getName().getKind()) {
- case UnqualifiedId::IK_ImplicitSelfParam:
- case UnqualifiedId::IK_OperatorFunctionId:
- case UnqualifiedId::IK_Identifier:
- case UnqualifiedId::IK_LiteralOperatorId:
- case UnqualifiedId::IK_TemplateId:
- T = ConvertDeclSpecToType(state);
-
- if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
- OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- // Owned declaration is embedded in declarator.
- OwnedTagDecl->setEmbeddedInDeclarator(true);
- }
- break;
- case UnqualifiedId::IK_ConstructorName:
- case UnqualifiedId::IK_ConstructorTemplateId:
- case UnqualifiedId::IK_DestructorName:
- // Constructors and destructors don't have return types. Use
- // "void" instead.
- T = SemaRef.Context.VoidTy;
- break;
- case UnqualifiedId::IK_ConversionFunctionId:
- // The result type of a conversion function is the type that it
- // converts to.
- T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
- &ReturnTypeInfo);
- break;
- }
- if (D.getAttributes())
- distributeTypeAttrsFromDeclarator(state, T);
- // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- // In C++0x, a function declarator using 'auto' must have a trailing return
- // type (this is checked later) and we can skip this. In other languages
- // using auto, we need to check regardless.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- (!SemaRef.getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) {
- int Error = -1;
- switch (D.getContext()) {
- case Declarator::KNRTypeListContext:
- llvm_unreachable("K&R type lists aren't allowed in C++");
- break;
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::PrototypeContext:
- Error = 0; // Function prototype
- break;
- case Declarator::MemberContext:
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
- break;
- switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
- case TTK_Enum: llvm_unreachable("unhandled tag kind");
- case TTK_Struct: Error = 1; /* Struct member */ break;
- case TTK_Union: Error = 2; /* Union member */ break;
- case TTK_Class: Error = 3; /* Class member */ break;
- }
- break;
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- Error = 4; // Exception declaration
- break;
- case Declarator::TemplateParamContext:
- Error = 5; // Template parameter
- break;
- case Declarator::BlockLiteralContext:
- Error = 6; // Block literal
- break;
- case Declarator::TemplateTypeArgContext:
- Error = 7; // Template type argument
- break;
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
- Error = 9; // Type alias
- break;
- case Declarator::TypeNameContext:
- Error = 11; // Generic
- break;
- case Declarator::FileContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::ConditionContext:
- case Declarator::CXXNewContext:
- break;
- }
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- Error = 8;
- // In Objective-C it is an error to use 'auto' on a function declarator.
- if (D.isFunctionDeclarator())
- Error = 10;
- // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator
- // contains a trailing return type. That is only legal at the outermost
- // level. Check all declarator chunks (outermost first) anyway, to give
- // better diagnostics.
- if (SemaRef.getLangOptions().CPlusPlus0x && Error != -1) {
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- unsigned chunkIndex = e - i - 1;
- state.setCurrentChunkIndex(chunkIndex);
- DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- if (DeclType.Kind == DeclaratorChunk::Function) {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (FTI.TrailingReturnType) {
- Error = -1;
- break;
- }
- }
- }
- }
- if (Error != -1) {
- SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_auto_not_allowed)
- << Error;
- T = SemaRef.Context.IntTy;
- D.setInvalidType(true);
- } else
- SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::warn_cxx98_compat_auto_type_specifier);
- }
- if (SemaRef.getLangOptions().CPlusPlus &&
- OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
- // Check the contexts where C++ forbids the declaration of a new class
- // or enumeration in a type-specifier-seq.
- switch (D.getContext()) {
- case Declarator::FileContext:
- case Declarator::MemberContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::BlockLiteralContext:
- // C++0x [dcl.type]p3:
- // A type-specifier-seq shall not define a class or enumeration unless
- // it appears in the type-id of an alias-declaration (7.1.3) that is not
- // the declaration of a template-declaration.
- case Declarator::AliasDeclContext:
- break;
- case Declarator::AliasTemplateContext:
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_alias_template)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- break;
- case Declarator::TypeNameContext:
- case Declarator::TemplateParamContext:
- case Declarator::CXXNewContext:
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- case Declarator::TemplateTypeArgContext:
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_type_specifier)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- break;
- case Declarator::PrototypeContext:
- case Declarator::ObjCParameterContext:
- case Declarator::ObjCResultContext:
- case Declarator::KNRTypeListContext:
- // C++ [dcl.fct]p6:
- // Types shall not be defined in return or parameter types.
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_param_type)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- break;
- case Declarator::ConditionContext:
- // C++ 6.4p2:
- // The type-specifier-seq shall not contain typedef and shall not declare
- // a new class or enumeration.
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_condition);
- break;
- }
- }
- return T;
- }
- static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
- QualType declSpecType,
- TypeSourceInfo *TInfo) {
- QualType T = declSpecType;
- Declarator &D = state.getDeclarator();
- Sema &S = state.getSema();
- ASTContext &Context = S.Context;
- const LangOptions &LangOpts = S.getLangOptions();
- bool ImplicitlyNoexcept = false;
- if (D.getName().getKind() == UnqualifiedId::IK_OperatorFunctionId &&
- LangOpts.CPlusPlus0x) {
- OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator;
- /// In C++0x, deallocation functions (normal and array operator delete)
- /// are implicitly noexcept.
- if (OO == OO_Delete || OO == OO_Array_Delete)
- ImplicitlyNoexcept = true;
- }
- // The name we're declaring, if any.
- DeclarationName Name;
- if (D.getIdentifier())
- Name = D.getIdentifier();
- // Does this declaration declare a typedef-name?
- bool IsTypedefName =
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
- D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext;
- // Walk the DeclTypeInfo, building the recursive type as we go.
- // DeclTypeInfos are ordered from the identifier out, which is
- // opposite of what we want :).
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- unsigned chunkIndex = e - i - 1;
- state.setCurrentChunkIndex(chunkIndex);
- DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
- switch (DeclType.Kind) {
- default: llvm_unreachable("Unknown decltype!");
- case DeclaratorChunk::Paren:
- T = S.BuildParenType(T);
- break;
- case DeclaratorChunk::BlockPointer:
- // If blocks are disabled, emit an error.
- if (!LangOpts.Blocks)
- S.Diag(DeclType.Loc, diag::err_blocks_disable);
- T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
- if (DeclType.Cls.TypeQuals)
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
- break;
- case DeclaratorChunk::Pointer:
- // Verify that we're not building a pointer to pointer to function with
- // exception specification.
- if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
- S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
- if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
- T = Context.getObjCObjectPointerType(T);
- if (DeclType.Ptr.TypeQuals)
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
- break;
- }
- T = S.BuildPointerType(T, DeclType.Loc, Name);
- if (DeclType.Ptr.TypeQuals)
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
- break;
- case DeclaratorChunk::Reference: {
- // Verify that we're not building a reference to pointer to function with
- // exception specification.
- if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
- S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
- T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
- Qualifiers Quals;
- if (DeclType.Ref.HasRestrict)
- T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
- break;
- }
- case DeclaratorChunk::Array: {
- // Verify that we're not building an array of pointers to function with
- // exception specification.
- if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
- S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
- DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
- Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
- ArrayType::ArraySizeModifier ASM;
- if (ATI.isStar)
- ASM = ArrayType::Star;
- else if (ATI.hasStatic)
- ASM = ArrayType::Static;
- else
- ASM = ArrayType::Normal;
- if (ASM == ArrayType::Star && !D.isPrototypeContext()) {
- // FIXME: This check isn't quite right: it allows star in prototypes
- // for function definitions, and disallows some edge cases detailed
- // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
- S.Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
- ASM = ArrayType::Normal;
- D.setInvalidType(true);
- }
- T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
- SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
- break;
- }
- case DeclaratorChunk::Function: {
- // If the function declarator has a prototype (i.e. it is not () and
- // does not have a K&R-style identifier list), then the arguments are part
- // of the type, otherwise the argument list is ().
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- // Check for auto functions and trailing return type and adjust the
- // return type accordingly.
- if (!D.isInvalidType()) {
- // trailing-return-type is only required if we're declaring a function,
- // and not, for instance, a pointer to a function.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- !FTI.TrailingReturnType && chunkIndex == 0) {
- S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_auto_missing_trailing_return);
- T = Context.IntTy;
- D.setInvalidType(true);
- } else if (FTI.TrailingReturnType) {
- // T must be exactly 'auto' at this point. See CWG issue 681.
- if (isa<ParenType>(T)) {
- S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_trailing_return_in_parens)
- << T << D.getDeclSpec().getSourceRange();
- D.setInvalidType(true);
- } else if (T.hasQualifiers() || !isa<AutoType>(T)) {
- S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_trailing_return_without_auto)
- << T << D.getDeclSpec().getSourceRange();
- D.setInvalidType(true);
- }
- T = S.GetTypeFromParser(
- ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
- &TInfo);
- }
- }
- // C99 6.7.5.3p1: The return type may not be a function or array type.
- // For conversion functions, we'll diagnose this particular error later.
- if ((T->isArrayType() || T->isFunctionType()) &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
- unsigned diagID = diag::err_func_returning_array_function;
- // Last processing chunk in block context means this function chunk
- // represents the block.
- if (chunkIndex == 0 &&
- D.getContext() == Declarator::BlockLiteralContext)
- diagID = diag::err_block_returning_array_function;
- S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
- T = Context.IntTy;
- D.setInvalidType(true);
- }
- // Do not allow returning half FP value.
- // FIXME: This really should be in BuildFunctionType.
- if (T->isHalfType()) {
- S.Diag(D.getIdentifierLoc(),
- diag::err_parameters_retval_cannot_have_fp16_type) << 1
- << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
- D.setInvalidType(true);
- }
- // cv-qualifiers on return types are pointless except when the type is a
- // class type in C++.
- if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) &&
- (!LangOpts.CPlusPlus || !T->isDependentType())) {
- assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
- DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
- assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
- DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
- DiagnoseIgnoredQualifiers(PTI.TypeQuals,
- SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
- SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
- SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
- S);
- } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
- (!LangOpts.CPlusPlus ||
- (!T->isDependentType() && !T->isRecordType()))) {
- DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
- D.getDeclSpec().getConstSpecLoc(),
- D.getDeclSpec().getVolatileSpecLoc(),
- D.getDeclSpec().getRestrictSpecLoc(),
- S);
- }
- if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
- // C++ [dcl.fct]p6:
- // Types shall not be defined in return or parameter types.
- TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- if (Tag->isCompleteDefinition())
- S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
- << Context.getTypeDeclType(Tag);
- }
- // Exception specs are not allowed in typedefs. Complain, but add it
- // anyway.
- if (IsTypedefName && FTI.getExceptionSpecType())
- S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
- << (D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext);
- if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
- // Simple void foo(), where the incoming T is the result type.
- T = Context.getFunctionNoProtoType(T);
- } else {
- // We allow a zero-parameter variadic function in C if the
- // function is marked with the "overloadable" attribute. Scan
- // for this attribute now.
- if (!FTI.NumArgs && FTI.isVariadic && !LangOpts.CPlusPlus) {
- bool Overloadable = false;
- for (const AttributeList *Attrs = D.getAttributes();
- Attrs; Attrs = Attrs->getNext()) {
- if (Attrs->getKind() == AttributeList::AT_overloadable) {
- Overloadable = true;
- break;
- }
- }
- if (!Overloadable)
- S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
- }
- if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
- // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
- // definition.
- S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
- D.setInvalidType(true);
- break;
- }
- FunctionProtoType::ExtProtoInfo EPI;
- EPI.Variadic = FTI.isVariadic;
- EPI.TypeQuals = FTI.TypeQuals;
- EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
- : FTI.RefQualifierIsLValueRef? RQ_LValue
- : RQ_RValue;
-
- // Otherwise, we have a function with an argument list that is
- // potentially variadic.
- SmallVector<QualType, 16> ArgTys;
- ArgTys.reserve(FTI.NumArgs);
- SmallVector<bool, 16> ConsumedArguments;
- ConsumedArguments.reserve(FTI.NumArgs);
- bool HasAnyConsumedArguments = false;
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
- QualType ArgTy = Param->getType();
- assert(!ArgTy.isNull() && "Couldn't parse type?");
- // Adjust the parameter type.
- assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
- "Unadjusted type?");
- // Look for 'void'. void is allowed only as a single argument to a
- // function with no other parameters (C99 6.7.5.3p10). We record
- // int(void) as a FunctionProtoType with an empty argument list.
- if (ArgTy->isVoidType()) {
- // If this is something like 'float(int, void)', reject it. 'void'
- // is an incomplete type (C99 6.2.5p19) and function decls cannot
- // have arguments of incomplete type.
- if (FTI.NumArgs != 1 || FTI.isVariadic) {
- S.Diag(DeclType.Loc, diag::err_void_only_param);
- ArgTy = Context.IntTy;
- Param->setType(ArgTy);
- } else if (FTI.ArgInfo[i].Ident) {
- // Reject, but continue to parse 'int(void abc)'.
- S.Diag(FTI.ArgInfo[i].IdentLoc,
- diag::err_param_with_void_type);
- ArgTy = Context.IntTy;
- Param->setType(ArgTy);
- } else {
- // Reject, but continue to parse 'float(const void)'.
- if (ArgTy.hasQualifiers())
- S.Diag(DeclType.Loc, diag::err_void_param_qualified);
- // Do not add 'void' to the ArgTys list.
- break;
- }
- } else if (ArgTy->isHalfType()) {
- // Disallow half FP arguments.
- // FIXME: This really should be in BuildFunctionType.
- S.Diag(Param->getLocation(),
- diag::err_parameters_retval_cannot_have_fp16_type) << 0
- << FixItHint::CreateInsertion(Param->getLocation(), "*");
- D.setInvalidType();
- } else if (!FTI.hasPrototype) {
- if (ArgTy->isPromotableIntegerType()) {
- ArgTy = Context.getPromotedIntegerType(ArgTy);
- Param->setKNRPromoted(true);
- } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
- if (BTy->getKind() == BuiltinType::Float) {
- ArgTy = Context.DoubleTy;
- Param->setKNRPromoted(true);
- }
- }
- }
- if (LangOpts.ObjCAutoRefCount) {
- bool Consumed = Param->hasAttr<NSConsumedAttr>();
- ConsumedArguments.push_back(Consumed);
- HasAnyConsumedArguments |= Consumed;
- }
- ArgTys.push_back(ArgTy);
- }
- if (HasAnyConsumedArguments)
- EPI.ConsumedArguments = ConsumedArguments.data();
- SmallVector<QualType, 4> Exceptions;
- EPI.ExceptionSpecType = FTI.getExceptionSpecType();
- if (FTI.getExceptionSpecType() == EST_Dynamic) {
- Exceptions.reserve(FTI.NumExceptions);
- for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
- // FIXME: Preserve type source info.
- QualType ET = S.GetTypeFromParser(FTI.Exceptions[ei].Ty);
- // Check that the type is valid for an exception spec, and
- // drop it if not.
- if (!S.CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
- Exceptions.push_back(ET);
- }
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
- } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
- // If an error occurred, there's no expression here.
- if (Expr *NoexceptExpr = FTI.NoexceptExpr) {
- assert((NoexceptExpr->isTypeDependent() ||
- NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
- Context.BoolTy) &&
- "Parser should have made sure that the expression is boolean");
- SourceLocation ErrLoc;
- llvm::APSInt Dummy;
- if (!NoexceptExpr->isValueDependent() &&
- !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc,
- /*evaluated*/false))
- S.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression)
- << NoexceptExpr->getSourceRange();
- else
- EPI.NoexceptExpr = NoexceptExpr;
- }
- } else if (FTI.getExceptionSpecType() == EST_None &&
- ImplicitlyNoexcept && chunkIndex == 0) {
- // Only the outermost chunk is marked noexcept, of course.
- EPI.ExceptionSpecType = EST_BasicNoexcept;
- }
- T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
- }
- break;
- }
- case DeclaratorChunk::MemberPointer:
- // The scope spec must refer to a class, or be dependent.
- CXXScopeSpec &SS = DeclType.Mem.Scope();
- QualType ClsType;
- if (SS.isInvalid()) {
- // Avoid emitting extra errors if we already errored on the scope.
- D.setInvalidType(true);
- } else if (S.isDependentScopeSpecifier(SS) ||
- dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
- NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
- NNS->getAsIdentifier());
- break;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- llvm_unreachable("Nested-name-specifier must name a type");
- break;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- ClsType = QualType(NNS->getAsType(), 0);
- // Note: if the NNS has a prefix and ClsType is a nondependent
- // TemplateSpecializationType, then the NNS prefix is NOT included
- // in ClsType; hence we wrap ClsType into an ElaboratedType.
- // NOTE: in particular, no wrap occurs if ClsType already is an
- // Elaborated, DependentName, or DependentTemplateSpecialization.
- if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
- ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
- break;
- }
- } else {
- S.Diag(DeclType.Mem.Scope().getBeginLoc(),
- diag::err_illegal_decl_mempointer_in_nonclass)
- << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
- << DeclType.Mem.Scope().getRange();
- D.setInvalidType(true);
- }
- if (!ClsType.isNull())
- T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier());
- if (T.isNull()) {
- T = Context.IntTy;
- D.setInvalidType(true);
- } else if (DeclType.Mem.TypeQuals) {
- T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
- }
- break;
- }
- if (T.isNull()) {
- D.setInvalidType(true);
- T = Context.IntTy;
- }
- // See if there are any attributes on this declarator chunk.
- if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
- processTypeAttrs(state, T, false, attrs);
- }
- if (LangOpts.CPlusPlus && T->isFunctionType()) {
- const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
- assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
- // C++ 8.3.5p4:
- // A cv-qualifier-seq shall only be part of the function type
- // for a nonstatic member function, the function type to which a pointer
- // to member refers, or the top-level function type of a function typedef
- // declaration.
- //
- // Core issue 547 also allows cv-qualifiers on function types that are
- // top-level template type arguments.
- bool FreeFunction;
- if (!D.getCXXScopeSpec().isSet()) {
- FreeFunction = (D.getContext() != Declarator::MemberContext ||
- D.getDeclSpec().isFriendSpecified());
- } else {
- DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
- FreeFunction = (DC && !DC->isRecord());
- }
- // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
- // function that is not a constructor declares that function to be const.
- if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
- D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
- D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId &&
- !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {
- // Rebuild function type adding a 'const' qualifier.
- FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
- EPI.TypeQuals |= DeclSpec::TQ_const;
- T = Context.getFunctionType(FnTy->getResultType(),
- FnTy->arg_type_begin(),
- FnTy->getNumArgs(), EPI);
- }
- // C++0x [dcl.fct]p6:
- // A ref-qualifier shall only be part of the function type for a
- // non-static member function, the function type to which a pointer to
- // member refers, or the top-level function type of a function typedef
- // declaration.
- if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) &&
- !(D.getContext() == Declarator::TemplateTypeArgContext &&
- !D.isFunctionDeclarator()) && !IsTypedefName &&
- (FreeFunction ||
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
- if (D.getContext() == Declarator::TemplateTypeArgContext) {
- // Accept qualified function types as template type arguments as a GNU
- // extension. This is also the subject of C++ core issue 547.
- std::string Quals;
- if (FnTy->getTypeQuals() != 0)
- Quals = Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
-
- switch (FnTy->getRefQualifier()) {
- case RQ_None:
- break;
-
- case RQ_LValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += '&';
- break;
-
- case RQ_RValue:
- if (!Quals.empty())
- Quals += ' ';
- Quals += "&&";
- break;
- }
-
- S.Diag(D.getIdentifierLoc(),
- diag::ext_qualified_function_type_template_arg)
- << Quals;
- } else {
- if (FnTy->getTypeQuals() != 0) {
- if (D.isFunctionDeclarator()) {
- SourceRange Range = D.getIdentifierLoc();
- for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
- const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1);
- if (Chunk.Kind == DeclaratorChunk::Function &&
- Chunk.Fun.TypeQuals != 0) {
- switch (Chunk.Fun.TypeQuals) {
- case Qualifiers::Const:
- Range = Chunk.Fun.getConstQualifierLoc();
- break;
- case Qualifiers::Volatile:
- Range = Chunk.Fun.getVolatileQualifierLoc();
- break;
- case Qualifiers::Const | Qualifiers::Volatile: {
- SourceLocation CLoc = Chunk.Fun.getConstQualifierLoc();
- SourceLocation VLoc = Chunk.Fun.getVolatileQualifierLoc();
- if (S.getSourceManager()
- .isBeforeInTranslationUnit(CLoc, VLoc)) {
- Range = SourceRange(CLoc, VLoc);
- } else {
- Range = SourceRange(VLoc, CLoc);
- }
- }
- break;
- }
- break;
- }
- }
- S.Diag(Range.getBegin(), diag::err_invalid_qualified_function_type)
- << FixItHint::CreateRemoval(Range);
- } else
- S.Diag(D.getIdentifierLoc(),
- diag::err_invalid_qualified_typedef_function_type_use)
- << FreeFunction;
- }
-
- if (FnTy->getRefQualifier()) {
- if (D.isFunctionDeclarator()) {
- SourceLocation Loc = D.getIdentifierLoc();
- for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
- const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1);
- if (Chunk.Kind == DeclaratorChunk::Function &&
- Chunk.Fun.hasRefQualifier()) {
- Loc = Chunk.Fun.getRefQualifierLoc();
- break;
- }
- }
- S.Diag(Loc, diag::err_invalid_ref_qualifier_function_type)
- << (FnTy->getRefQualifier() == RQ_LValue)
- << FixItHint::CreateRemoval(Loc);
- } else {
- S.Diag(D.getIdentifierLoc(),
- diag::err_invalid_ref_qualifier_typedef_function_type_use)
- << FreeFunction
- << (FnTy->getRefQualifier() == RQ_LValue);
- }
- }
-
- // Strip the cv-qualifiers and ref-qualifiers from the type.
- FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
- EPI.TypeQuals = 0;
- EPI.RefQualifier = RQ_None;
-
- T = Context.getFunctionType(FnTy->getResultType(),
- FnTy->arg_type_begin(),
- FnTy->getNumArgs(), EPI);
- }
- }
- }
- // Apply any undistributed attributes from the declarator.
- if (!T.isNull())
- if (AttributeList *attrs = D.getAttributes())
- processTypeAttrs(state, T, false, attrs);
- // Diagnose any ignored type attributes.
- if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
- // C++0x [dcl.constexpr]p9:
- // A constexpr specifier used in an object declaration declares the object
- // as const.
- if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
- T.addConst();
- }
- // If there was an ellipsis in the declarator, the declaration declares a
- // parameter pack whose type may be a pack expansion type.
- if (D.hasEllipsis() && !T.isNull()) {
- // C++0x [dcl.fct]p13:
- // A declarator-id or abstract-declarator containing an ellipsis shall
- // only be used in a parameter-declaration. Such a parameter-declaration
- // is a parameter pack (14.5.3). [...]
- switch (D.getContext()) {
- case Declarator::PrototypeContext:
- // C++0x [dcl.fct]p13:
- // [...] When it is part of a parameter-declaration-clause, the
- // parameter pack is a function parameter pack (14.5.3). The type T
- // of the declarator-id of the function parameter pack shall contain
- // a template parameter pack; each template parameter pack in T is
- // expanded by the function parameter pack.
- //
- // We represent function parameter packs as function parameters whose
- // type is a pack expansion.
- if (!T->containsUnexpandedParameterPack()) {
- S.Diag(D.getEllipsisLoc(),
- diag::err_function_parameter_pack_without_parameter_packs)
- << T << D.getSourceRange();
- D.setEllipsisLoc(SourceLocation());
- } else {
- T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
- }
- break;
-
- case Declarator::TemplateParamContext:
- // C++0x [temp.param]p15:
- // If a template-parameter is a [...] is a parameter-declaration that
- // declares a parameter pack (8.3.5), then the template-parameter is a
- // template parameter pack (14.5.3).
- //
- // Note: core issue 778 clarifies that, if there are any unexpanded
- // parameter packs in the type of the non-type template parameter, then
- // it expands those parameter packs.
- if (T->containsUnexpandedParameterPack())
- T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
- else
- S.Diag(D.getEllipsisLoc(),
- LangOpts.CPlusPlus0x
- ? diag::warn_cxx98_compat_variadic_templates
- : diag::ext_variadic_templates);
- break;
-
- case Declarator::FileContext:
- case Declarator::KNRTypeListContext:
- case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
- case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
- case Declarator::TypeNameContext:
- case Declarator::CXXNewContext:
- case Declarator::AliasDeclContext:
- case Declarator::AliasTemplateContext:
- case Declarator::MemberContext:
- case Declarator::BlockContext:
- case Declarator::ForContext:
- case Declarator::ConditionContext:
- case Declarator::CXXCatchContext:
- case Declarator::ObjCCatchContext:
- case Declarator::BlockLiteralContext:
- case Declarator::TemplateTypeArgContext:
- // FIXME: We may want to allow parameter packs in block-literal contexts
- // in the future.
- S.Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter);
- D.setEllipsisLoc(SourceLocation());
- break;
- }
- }
- if (T.isNull())
- return Context.getNullTypeSourceInfo();
- else if (D.isInvalidType())
- return Context.getTrivialTypeSourceInfo(T);
- return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
- }
- /// GetTypeForDeclarator - Convert the type for the specified
- /// declarator to Type instances.
- ///
- /// The result of this call will never be null, but the associated
- /// type may be a null type if there's an unrecoverable error.
- TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
- // Determine the type of the declarator. Not all forms of declarator
- // have a type.
- TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = 0;
- QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (T.isNull())
- return Context.getNullTypeSourceInfo();
- if (D.isPrototypeContext() && getLangOptions().ObjCAutoRefCount)
- inferARCWriteback(state, T);
-
- return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
- }
- static void transferARCOwnershipToDeclSpec(Sema &S,
- QualType &declSpecTy,
- Qualifiers::ObjCLifetime ownership) {
- if (declSpecTy->isObjCRetainableType() &&
- declSpecTy.getObjCLifetime() == Qualifiers::OCL_None) {
- Qualifiers qs;
- qs.addObjCLifetime(ownership);
- declSpecTy = S.Context.getQualifiedType(declSpecTy, qs);
- }
- }
- static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
- Qualifiers::ObjCLifetime ownership,
- unsigned chunkIndex) {
- Sema &S = state.getSema();
- Declarator &D = state.getDeclarator();
- // Look for an explicit lifetime attribute.
- DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
- for (const AttributeList *attr = chunk.getAttrs(); attr;
- attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_objc_ownership)
- return;
- const char *attrStr = 0;
- switch (ownership) {
- case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break;
- case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
- case Qualifiers::OCL_Strong: attrStr = "strong"; break;
- case Qualifiers::OCL_Weak: attrStr = "weak"; break;
- case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
- }
- // If there wasn't one, add one (with an invalid source location
- // so that we don't make an AttributedType for it).
- AttributeList *attr = D.getAttributePool()
- .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
- /*scope*/ 0, SourceLocation(),
- &S.Context.Idents.get(attrStr), SourceLocation(),
- /*args*/ 0, 0,
- /*declspec*/ false, /*C++0x*/ false);
- spliceAttrIntoList(*attr, chunk.getAttrListRef());
- // TODO: mark whether we did this inference?
- }
- /// \brief Used for transfering ownership in casts resulting in l-values.
- static void transferARCOwnership(TypeProcessingState &state,
- QualType &declSpecTy,
- Qualifiers::ObjCLifetime ownership) {
- Sema &S = state.getSema();
- Declarator &D = state.getDeclarator();
- int inner = -1;
- bool hasIndirection = false;
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- DeclaratorChunk &chunk = D.getTypeObject(i);
- switch (chunk.Kind) {
- case DeclaratorChunk::Paren:
- // Ignore parens.
- break;
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::Pointer:
- if (inner != -1)
- hasIndirection = true;
- inner = i;
- break;
- case DeclaratorChunk::BlockPointer:
- if (inner != -1)
- transferARCOwnershipToDeclaratorChunk(state, ownership, i);
- return;
- case DeclaratorChunk::Function:
- case DeclaratorChunk::MemberPointer:
- return;
- }
- }
- if (inner == -1)
- return;
- DeclaratorChunk &chunk = D.getTypeObject(inner);
- if (chunk.Kind == DeclaratorChunk::Pointer) {
- if (declSpecTy->isObjCRetainableType())
- return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
- if (declSpecTy->isObjCObjectType() && hasIndirection)
- return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
- } else {
- assert(chunk.Kind == DeclaratorChunk::Array ||
- chunk.Kind == DeclaratorChunk::Reference);
- return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
- }
- }
- TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
- TypeProcessingState state(*this, D);
- TypeSourceInfo *ReturnTypeInfo = 0;
- QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (declSpecTy.isNull())
- return Context.getNullTypeSourceInfo();
- if (getLangOptions().ObjCAutoRefCount) {
- Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
- if (ownership != Qualifiers::OCL_None)
- transferARCOwnership(state, declSpecTy, ownership);
- }
- return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
- }
- /// Map an AttributedType::Kind to an AttributeList::Kind.
- static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
- switch (kind) {
- case AttributedType::attr_address_space:
- return AttributeList::AT_address_space;
- case AttributedType::attr_regparm:
- return AttributeList::AT_regparm;
- case AttributedType::attr_vector_size:
- return AttributeList::AT_vector_size;
- case AttributedType::attr_neon_vector_type:
- return AttributeList::AT_neon_vector_type;
- case AttributedType::attr_neon_polyvector_type:
- return AttributeList::AT_neon_polyvector_type;
- case AttributedType::attr_objc_gc:
- return AttributeList::AT_objc_gc;
- case AttributedType::attr_objc_ownership:
- return AttributeList::AT_objc_ownership;
- case AttributedType::attr_noreturn:
- return AttributeList::AT_noreturn;
- case AttributedType::attr_cdecl:
- return AttributeList::AT_cdecl;
- case AttributedType::attr_fastcall:
- return AttributeList::AT_fastcall;
- case AttributedType::attr_stdcall:
- return AttributeList::AT_stdcall;
- case AttributedType::attr_thiscall:
- return AttributeList::AT_thiscall;
- case AttributedType::attr_pascal:
- return AttributeList::AT_pascal;
- case AttributedType::attr_pcs:
- return AttributeList::AT_pcs;
- }
- llvm_unreachable("unexpected attribute kind!");
- return AttributeList::Kind();
- }
- static void fillAttributedTypeLoc(AttributedTypeLoc TL,
- const AttributeList *attrs) {
- AttributedType::Kind kind = TL.getAttrKind();
- assert(attrs && "no type attributes in the expected location!");
- AttributeList::Kind parsedKind = getAttrListKind(kind);
- while (attrs->getKind() != parsedKind) {
- attrs = attrs->getNext();
- assert(attrs && "no matching attribute in expected location!");
- }
- TL.setAttrNameLoc(attrs->getLoc());
- if (TL.hasAttrExprOperand())
- TL.setAttrExprOperand(attrs->getArg(0));
- else if (TL.hasAttrEnumOperand())
- TL.setAttrEnumOperandLoc(attrs->getParameterLoc());
- // FIXME: preserve this information to here.
- if (TL.hasAttrOperand())
- TL.setAttrOperandParensRange(SourceRange());
- }
- namespace {
- class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
- ASTContext &Context;
- const DeclSpec &DS;
- public:
- TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
- : Context(Context), DS(DS) {}
- void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, DS.getAttributes().getList());
- Visit(TL.getModifiedLoc());
- }
- void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
- Visit(TL.getUnqualifiedLoc());
- }
- void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
- }
- void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeLoc());
- }
- void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
- // Handle the base type, which might not have been written explicitly.
- if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
- TL.setHasBaseTypeAsWritten(false);
- TL.getBaseLoc().initialize(Context, SourceLocation());
- } else {
- TL.setHasBaseTypeAsWritten(true);
- Visit(TL.getBaseLoc());
- }
- // Protocol qualifiers.
- if (DS.getProtocolQualifiers()) {
- assert(TL.getNumProtocols() > 0);
- assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
- TL.setLAngleLoc(DS.getProtocolLAngleLoc());
- TL.setRAngleLoc(DS.getSourceRange().getEnd());
- for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
- TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
- } else {
- assert(TL.getNumProtocols() == 0);
- TL.setLAngleLoc(SourceLocation());
- TL.setRAngleLoc(SourceLocation());
- }
- }
- void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
- TL.setStarLoc(SourceLocation());
- Visit(TL.getPointeeLoc());
- }
- void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- // If we got no declarator info from previous Sema routines,
- // just fill with the typespec loc.
- if (!TInfo) {
- TL.initialize(Context, DS.getTypeSpecTypeNameLoc());
- return;
- }
- TypeLoc OldTL = TInfo->getTypeLoc();
- if (TInfo->getType()->getAs<ElaboratedType>()) {
- ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL);
- TemplateSpecializationTypeLoc NamedTL =
- cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc());
- TL.copy(NamedTL);
- }
- else
- TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL));
- }
- void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
- TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- }
- void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
- TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.setUnderlyingTInfo(TInfo);
- }
- void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
- // FIXME: This holds only because we only have one unary transform.
- assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
- TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
- assert(DS.getRepAsType());
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.setUnderlyingTInfo(TInfo);
- }
- void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
- // By default, use the source location of the type specifier.
- TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
- if (TL.needsExtraLocalData()) {
- // Set info for the written builtin specifiers.
- TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
- // Try to have a meaningful source location.
- if (TL.getWrittenSignSpec() != TSS_unspecified)
- // Sign spec loc overrides the others (e.g., 'unsigned long').
- TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
- else if (TL.getWrittenWidthSpec() != TSW_unspecified)
- // Width spec loc overrides type spec loc (e.g., 'short int').
- TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
- }
- }
- void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- ElaboratedTypeKeyword Keyword
- = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
- if (DS.getTypeSpecType() == TST_typename) {
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- if (TInfo) {
- TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
- return;
- }
- }
- TL.setKeywordLoc(Keyword != ETK_None
- ? DS.getTypeSpecTypeLoc()
- : SourceLocation());
- const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
- Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
- }
- void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
- ElaboratedTypeKeyword Keyword
- = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
- if (DS.getTypeSpecType() == TST_typename) {
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- if (TInfo) {
- TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
- return;
- }
- }
- TL.setKeywordLoc(Keyword != ETK_None
- ? DS.getTypeSpecTypeLoc()
- : SourceLocation());
- const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
- TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
- }
- void VisitDependentTemplateSpecializationTypeLoc(
- DependentTemplateSpecializationTypeLoc TL) {
- ElaboratedTypeKeyword Keyword
- = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
- if (Keyword == ETK_Typename) {
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- if (TInfo) {
- TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
- TInfo->getTypeLoc()));
- return;
- }
- }
- TL.initializeLocal(Context, SourceLocation());
- TL.setKeywordLoc(Keyword != ETK_None
- ? DS.getTypeSpecTypeLoc()
- : SourceLocation());
- const CXXScopeSpec& SS = DS.getTypeSpecScope();
- TL.setQualifierLoc(SS.getWithLocInContext(Context));
- TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
- }
- void VisitTagTypeLoc(TagTypeLoc TL) {
- TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
- }
- void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
- TL.setKWLoc(DS.getTypeSpecTypeLoc());
- TL.setParensRange(DS.getTypeofParensRange());
-
- TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
- }
- void VisitTypeLoc(TypeLoc TL) {
- // FIXME: add other typespec types and change this to an assert.
- TL.initialize(Context, DS.getTypeSpecTypeLoc());
- }
- };
- class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
- ASTContext &Context;
- const DeclaratorChunk &Chunk;
- public:
- DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
- : Context(Context), Chunk(Chunk) {}
- void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
- llvm_unreachable("qualified type locs not expected here!");
- }
- void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- fillAttributedTypeLoc(TL, Chunk.getAttrs());
- }
- void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
- TL.setCaretLoc(Chunk.Loc);
- }
- void VisitPointerTypeLoc(PointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Pointer);
- TL.setStarLoc(Chunk.Loc);
- }
- void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Pointer);
- TL.setStarLoc(Chunk.Loc);
- }
- void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
- const CXXScopeSpec& SS = Chunk.Mem.Scope();
- NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
- const Type* ClsTy = TL.getClass();
- QualType ClsQT = QualType(ClsTy, 0);
- TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
- // Now copy source location info into the type loc component.
- TypeLoc ClsTL = ClsTInfo->getTypeLoc();
- switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
- {
- DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL);
- DNTLoc.setKeywordLoc(SourceLocation());
- DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
- DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
- }
- break;
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- if (isa<ElaboratedType>(ClsTy)) {
- ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL);
- ETLoc.setKeywordLoc(SourceLocation());
- ETLoc.setQualifierLoc(NNSLoc.getPrefix());
- TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
- NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
- } else {
- ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
- }
- break;
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- llvm_unreachable("Nested-name-specifier must name a type");
- break;
- }
- // Finally fill in MemberPointerLocInfo fields.
- TL.setStarLoc(Chunk.Loc);
- TL.setClassTInfo(ClsTInfo);
- }
- void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Reference);
- // 'Amp' is misleading: this might have been originally
- /// spelled with AmpAmp.
- TL.setAmpLoc(Chunk.Loc);
- }
- void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Reference);
- assert(!Chunk.Ref.LValueRef);
- TL.setAmpAmpLoc(Chunk.Loc);
- }
- void VisitArrayTypeLoc(ArrayTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Array);
- TL.setLBracketLoc(Chunk.Loc);
- TL.setRBracketLoc(Chunk.EndLoc);
- TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
- }
- void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Function);
- TL.setLocalRangeBegin(Chunk.Loc);
- TL.setLocalRangeEnd(Chunk.EndLoc);
- TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
- const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
- for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
- ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
- TL.setArg(tpi++, Param);
- }
- // FIXME: exception specs
- }
- void VisitParenTypeLoc(ParenTypeLoc TL) {
- assert(Chunk.Kind == DeclaratorChunk::Paren);
- TL.setLParenLoc(Chunk.Loc);
- TL.setRParenLoc(Chunk.EndLoc);
- }
- void VisitTypeLoc(TypeLoc TL) {
- llvm_unreachable("unsupported TypeLoc kind in declarator!");
- }
- };
- }
- /// \brief Create and instantiate a TypeSourceInfo with type source information.
- ///
- /// \param T QualType referring to the type as written in source code.
- ///
- /// \param ReturnTypeInfo For declarators whose return type does not show
- /// up in the normal place in the declaration specifiers (such as a C++
- /// conversion function), this pointer will refer to a type source information
- /// for that return type.
- TypeSourceInfo *
- Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
- TypeSourceInfo *ReturnTypeInfo) {
- TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
- UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
- // Handle parameter packs whose type is a pack expansion.
- if (isa<PackExpansionType>(T)) {
- cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
- CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
- }
-
- for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
- while (isa<AttributedTypeLoc>(CurrTL)) {
- AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL);
- fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
- CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
- }
- DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
- CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
- }
-
- // If we have different source information for the return type, use
- // that. This really only applies to C++ conversion functions.
- if (ReturnTypeInfo) {
- TypeLoc TL = ReturnTypeInfo->getTypeLoc();
- assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
- memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
- } else {
- TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
- }
-
- return TInfo;
- }
- /// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
- ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
- // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
- // and Sema during declaration parsing. Try deallocating/caching them when
- // it's appropriate, instead of allocating them and keeping them around.
- LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
- TypeAlignment);
- new (LocT) LocInfoType(T, TInfo);
- assert(LocT->getTypeClass() != T->getTypeClass() &&
- "LocInfoType's TypeClass conflicts with an existing Type class");
- return ParsedType::make(QualType(LocT, 0));
- }
- void LocInfoType::getAsStringInternal(std::string &Str,
- const PrintingPolicy &Policy) const {
- llvm_unreachable("LocInfoType leaked into the type system; an opaque TypeTy*"
- " was used directly instead of getting the QualType through"
- " GetTypeFromParser");
- }
- TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
- // C99 6.7.6: Type names have no identifier. This is already validated by
- // the parser.
- assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
- TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType T = TInfo->getType();
- if (D.isInvalidType())
- return true;
- // Make sure there are no unused decl attributes on the declarator.
- // We don't want to do this for ObjC parameters because we're going
- // to apply them to the actual parameter declaration.
- if (D.getContext() != Declarator::ObjCParameterContext)
- checkUnusedDeclAttributes(D);
- if (getLangOptions().CPlusPlus) {
- // Check that there are no default arguments (C++ only).
- CheckExtraCXXDefaultArguments(D);
- }
- return CreateParsedType(T, TInfo);
- }
- ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
- QualType T = Context.getObjCInstanceType();
- TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
- return CreateParsedType(T, TInfo);
- }
- //===----------------------------------------------------------------------===//
- // Type Attribute Processing
- //===----------------------------------------------------------------------===//
- /// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
- /// specified type. The attribute contains 1 argument, the id of the address
- /// space for the type.
- static void HandleAddressSpaceTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S){
- // If this type is already address space qualified, reject it.
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
- // qualifiers for two or more different address spaces."
- if (Type.getAddressSpace()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
- Attr.setInvalid();
- return;
- }
- // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
- // qualified by an address-space qualifier."
- if (Type->isFunctionType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type);
- Attr.setInvalid();
- return;
- }
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- Attr.setInvalid();
- return;
- }
- Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
- llvm::APSInt addrSpace(32);
- if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
- !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
- << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // Bounds checking.
- if (addrSpace.isSigned()) {
- if (addrSpace.isNegative()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
- << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- addrSpace.setIsSigned(false);
- }
- llvm::APSInt max(addrSpace.getBitWidth());
- max = Qualifiers::MaxAddressSpace;
- if (addrSpace > max) {
- S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
- Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
- }
- /// handleObjCOwnershipTypeAttr - Process an objc_ownership
- /// attribute on the specified type.
- ///
- /// Returns 'true' if the attribute was handled.
- static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
- bool NonObjCPointer = false;
- if (!type->isDependentType()) {
- if (const PointerType *ptr = type->getAs<PointerType>()) {
- QualType pointee = ptr->getPointeeType();
- if (pointee->isObjCRetainableType() || pointee->isPointerType())
- return false;
- // It is important not to lose the source info that there was an attribute
- // applied to non-objc pointer. We will create an attributed type but
- // its type will be the same as the original type.
- NonObjCPointer = true;
- } else if (!type->isObjCRetainableType()) {
- return false;
- }
- }
- Sema &S = state.getSema();
- SourceLocation AttrLoc = attr.getLoc();
- if (AttrLoc.isMacroID())
- AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
- if (type.getQualifiers().getObjCLifetime()) {
- S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
- << type;
- return true;
- }
- if (!attr.getParameterName()) {
- S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
- << "objc_ownership" << 1;
- attr.setInvalid();
- return true;
- }
- Qualifiers::ObjCLifetime lifetime;
- if (attr.getParameterName()->isStr("none"))
- lifetime = Qualifiers::OCL_ExplicitNone;
- else if (attr.getParameterName()->isStr("strong"))
- lifetime = Qualifiers::OCL_Strong;
- else if (attr.getParameterName()->isStr("weak"))
- lifetime = Qualifiers::OCL_Weak;
- else if (attr.getParameterName()->isStr("autoreleasing"))
- lifetime = Qualifiers::OCL_Autoreleasing;
- else {
- S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
- << "objc_ownership" << attr.getParameterName();
- attr.setInvalid();
- return true;
- }
- // Consume lifetime attributes without further comment outside of
- // ARC mode.
- if (!S.getLangOptions().ObjCAutoRefCount)
- return true;
- if (NonObjCPointer) {
- StringRef name = attr.getName()->getName();
- switch (lifetime) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- break;
- case Qualifiers::OCL_Strong: name = "__strong"; break;
- case Qualifiers::OCL_Weak: name = "__weak"; break;
- case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
- }
- S.Diag(AttrLoc, diag::warn_objc_object_attribute_wrong_type)
- << name << type;
- }
- Qualifiers qs;
- qs.setObjCLifetime(lifetime);
- QualType origType = type;
- if (!NonObjCPointer)
- type = S.Context.getQualifiedType(type, qs);
- // If we have a valid source location for the attribute, use an
- // AttributedType instead.
- if (AttrLoc.isValid())
- type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
- origType, type);
- // Forbid __weak if the runtime doesn't support it.
- if (lifetime == Qualifiers::OCL_Weak &&
- !S.getLangOptions().ObjCRuntimeHasWeak && !NonObjCPointer) {
- // Actually, delay this until we know what we're parsing.
- if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
- S.DelayedDiagnostics.add(
- sema::DelayedDiagnostic::makeForbiddenType(
- S.getSourceManager().getExpansionLoc(AttrLoc),
- diag::err_arc_weak_no_runtime, type, /*ignored*/ 0));
- } else {
- S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
- }
- attr.setInvalid();
- return true;
- }
-
- // Forbid __weak for class objects marked as
- // objc_arc_weak_reference_unavailable
- if (lifetime == Qualifiers::OCL_Weak) {
- QualType T = type;
- while (const PointerType *ptr = T->getAs<PointerType>())
- T = ptr->getPointeeType();
- if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
- ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
- if (Class->isArcWeakrefUnavailable()) {
- S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
- S.Diag(ObjT->getInterfaceDecl()->getLocation(),
- diag::note_class_declared);
- }
- }
- }
-
- return true;
- }
- /// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type
- /// attribute on the specified type. Returns true to indicate that
- /// the attribute was handled, false to indicate that the type does
- /// not permit the attribute.
- static bool handleObjCGCTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
- Sema &S = state.getSema();
- // Delay if this isn't some kind of pointer.
- if (!type->isPointerType() &&
- !type->isObjCObjectPointerType() &&
- !type->isBlockPointerType())
- return false;
- if (type.getObjCGCAttr() != Qualifiers::GCNone) {
- S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
- attr.setInvalid();
- return true;
- }
- // Check the attribute arguments.
- if (!attr.getParameterName()) {
- S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
- << "objc_gc" << 1;
- attr.setInvalid();
- return true;
- }
- Qualifiers::GC GCAttr;
- if (attr.getNumArgs() != 0) {
- S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- attr.setInvalid();
- return true;
- }
- if (attr.getParameterName()->isStr("weak"))
- GCAttr = Qualifiers::Weak;
- else if (attr.getParameterName()->isStr("strong"))
- GCAttr = Qualifiers::Strong;
- else {
- S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
- << "objc_gc" << attr.getParameterName();
- attr.setInvalid();
- return true;
- }
- QualType origType = type;
- type = S.Context.getObjCGCQualType(origType, GCAttr);
- // Make an attributed type to preserve the source information.
- if (attr.getLoc().isValid())
- type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
- origType, type);
- return true;
- }
- namespace {
- /// A helper class to unwrap a type down to a function for the
- /// purposes of applying attributes there.
- ///
- /// Use:
- /// FunctionTypeUnwrapper unwrapped(SemaRef, T);
- /// if (unwrapped.isFunctionType()) {
- /// const FunctionType *fn = unwrapped.get();
- /// // change fn somehow
- /// T = unwrapped.wrap(fn);
- /// }
- struct FunctionTypeUnwrapper {
- enum WrapKind {
- Desugar,
- Parens,
- Pointer,
- BlockPointer,
- Reference,
- MemberPointer
- };
- QualType Original;
- const FunctionType *Fn;
- SmallVector<unsigned char /*WrapKind*/, 8> Stack;
- FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
- while (true) {
- const Type *Ty = T.getTypePtr();
- if (isa<FunctionType>(Ty)) {
- Fn = cast<FunctionType>(Ty);
- return;
- } else if (isa<ParenType>(Ty)) {
- T = cast<ParenType>(Ty)->getInnerType();
- Stack.push_back(Parens);
- } else if (isa<PointerType>(Ty)) {
- T = cast<PointerType>(Ty)->getPointeeType();
- Stack.push_back(Pointer);
- } else if (isa<BlockPointerType>(Ty)) {
- T = cast<BlockPointerType>(Ty)->getPointeeType();
- Stack.push_back(BlockPointer);
- } else if (isa<MemberPointerType>(Ty)) {
- T = cast<MemberPointerType>(Ty)->getPointeeType();
- Stack.push_back(MemberPointer);
- } else if (isa<ReferenceType>(Ty)) {
- T = cast<ReferenceType>(Ty)->getPointeeType();
- Stack.push_back(Reference);
- } else {
- const Type *DTy = Ty->getUnqualifiedDesugaredType();
- if (Ty == DTy) {
- Fn = 0;
- return;
- }
- T = QualType(DTy, 0);
- Stack.push_back(Desugar);
- }
- }
- }
- bool isFunctionType() const { return (Fn != 0); }
- const FunctionType *get() const { return Fn; }
- QualType wrap(Sema &S, const FunctionType *New) {
- // If T wasn't modified from the unwrapped type, do nothing.
- if (New == get()) return Original;
- Fn = New;
- return wrap(S.Context, Original, 0);
- }
- private:
- QualType wrap(ASTContext &C, QualType Old, unsigned I) {
- if (I == Stack.size())
- return C.getQualifiedType(Fn, Old.getQualifiers());
- // Build up the inner type, applying the qualifiers from the old
- // type to the new type.
- SplitQualType SplitOld = Old.split();
- // As a special case, tail-recurse if there are no qualifiers.
- if (SplitOld.second.empty())
- return wrap(C, SplitOld.first, I);
- return C.getQualifiedType(wrap(C, SplitOld.first, I), SplitOld.second);
- }
- QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
- if (I == Stack.size()) return QualType(Fn, 0);
- switch (static_cast<WrapKind>(Stack[I++])) {
- case Desugar:
- // This is the point at which we potentially lose source
- // information.
- return wrap(C, Old->getUnqualifiedDesugaredType(), I);
- case Parens: {
- QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
- return C.getParenType(New);
- }
- case Pointer: {
- QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
- return C.getPointerType(New);
- }
- case BlockPointer: {
- QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
- return C.getBlockPointerType(New);
- }
- case MemberPointer: {
- const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
- QualType New = wrap(C, OldMPT->getPointeeType(), I);
- return C.getMemberPointerType(New, OldMPT->getClass());
- }
- case Reference: {
- const ReferenceType *OldRef = cast<ReferenceType>(Old);
- QualType New = wrap(C, OldRef->getPointeeType(), I);
- if (isa<LValueReferenceType>(OldRef))
- return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
- else
- return C.getRValueReferenceType(New);
- }
- }
- llvm_unreachable("unknown wrapping kind");
- return QualType();
- }
- };
- }
- /// Process an individual function attribute. Returns true to
- /// indicate that the attribute was handled, false if it wasn't.
- static bool handleFunctionTypeAttr(TypeProcessingState &state,
- AttributeList &attr,
- QualType &type) {
- Sema &S = state.getSema();
- FunctionTypeUnwrapper unwrapped(S, type);
- if (attr.getKind() == AttributeList::AT_noreturn) {
- if (S.CheckNoReturnAttr(attr))
- return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- // Otherwise we can process right away.
- FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- // ns_returns_retained is not always a type attribute, but if we got
- // here, we're treating it as one right now.
- if (attr.getKind() == AttributeList::AT_ns_returns_retained) {
- assert(S.getLangOptions().ObjCAutoRefCount &&
- "ns_returns_retained treated as type attribute in non-ARC");
- if (attr.getNumArgs()) return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- FunctionType::ExtInfo EI
- = unwrapped.get()->getExtInfo().withProducesResult(true);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- if (attr.getKind() == AttributeList::AT_regparm) {
- unsigned value;
- if (S.CheckRegparmAttr(attr, value))
- return true;
- // Delay if this is not a function type.
- if (!unwrapped.isFunctionType())
- return false;
- // Diagnose regparm with fastcall.
- const FunctionType *fn = unwrapped.get();
- CallingConv CC = fn->getCallConv();
- if (CC == CC_X86FastCall) {
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << "regparm";
- attr.setInvalid();
- return true;
- }
- FunctionType::ExtInfo EI =
- unwrapped.get()->getExtInfo().withRegParm(value);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- // Otherwise, a calling convention.
- CallingConv CC;
- if (S.CheckCallingConvAttr(attr, CC))
- return true;
- // Delay if the type didn't work out to a function.
- if (!unwrapped.isFunctionType()) return false;
- const FunctionType *fn = unwrapped.get();
- CallingConv CCOld = fn->getCallConv();
- if (S.Context.getCanonicalCallConv(CC) ==
- S.Context.getCanonicalCallConv(CCOld)) {
- FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) {
- // Should we diagnose reapplications of the same convention?
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << FunctionType::getNameForCallConv(CC)
- << FunctionType::getNameForCallConv(CCOld);
- attr.setInvalid();
- return true;
- }
- // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
- if (CC == CC_X86FastCall) {
- if (isa<FunctionNoProtoType>(fn)) {
- S.Diag(attr.getLoc(), diag::err_cconv_knr)
- << FunctionType::getNameForCallConv(CC);
- attr.setInvalid();
- return true;
- }
- const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
- if (FnP->isVariadic()) {
- S.Diag(attr.getLoc(), diag::err_cconv_varargs)
- << FunctionType::getNameForCallConv(CC);
- attr.setInvalid();
- return true;
- }
- // Also diagnose fastcall with regparm.
- if (fn->getHasRegParm()) {
- S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "regparm"
- << FunctionType::getNameForCallConv(CC);
- attr.setInvalid();
- return true;
- }
- }
- FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
- return true;
- }
- /// Handle OpenCL image access qualifiers: read_only, write_only, read_write
- static void HandleOpenCLImageAccessAttribute(QualType& CurType,
- const AttributeList &Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- Attr.setInvalid();
- return;
- }
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
- llvm::APSInt arg(32);
- if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
- !sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "opencl_image_access" << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
- switch (iarg) {
- case CLIA_read_only:
- case CLIA_write_only:
- case CLIA_read_write:
- // Implemented in a separate patch
- break;
- default:
- // Implemented in a separate patch
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- break;
- }
- }
- /// HandleVectorSizeAttribute - this attribute is only applicable to integral
- /// and float scalars, although arrays, pointers, and function return values are
- /// allowed in conjunction with this construct. Aggregates with this attribute
- /// are invalid, even if they are of the same size as a corresponding scalar.
- /// The raw attribute should contain precisely 1 argument, the vector size for
- /// the variable, measured in bytes. If curType and rawAttr are well formed,
- /// this routine will return a new vector type.
- static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
- Sema &S) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- Attr.setInvalid();
- return;
- }
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
- llvm::APSInt vecSize(32);
- if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
- !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "vector_size" << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // the base type must be integer or float, and can't already be a vector.
- if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
- Attr.setInvalid();
- return;
- }
- unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
- // vecSize is specified in bytes - convert to bits.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
- // the vector size needs to be an integral multiple of the type size.
- if (vectorSize % typeSize) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- if (vectorSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
- << sizeExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // Success! Instantiate the vector type, the number of elements is > 0, and
- // not required to be a power of 2, unlike GCC.
- CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
- VectorType::GenericVector);
- }
- /// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
- /// a type.
- static void HandleExtVectorTypeAttr(QualType &CurType,
- const AttributeList &Attr,
- Sema &S) {
- Expr *sizeExpr;
-
- // Special case where the argument is a template id.
- if (Attr.getParameterName()) {
- CXXScopeSpec SS;
- UnqualifiedId id;
- id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
-
- ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, id, false,
- false);
- if (Size.isInvalid())
- return;
-
- sizeExpr = Size.get();
- } else {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
- sizeExpr = Attr.getArg(0);
- }
-
- // Create the vector type.
- QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
- if (!T.isNull())
- CurType = T;
- }
- /// HandleNeonVectorTypeAttr - The "neon_vector_type" and
- /// "neon_polyvector_type" attributes are used to create vector types that
- /// are mangled according to ARM's ABI. Otherwise, these types are identical
- /// to those created with the "vector_size" attribute. Unlike "vector_size"
- /// the argument to these Neon attributes is the number of vector elements,
- /// not the vector size in bytes. The vector width and element type must
- /// match one of the standard Neon vector types.
- static void HandleNeonVectorTypeAttr(QualType& CurType,
- const AttributeList &Attr, Sema &S,
- VectorType::VectorKind VecKind,
- const char *AttrName) {
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- Attr.setInvalid();
- return;
- }
- // The number of elements must be an ICE.
- Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0));
- llvm::APSInt numEltsInt(32);
- if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
- !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << AttrName << numEltsExpr->getSourceRange();
- Attr.setInvalid();
- return;
- }
- // Only certain element types are supported for Neon vectors.
- const BuiltinType* BTy = CurType->getAs<BuiltinType>();
- if (!BTy ||
- (VecKind == VectorType::NeonPolyVector &&
- BTy->getKind() != BuiltinType::SChar &&
- BTy->getKind() != BuiltinType::Short) ||
- (BTy->getKind() != BuiltinType::SChar &&
- BTy->getKind() != BuiltinType::UChar &&
- BTy->getKind() != BuiltinType::Short &&
- BTy->getKind() != BuiltinType::UShort &&
- BTy->getKind() != BuiltinType::Int &&
- BTy->getKind() != BuiltinType::UInt &&
- BTy->getKind() != BuiltinType::LongLong &&
- BTy->getKind() != BuiltinType::ULongLong &&
- BTy->getKind() != BuiltinType::Float)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType;
- Attr.setInvalid();
- return;
- }
- // The total size of the vector must be 64 or 128 bits.
- unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
- unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
- unsigned vecSize = typeSize * numElts;
- if (vecSize != 64 && vecSize != 128) {
- S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
- Attr.setInvalid();
- return;
- }
- CurType = S.Context.getVectorType(CurType, numElts, VecKind);
- }
- static void processTypeAttrs(TypeProcessingState &state, QualType &type,
- bool isDeclSpec, AttributeList *attrs) {
- // Scan through and apply attributes to this type where it makes sense. Some
- // attributes (such as __address_space__, __vector_size__, etc) apply to the
- // type, but others can be present in the type specifiers even though they
- // apply to the decl. Here we apply type attributes and ignore the rest.
- AttributeList *next;
- do {
- AttributeList &attr = *attrs;
- next = attr.getNext();
- // Skip attributes that were marked to be invalid.
- if (attr.isInvalid())
- continue;
- // If this is an attribute we can handle, do so now,
- // otherwise, add it to the FnAttrs list for rechaining.
- switch (attr.getKind()) {
- default: break;
- case AttributeList::AT_may_alias:
- // FIXME: This attribute needs to actually be handled, but if we ignore
- // it it breaks large amounts of Linux software.
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_address_space:
- HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- OBJC_POINTER_TYPE_ATTRS_CASELIST:
- if (!handleObjCPointerTypeAttr(state, attr, type))
- distributeObjCPointerTypeAttr(state, attr, type);
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_vector_size:
- HandleVectorSizeAttr(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_ext_vector_type:
- if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_typedef)
- HandleExtVectorTypeAttr(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_neon_vector_type:
- HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonVector, "neon_vector_type");
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_neon_polyvector_type:
- HandleNeonVectorTypeAttr(type, attr, state.getSema(),
- VectorType::NeonPolyVector,
- "neon_polyvector_type");
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_opencl_image_access:
- HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
- attr.setUsedAsTypeAttr();
- break;
- case AttributeList::AT_ns_returns_retained:
- if (!state.getSema().getLangOptions().ObjCAutoRefCount)
- break;
- // fallthrough into the function attrs
- FUNCTION_TYPE_ATTRS_CASELIST:
- attr.setUsedAsTypeAttr();
- // Never process function type attributes as part of the
- // declaration-specifiers.
- if (isDeclSpec)
- distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
- // Otherwise, handle the possible delays.
- else if (!handleFunctionTypeAttr(state, attr, type))
- distributeFunctionTypeAttr(state, attr, type);
- break;
- }
- } while ((attrs = next));
- }
- /// \brief Ensure that the type of the given expression is complete.
- ///
- /// This routine checks whether the expression \p E has a complete type. If the
- /// expression refers to an instantiable construct, that instantiation is
- /// performed as needed to complete its type. Furthermore
- /// Sema::RequireCompleteType is called for the expression's type (or in the
- /// case of a reference type, the referred-to type).
- ///
- /// \param E The expression whose type is required to be complete.
- /// \param PD The partial diagnostic that will be printed out if the type cannot
- /// be completed.
- ///
- /// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
- /// otherwise.
- bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
- std::pair<SourceLocation,
- PartialDiagnostic> Note) {
- QualType T = E->getType();
- // Fast path the case where the type is already complete.
- if (!T->isIncompleteType())
- return false;
- // Incomplete array types may be completed by the initializer attached to
- // their definitions. For static data members of class templates we need to
- // instantiate the definition to get this initializer and complete the type.
- if (T->isIncompleteArrayType()) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember()) {
-
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- if (MSInfo->getTemplateSpecializationKind()
- != TSK_ExplicitSpecialization) {
- // If we don't already have a point of instantiation, this is it.
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- MSInfo->setPointOfInstantiation(E->getLocStart());
-
- // This is a modification of an existing AST node. Notify
- // listeners.
- if (ASTMutationListener *L = getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- }
-
- InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
-
- // Update the type to the newly instantiated definition's type both
- // here and within the expression.
- if (VarDecl *Def = Var->getDefinition()) {
- DRE->setDecl(Def);
- T = Def->getType();
- DRE->setType(T);
- E->setType(T);
- }
- }
-
- // We still go on to try to complete the type independently, as it
- // may also require instantiations or diagnostics if it remains
- // incomplete.
- }
- }
- }
- }
- // FIXME: Are there other cases which require instantiating something other
- // than the type to complete the type of an expression?
- // Look through reference types and complete the referred type.
- if (const ReferenceType *Ref = T->getAs<ReferenceType>())
- T = Ref->getPointeeType();
- return RequireCompleteType(E->getExprLoc(), T, PD, Note);
- }
- /// @brief Ensure that the type T is a complete type.
- ///
- /// This routine checks whether the type @p T is complete in any
- /// context where a complete type is required. If @p T is a complete
- /// type, returns false. If @p T is a class template specialization,
- /// this routine then attempts to perform class template
- /// instantiation. If instantiation fails, or if @p T is incomplete
- /// and cannot be completed, issues the diagnostic @p diag (giving it
- /// the type @p T) and returns true.
- ///
- /// @param Loc The location in the source that the incomplete type
- /// diagnostic should refer to.
- ///
- /// @param T The type that this routine is examining for completeness.
- ///
- /// @param PD The partial diagnostic that will be printed out if T is not a
- /// complete type.
- ///
- /// @returns @c true if @p T is incomplete and a diagnostic was emitted,
- /// @c false otherwise.
- bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD,
- std::pair<SourceLocation,
- PartialDiagnostic> Note) {
- unsigned diag = PD.getDiagID();
- // FIXME: Add this assertion to make sure we always get instantiation points.
- // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
- // FIXME: Add this assertion to help us flush out problems with
- // checking for dependent types and type-dependent expressions.
- //
- // assert(!T->isDependentType() &&
- // "Can't ask whether a dependent type is complete");
- // If we have a complete type, we're done.
- if (!T->isIncompleteType())
- return false;
- const TagType *Tag = T->getAs<TagType>();
- const ObjCInterfaceType *IFace = 0;
-
- if (Tag) {
- // Avoid diagnosing invalid decls as incomplete.
- if (Tag->getDecl()->isInvalidDecl())
- return true;
- // Give the external AST source a chance to complete the type.
- if (Tag->getDecl()->hasExternalLexicalStorage()) {
- Context.getExternalSource()->CompleteType(Tag->getDecl());
- if (!Tag->isIncompleteType())
- return false;
- }
- }
- else if ((IFace = T->getAs<ObjCInterfaceType>())) {
- // Avoid diagnosing invalid decls as incomplete.
- if (IFace->getDecl()->isInvalidDecl())
- return true;
-
- // Give the external AST source a chance to complete the type.
- if (IFace->getDecl()->hasExternalLexicalStorage()) {
- Context.getExternalSource()->CompleteType(IFace->getDecl());
- if (!IFace->isIncompleteType())
- return false;
- }
- }
-
- // If we have a class template specialization or a class member of a
- // class template specialization, or an array with known size of such,
- // try to instantiate it.
- QualType MaybeTemplate = T;
- if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T))
- MaybeTemplate = Array->getElementType();
- if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
- if (ClassTemplateSpecializationDecl *ClassTemplateSpec
- = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
- if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
- return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
- TSK_ImplicitInstantiation,
- /*Complain=*/diag != 0);
- } else if (CXXRecordDecl *Rec
- = dyn_cast<CXXRecordDecl>(Record->getDecl())) {
- if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
- MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- // This record was instantiated from a class within a template.
- if (MSInfo->getTemplateSpecializationKind()
- != TSK_ExplicitSpecialization)
- return InstantiateClass(Loc, Rec, Pattern,
- getTemplateInstantiationArgs(Rec),
- TSK_ImplicitInstantiation,
- /*Complain=*/diag != 0);
- }
- }
- }
- if (diag == 0)
- return true;
-
- // We have an incomplete type. Produce a diagnostic.
- Diag(Loc, PD) << T;
-
- // If we have a note, produce it.
- if (!Note.first.isInvalid())
- Diag(Note.first, Note.second);
-
- // If the type was a forward declaration of a class/struct/union
- // type, produce a note.
- if (Tag && !Tag->getDecl()->isInvalidDecl())
- Diag(Tag->getDecl()->getLocation(),
- Tag->isBeingDefined() ? diag::note_type_being_defined
- : diag::note_forward_declaration)
- << QualType(Tag, 0);
-
- // If the Objective-C class was a forward declaration, produce a note.
- if (IFace && !IFace->getDecl()->isInvalidDecl())
- Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
- return true;
- }
- bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD) {
- return RequireCompleteType(Loc, T, PD,
- std::make_pair(SourceLocation(), PDiag(0)));
- }
-
- bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- unsigned DiagID) {
- return RequireCompleteType(Loc, T, PDiag(DiagID),
- std::make_pair(SourceLocation(), PDiag(0)));
- }
- /// @brief Ensure that the type T is a literal type.
- ///
- /// This routine checks whether the type @p T is a literal type. If @p T is an
- /// incomplete type, an attempt is made to complete it. If @p T is a literal
- /// type, or @p AllowIncompleteType is true and @p T is an incomplete type,
- /// returns false. Otherwise, this routine issues the diagnostic @p PD (giving
- /// it the type @p T), along with notes explaining why the type is not a
- /// literal type, and returns true.
- ///
- /// @param Loc The location in the source that the non-literal type
- /// diagnostic should refer to.
- ///
- /// @param T The type that this routine is examining for literalness.
- ///
- /// @param PD The partial diagnostic that will be printed out if T is not a
- /// literal type.
- ///
- /// @param AllowIncompleteType If true, an incomplete type will be considered
- /// acceptable.
- ///
- /// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
- /// @c false otherwise.
- bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD,
- bool AllowIncompleteType) {
- assert(!T->isDependentType() && "type should not be dependent");
- bool Incomplete = RequireCompleteType(Loc, T, 0);
- if (T->isLiteralType() || (AllowIncompleteType && Incomplete))
- return false;
- if (PD.getDiagID() == 0)
- return true;
- Diag(Loc, PD) << T;
- if (T->isVariableArrayType())
- return true;
- const RecordType *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>();
- if (!RT)
- return true;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- // If the class has virtual base classes, then it's not an aggregate, and
- // cannot have any constexpr constructors, so is non-literal. This is better
- // to diagnose than the resulting absence of constexpr constructors.
- if (RD->getNumVBases()) {
- Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
- << RD->isStruct() << RD->getNumVBases();
- for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
- E = RD->vbases_end(); I != E; ++I)
- Diag(I->getSourceRange().getBegin(),
- diag::note_constexpr_virtual_base_here) << I->getSourceRange();
- } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor()) {
- Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
- switch (RD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- break;
- case TSK_ImplicitInstantiation:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- // If the base template had constexpr constructors which were
- // instantiated as non-constexpr constructors, explain why.
- for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
- E = RD->ctor_end(); I != E; ++I) {
- if ((*I)->isCopyConstructor() || (*I)->isMoveConstructor())
- continue;
- FunctionDecl *Base = (*I)->getInstantiatedFromMemberFunction();
- if (Base && Base->isConstexpr())
- CheckConstexprFunctionDecl(*I, CCK_NoteNonConstexprInstantiation);
- }
- }
- } else if (RD->hasNonLiteralTypeFieldsOrBases()) {
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- if (!I->getType()->isLiteralType()) {
- Diag(I->getSourceRange().getBegin(),
- diag::note_non_literal_base_class)
- << RD << I->getType() << I->getSourceRange();
- return true;
- }
- }
- for (CXXRecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end(); I != E; ++I) {
- if (!(*I)->getType()->isLiteralType()) {
- Diag((*I)->getLocation(), diag::note_non_literal_field)
- << RD << (*I) << (*I)->getType();
- return true;
- } else if ((*I)->isMutable()) {
- Diag((*I)->getLocation(), diag::note_non_literal_mutable_field) << RD;
- return true;
- }
- }
- } else if (!RD->hasTrivialDestructor()) {
- // All fields and bases are of literal types, so have trivial destructors.
- // If this class's destructor is non-trivial it must be user-declared.
- CXXDestructorDecl *Dtor = RD->getDestructor();
- assert(Dtor && "class has literal fields and bases but no dtor?");
- if (!Dtor)
- return true;
- Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
- diag::note_non_literal_user_provided_dtor :
- diag::note_non_literal_nontrivial_dtor) << RD;
- }
- return true;
- }
- /// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
- /// and qualified by the nested-name-specifier contained in SS.
- QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T) {
- if (T.isNull())
- return T;
- NestedNameSpecifier *NNS;
- if (SS.isValid())
- NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- else {
- if (Keyword == ETK_None)
- return T;
- NNS = 0;
- }
- return Context.getElaboratedType(Keyword, NNS, T);
- }
- QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
- ExprResult ER = CheckPlaceholderExpr(E);
- if (ER.isInvalid()) return QualType();
- E = ER.take();
- if (!E->isTypeDependent()) {
- QualType T = E->getType();
- if (const TagType *TT = T->getAs<TagType>())
- DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
- }
- return Context.getTypeOfExprType(E);
- }
- QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
- ExprResult ER = CheckPlaceholderExpr(E);
- if (ER.isInvalid()) return QualType();
- E = ER.take();
-
- return Context.getDecltypeType(E);
- }
- QualType Sema::BuildUnaryTransformType(QualType BaseType,
- UnaryTransformType::UTTKind UKind,
- SourceLocation Loc) {
- switch (UKind) {
- case UnaryTransformType::EnumUnderlyingType:
- if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
- Diag(Loc, diag::err_only_enums_have_underlying_types);
- return QualType();
- } else {
- QualType Underlying = BaseType;
- if (!BaseType->isDependentType()) {
- EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
- assert(ED && "EnumType has no EnumDecl");
- DiagnoseUseOfDecl(ED, Loc);
- Underlying = ED->getIntegerType();
- }
- assert(!Underlying.isNull());
- return Context.getUnaryTransformType(BaseType, Underlying,
- UnaryTransformType::EnumUnderlyingType);
- }
- }
- llvm_unreachable("unknown unary transform type");
- }
- QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
- if (!T->isDependentType()) {
- int DisallowedKind = -1;
- if (T->isIncompleteType())
- // FIXME: It isn't entirely clear whether incomplete atomic types
- // are allowed or not; for simplicity, ban them for the moment.
- DisallowedKind = 0;
- else if (T->isArrayType())
- DisallowedKind = 1;
- else if (T->isFunctionType())
- DisallowedKind = 2;
- else if (T->isReferenceType())
- DisallowedKind = 3;
- else if (T->isAtomicType())
- DisallowedKind = 4;
- else if (T.hasQualifiers())
- DisallowedKind = 5;
- else if (!T.isTriviallyCopyableType(Context))
- // Some other non-trivially-copyable type (probably a C++ class)
- DisallowedKind = 6;
- if (DisallowedKind != -1) {
- Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
- return QualType();
- }
- // FIXME: Do we need any handling for ARC here?
- }
- // Build the pointer type.
- return Context.getAtomicType(T);
- }
|